Пример #1
0
        internal void Bind(
            OciHandle statementHandle,
            NativeBuffer buffer,
            OciHandle errorHandle,
            int rowBufferLength
            )
        {
            //  Binds the buffer for the column to the statement handle specified.

            OciHandle defineHandle = null;
            IntPtr    h;

            OCI.MODE mode = OCI.MODE.OCI_DEFAULT;
            int      bindSize;

            OCI.DATATYPE ociType = _metaType.OciType;

            _rowBuffer = buffer;

            if (_metaType.IsLong)
            {
                mode     = OCI.MODE.OCI_DYNAMIC_FETCH;
                bindSize = Int32.MaxValue;
            }
            else
            {
                bindSize = _size;
            }

            HandleRef indicatorLocation = ADP.NullHandleRef;
            HandleRef lengthLocation    = ADP.NullHandleRef;
            HandleRef valueLocation     = _rowBuffer.PtrOffset(_valueOffset);

            if (-1 != _indicatorOffset)
            {
                indicatorLocation = _rowBuffer.PtrOffset(_indicatorOffset);
            }

            if (-1 != _lengthOffset && !_metaType.IsLong)
            {
                lengthLocation = _rowBuffer.PtrOffset(_lengthOffset);
            }

            try
            {
                try
                {
                    int rc = TracedNativeMethods.OCIDefineByPos(
                        statementHandle,                                    // hndlp
                        out h,                                              // defnpp
                        errorHandle,                                        // errhp
                        _ordinal + 1,                                       // position
                        valueLocation,                                      // valuep
                        bindSize,                                           // value_sz
                        ociType,                                            // htype
                        indicatorLocation,                                  // indp,
                        lengthLocation,                                     // rlenp,
                        ADP.NullHandleRef,                                  // rcodep,
                        mode                                                // mode
                        );
                    if (rc != 0)
                    {
                        _connection.CheckError(errorHandle, rc);
                    }

                    defineHandle = new OciDefineHandle(statementHandle, h);

                    if (0 != rowBufferLength)
                    {
                        int valOffset = rowBufferLength;
                        int indOffset = (-1 != _indicatorOffset) ? rowBufferLength : 0;
                        int lenOffset = (-1 != _lengthOffset && !_metaType.IsLong) ? rowBufferLength : 0;

                        rc = TracedNativeMethods.OCIDefineArrayOfStruct(
                            defineHandle,
                            errorHandle,
                            valOffset,
                            indOffset,
                            lenOffset,
                            0                            // never use rcodep above...
                            );
                        if (rc != 0)
                        {
                            _connection.CheckError(errorHandle, rc);
                        }
                    }

                    if (!_connection.UnicodeEnabled)
                    {
                        if (_metaType.UsesNationalCharacterSet)
                        {
                            Debug.Assert(!_metaType.IsLong, "LONG data may never be bound as NCHAR");
                            // NOTE:    the order is important here; setting charsetForm will
                            //          reset charsetId (I found this out the hard way...)
                            defineHandle.SetAttribute(OCI.ATTR.OCI_ATTR_CHARSET_FORM, (int)OCI.CHARSETFORM.SQLCS_NCHAR, errorHandle);
                        }
                        if (_bindAsUCS2)
                        {
                            // NOTE:    the order is important here; setting charsetForm will
                            //          reset charsetId (I found this out the hard way...)
                            defineHandle.SetAttribute(OCI.ATTR.OCI_ATTR_CHARSET_ID, OCI.OCI_UCS2ID, errorHandle);
                        }
                    }
                    if (_metaType.IsLong)
                    {
                        // Initialize the longBuffer in the rowBuffer to null
                        Marshal.WriteIntPtr((IntPtr)_rowBuffer.PtrOffset(_valueOffset), IntPtr.Zero);

                        if (null != _longBuffer)
                        {
                            _longBuffer.Dispose();
                            _longBuffer = null;
                        }

                        // We require MTxOCI8 to be in the path somewhere for us to handle LONG data
                        if (!OCI.IsNewMtxOci8Installed)
#if EVERETT
                        { throw ADP.MustInstallNewMtxOciLONG(); }
#else //!EVERETT        {
                            throw ADP.MustInstallNewMtxOci();
                        }
#endif //!EVERETT
                        _callback = new OCI.Callback.OCICallbackDefine(_callback_GetColumnPiecewise);

                        rc = TracedNativeMethods.MTxOciDefineDynamic(
                            defineHandle,                               // defnp
                            errorHandle,                                // errhp
                            ADP.NullHandleRef,                          // dvoid *octxp,
                            _callback                                   // OCICallbackDefine ocbfp
                            );
                        if (rc != 0)
                        {
                            _connection.CheckError(errorHandle, rc);
                        }
                    }
                }
                finally
                {
                    // We don't need this any longer, get rid of it.
                    OciHandle.SafeDispose(ref defineHandle);
                }
            }