internal void PrepareForBind(
            OracleConnection connection,
            ref int offset
            )
        {
            OracleParameter parameter = Parameter;

            // Don't bother with parameters where the user asks for the default value.
            if (!IsDirection(parameter, ParameterDirection.Output) && null == parameter.Value)
            {
                _bufferLengthInBytes = 0;
                return;
            }

            _bindingMetaType = parameter.GetMetaType();

            // We currently don't support binding a REF CURSOR as an input parameter; that
            // is for a future release.
            if (OCI.DATATYPE.RSET == _bindingMetaType.OciType && ParameterDirection.Output != parameter.Direction)
            {
                throw ADP.InputRefCursorNotSupported(parameter.ParameterName);
            }

            // Make sure we have a coerced value, if we haven't already done
            // so, then save it.
            parameter.SetCoercedValue(_bindingMetaType.BaseType, _bindingMetaType.NoConvertType);
            _coercedValue = parameter.CoercedValue;

            // When they're binding a LOB type, but not providing a LOB object,
            // we have to change the binding under the covers so we aren't forced
            // to create a temporary LOB.
            switch (_bindingMetaType.OciType)
            {
            case OCI.DATATYPE.BFILE:
            case OCI.DATATYPE.BLOB:
            case OCI.DATATYPE.CLOB:
                if (!ADP.IsNull(_coercedValue) && !(_coercedValue is OracleLob || _coercedValue is OracleBFile))
                {
                    _bindingMetaType = MetaType.GetMetaTypeForType(_bindingMetaType.DbType);
                }

                break;
            }

            // For fixed-width types, we take the bind size from the meta type
            // information; if it's zero, then the type must be variable width
            // (or it's an output parameter) and we require that they specify a
            // size.

            _bufferLength = _bindingMetaType.BindSize;

            if ((IsDirection(parameter, ParameterDirection.Output) &&
                 _bindingMetaType.IsVariableLength) ||                  // they must specify a size for variable-length output parameters...
                (0 == _bufferLength && !ADP.IsNull(_coercedValue)) ||   // ...or if it's a non-null, variable-length input paramter...
                (_bufferLength > short.MaxValue))                       // ...or if the parameter type's maximum size is huge.
            {
                int size = parameter.BindSize;

                if (0 != size)
                {
                    _bufferLength = size;
                }

                if (0 == _bufferLength || MetaType.LongMax == _bufferLength)
                {
                    throw ADP.ParameterSizeIsMissing(parameter.ParameterName, _bindingMetaType.BaseType);
                }
            }

            _bufferLengthInBytes = _bufferLength;

            if (_bindingMetaType.IsCharacterType && connection.ServerVersionAtLeastOracle8)
            {
                _bindAsUCS2           = true;
                _bufferLengthInBytes *= ADP.CharSize;
            }

            // Anything with a length that exceeds what fits into a two-byte integer
            // requires special binding because the base types don't allow more than
            // 65535 bytes.  We change the binding under the covers to reflect the
            // different type.

            if (!ADP.IsNull(_coercedValue) &&
                _bufferLength > _bindingMetaType.MaxBindSize)
            {
                // DEVNOTE: it is perfectly fine to bind values less than 65535 bytes
                //          as long, so there's no problem with using the maximum number
                //          of bytes for each Unicode character above.

                switch (_bindingMetaType.OciType)
                {
                case OCI.DATATYPE.CHAR:
                case OCI.DATATYPE.LONG:
                case OCI.DATATYPE.VARCHAR2:
                    _bindingMetaType = (_bindingMetaType.UsesNationalCharacterSet)
                                                ? MetaType.oracleTypeMetaType_LONGNVARCHAR
                                                : MetaType.oracleTypeMetaType_LONGVARCHAR;
                    break;

                case OCI.DATATYPE.RAW:
                case OCI.DATATYPE.LONGRAW:
                    _bindingMetaType = MetaType.oracleTypeMetaType_LONGVARRAW;
                    break;

                default:
                    Debug.Assert(false, "invalid type for long binding!");      // this should never happen!
                    break;
                }

                // Long data requires a LONGVARCHAR or LONGVARRAW binding instead, which
                // mean we have to add another 4 bytes for the length.
                _bufferLengthInBytes += 4;
            }

            if (0 > _bufferLengthInBytes)
            {
                throw ADP.ParameterSizeIsTooLarge(parameter.ParameterName);
            }

            // Fill in the buffer offsets. We lay out the buffer as follows:
            //
            //      indicator   0-3
            //      length      4-7
            //      data        8-...
            //
            _indicatorOffset = offset;   offset += 4;
            _lengthOffset    = offset;   offset += 4;
            _valueOffset     = offset;   offset += _bufferLengthInBytes;

            offset = (offset + 3) & ~0x3;   // DWORD align, please.
        }
        internal void PrepareForBind(OracleConnection connection, ref int offset)
        {
            OracleParameter parameter = this.Parameter;
            bool            flag      = false;
            object          obj2      = parameter.Value;

            if (!IsDirection(parameter, ParameterDirection.Output) && (obj2 == null))
            {
                this._bufferLength = 0;
            }
            else
            {
                this._bindingMetaType = parameter.GetMetaType(obj2);
                if ((OCI.DATATYPE.RSET == this._bindingMetaType.OciType) && System.Data.Common.ADP.IsDirection(parameter.Direction, ParameterDirection.Input))
                {
                    throw System.Data.Common.ADP.InputRefCursorNotSupported(parameter.ParameterName);
                }
                parameter.SetCoercedValueInternal(obj2, this._bindingMetaType);
                this._coercedValue = parameter.GetCoercedValueInternal();
                switch (this._bindingMetaType.OciType)
                {
                case OCI.DATATYPE.CLOB:
                case OCI.DATATYPE.BLOB:
                case OCI.DATATYPE.BFILE:
                    if ((!System.Data.Common.ADP.IsNull(this._coercedValue) && !(this._coercedValue is OracleLob)) && !(this._coercedValue is OracleBFile))
                    {
                        if (!connection.HasTransaction)
                        {
                            this._bindingMetaType = MetaType.GetMetaTypeForType(this._bindingMetaType.DbType);
                            flag = true;
                            break;
                        }
                        this._freeTemporaryLob = true;
                        this._coercedValue     = this.CreateTemporaryLobForValue(connection, this._bindingMetaType.OracleType, this._coercedValue);
                    }
                    break;
                }
                this._bindSize = this._bindingMetaType.BindSize;
                if (((IsDirection(parameter, ParameterDirection.Output) && this._bindingMetaType.IsVariableLength) || ((this._bindSize == 0) && !System.Data.Common.ADP.IsNull(this._coercedValue))) || (this._bindSize > 0x7fff))
                {
                    int bindSize = parameter.BindSize;
                    if (bindSize != 0)
                    {
                        this._bindSize = bindSize;
                    }
                    if (((this._bindSize == 0) || (0x7fffffff == this._bindSize)) && !this.IsEmpty(this._coercedValue))
                    {
                        throw System.Data.Common.ADP.ParameterSizeIsMissing(parameter.ParameterName, this._bindingMetaType.BaseType);
                    }
                }
                this._bufferLength = this._bindSize;
                if (this._bindingMetaType.IsCharacterType && connection.ServerVersionAtLeastOracle8)
                {
                    this._bindAsUCS2    = true;
                    this._bufferLength *= System.Data.Common.ADP.CharSize;
                }
                if (!System.Data.Common.ADP.IsNull(this._coercedValue) && ((this._bindSize > this._bindingMetaType.MaxBindSize) || flag))
                {
                    switch (this._bindingMetaType.OciType)
                    {
                    case OCI.DATATYPE.RAW:
                    case OCI.DATATYPE.LONGRAW:
                        this._bindingMetaType = MetaType.oracleTypeMetaType_LONGVARRAW;
                        break;

                    case OCI.DATATYPE.CHAR:
                    case OCI.DATATYPE.VARCHAR2:
                    case OCI.DATATYPE.LONG:
                        this._bindingMetaType = this._bindingMetaType.UsesNationalCharacterSet ? MetaType.oracleTypeMetaType_LONGNVARCHAR : MetaType.oracleTypeMetaType_LONGVARCHAR;
                        break;
                    }
                    this._bufferLength += 4;
                }
                if (0 > this._bufferLength)
                {
                    throw System.Data.Common.ADP.ParameterSizeIsTooLarge(parameter.ParameterName);
                }
                this._indicatorOffset = offset;
                offset            += IntPtr.Size;
                this._lengthOffset = offset;
                offset            += IntPtr.Size;
                this._valueOffset  = offset;
                offset            += this._bufferLength;
                offset             = (offset + (IntPtr.Size - 1)) & ~(IntPtr.Size - 1);
            }
        }
        internal static OracleString GetPersistedRowid(OracleConnection connection, OciRowidDescriptor rowidHandle)
        {
            OracleString @null = OracleString.Null;

            if (rowidHandle != null)
            {
                OciErrorHandle errorHandle   = connection.ErrorHandle;
                NativeBuffer   scratchBuffer = connection.GetScratchBuffer(0xf82);
                bool           success       = false;
                bool           flag          = false;
                RuntimeHelpers.PrepareConstrainedRegions();
                try
                {
                    int num;
                    scratchBuffer.DangerousAddRef(ref success);
                    if (OCI.ClientVersionAtLeastOracle9i)
                    {
                        int length = scratchBuffer.Length;
                        num = TracedNativeMethods.OCIRowidToChar(rowidHandle, scratchBuffer, ref length, errorHandle);
                        if (num != 0)
                        {
                            connection.CheckError(errorHandle, num);
                        }
                        return(new OracleString(scratchBuffer.PtrToStringAnsi(0, length)));
                    }
                    rowidHandle.DangerousAddRef(ref flag);
                    OciServiceContextHandle serviceContextHandle = connection.ServiceContextHandle;
                    OciStatementHandle      stmtp = new OciStatementHandle(serviceContextHandle);
                    string stmt   = "begin :rowid := :rdesc; end;";
                    int    offset = 0;
                    int    num6   = 4;
                    int    num5   = 8;
                    int    num3   = 12;
                    int    num2   = 0x10;
                    int    num4   = 20;
                    try
                    {
                        IntPtr ptr;
                        IntPtr ptr2;
                        num = TracedNativeMethods.OCIStmtPrepare(stmtp, errorHandle, stmt, OCI.SYNTAX.OCI_NTV_SYNTAX, OCI.MODE.OCI_DEFAULT, connection);
                        if (num != 0)
                        {
                            connection.CheckError(errorHandle, num);
                        }
                        scratchBuffer.WriteIntPtr(num5, rowidHandle.DangerousGetHandle());
                        scratchBuffer.WriteInt32(offset, 0);
                        scratchBuffer.WriteInt32(num6, 4);
                        scratchBuffer.WriteInt32(num3, 0);
                        scratchBuffer.WriteInt32(num2, 0xf6e);
                        num = TracedNativeMethods.OCIBindByName(stmtp, out ptr2, errorHandle, "rowid", 5, scratchBuffer.DangerousGetDataPtr(num4), 0xf6e, OCI.DATATYPE.VARCHAR2, scratchBuffer.DangerousGetDataPtr(num3), scratchBuffer.DangerousGetDataPtr(num2), OCI.MODE.OCI_DEFAULT);
                        if (num != 0)
                        {
                            connection.CheckError(errorHandle, num);
                        }
                        num = TracedNativeMethods.OCIBindByName(stmtp, out ptr, errorHandle, "rdesc", 5, scratchBuffer.DangerousGetDataPtr(num5), 4, OCI.DATATYPE.ROWID_DESC, scratchBuffer.DangerousGetDataPtr(offset), scratchBuffer.DangerousGetDataPtr(num6), OCI.MODE.OCI_DEFAULT);
                        if (num != 0)
                        {
                            connection.CheckError(errorHandle, num);
                        }
                        num = TracedNativeMethods.OCIStmtExecute(serviceContextHandle, stmtp, errorHandle, 1, OCI.MODE.OCI_DEFAULT);
                        if (num != 0)
                        {
                            connection.CheckError(errorHandle, num);
                        }
                        if (scratchBuffer.ReadInt16(num3) == -1)
                        {
                            return(@null);
                        }
                        @null = new OracleString(scratchBuffer, num4, num2, MetaType.GetMetaTypeForType(OracleType.RowId), connection, false, true);
                        GC.KeepAlive(rowidHandle);
                    }
                    finally
                    {
                        OciHandle.SafeDispose(ref stmtp);
                    }
                }
                finally
                {
                    if (flag)
                    {
                        rowidHandle.DangerousRelease();
                    }
                    if (success)
                    {
                        scratchBuffer.DangerousRelease();
                    }
                }
            }
            return(@null);
        }
예제 #4
0
        internal bool Describe(ref int offset, OracleConnection connection, OciErrorHandle errorHandle)
        {
            byte  num;
            short num3;
            bool  flag  = false;
            bool  flag2 = false;

            this._describeHandle.GetAttribute(OCI.ATTR.OCI_ATTR_SQLCODE, out this._columnName, errorHandle, this._connection);
            this._describeHandle.GetAttribute(OCI.ATTR.OCI_ATTR_OBJECT, out num3, errorHandle);
            this._describeHandle.GetAttribute(OCI.ATTR.OCI_ATTR_SESSION, out num, errorHandle);
            this._isNullable = 0 != num;
            OCI.DATATYPE ociType = (OCI.DATATYPE)num3;
            switch (ociType)
            {
            case OCI.DATATYPE.VARCHAR2:
            case OCI.DATATYPE.CHAR:
            {
                int num2;
                this._describeHandle.GetAttribute(OCI.ATTR.OCI_ATTR_FNCODE, out this._byteSize, errorHandle);
                this._describeHandle.GetAttribute(OCI.ATTR.OCI_ATTR_CHARSET_FORM, out num, errorHandle);
                OCI.CHARSETFORM charsetform = (OCI.CHARSETFORM)num;
                this._bindAsUTF16 = connection.ServerVersionAtLeastOracle8;
                if (connection.ServerVersionAtLeastOracle9i && OCI.ClientVersionAtLeastOracle9i)
                {
                    this._describeHandle.GetAttribute(OCI.ATTR.OCI_ATTR_CHAR_SIZE, out num3, errorHandle);
                    num2 = num3;
                }
                else
                {
                    num2 = this._byteSize;
                }
                if (charsetform == OCI.CHARSETFORM.SQLCS_NCHAR)
                {
                    this._metaType = MetaType.GetMetaTypeForType((OCI.DATATYPE.CHAR == ociType) ? System.Data.OracleClient.OracleType.NChar : System.Data.OracleClient.OracleType.NVarChar);
                }
                else
                {
                    this._metaType = MetaType.GetMetaTypeForType((OCI.DATATYPE.CHAR == ociType) ? System.Data.OracleClient.OracleType.Char : System.Data.OracleClient.OracleType.VarChar);
                    if (this._bindAsUTF16)
                    {
                        this._byteSize *= System.Data.Common.ADP.CharSize;
                    }
                }
                this._byteSize = Math.Max(this._byteSize, num2 * System.Data.Common.ADP.CharSize);
                flag           = true;
                break;
            }

            case OCI.DATATYPE.NUMBER:
                this._metaType = MetaType.GetMetaTypeForType(System.Data.OracleClient.OracleType.Number);
                this._byteSize = this._metaType.BindSize;
                this._describeHandle.GetAttribute(OCI.ATTR.OCI_ATTR_ENV, out this._precision, errorHandle);
                this._describeHandle.GetAttribute(OCI.ATTR.OCI_ATTR_SERVER, out this._scale, errorHandle);
                break;

            case OCI.DATATYPE.LONG:
                this._metaType    = MetaType.GetMetaTypeForType(System.Data.OracleClient.OracleType.LongVarChar);
                this._byteSize    = this._metaType.BindSize;
                flag              = true;
                flag2             = true;
                this._bindAsUTF16 = connection.ServerVersionAtLeastOracle8;
                break;

            case OCI.DATATYPE.ROWID:
            case OCI.DATATYPE.ROWID_DESC:
            case OCI.DATATYPE.UROWID:
                this._metaType = MetaType.GetMetaTypeForType(System.Data.OracleClient.OracleType.RowId);
                this._byteSize = this._metaType.BindSize;
                if (connection.UnicodeEnabled)
                {
                    this._bindAsUTF16 = true;
                    this._byteSize   *= System.Data.Common.ADP.CharSize;
                }
                flag = true;
                break;

            case OCI.DATATYPE.DATE:
                this._metaType = MetaType.GetMetaTypeForType(System.Data.OracleClient.OracleType.DateTime);
                this._byteSize = this._metaType.BindSize;
                flag           = true;
                break;

            case OCI.DATATYPE.RAW:
                this._metaType = MetaType.GetMetaTypeForType(System.Data.OracleClient.OracleType.Raw);
                this._describeHandle.GetAttribute(OCI.ATTR.OCI_ATTR_FNCODE, out this._byteSize, errorHandle);
                flag = true;
                break;

            case OCI.DATATYPE.LONGRAW:
                this._metaType = MetaType.GetMetaTypeForType(System.Data.OracleClient.OracleType.LongRaw);
                this._byteSize = this._metaType.BindSize;
                flag           = true;
                flag2          = true;
                break;

            case OCI.DATATYPE.CLOB:
                this._describeHandle.GetAttribute(OCI.ATTR.OCI_ATTR_CHARSET_FORM, out num, errorHandle);
                this._metaType = MetaType.GetMetaTypeForType((2 == num) ? System.Data.OracleClient.OracleType.NClob : System.Data.OracleClient.OracleType.Clob);
                this._byteSize = this._metaType.BindSize;
                flag2          = true;
                break;

            case OCI.DATATYPE.BLOB:
                this._metaType = MetaType.GetMetaTypeForType(System.Data.OracleClient.OracleType.Blob);
                this._byteSize = this._metaType.BindSize;
                flag2          = true;
                break;

            case OCI.DATATYPE.BFILE:
                this._metaType = MetaType.GetMetaTypeForType(System.Data.OracleClient.OracleType.BFile);
                this._byteSize = this._metaType.BindSize;
                flag2          = true;
                break;

            case OCI.DATATYPE.TIMESTAMP:
                this._metaType = MetaType.GetMetaTypeForType(System.Data.OracleClient.OracleType.Timestamp);
                this._byteSize = this._metaType.BindSize;
                flag           = true;
                break;

            case OCI.DATATYPE.TIMESTAMP_TZ:
                this._metaType = MetaType.GetMetaTypeForType(System.Data.OracleClient.OracleType.TimestampWithTZ);
                this._byteSize = this._metaType.BindSize;
                flag           = true;
                break;

            case OCI.DATATYPE.INTERVAL_YM:
                this._metaType = MetaType.GetMetaTypeForType(System.Data.OracleClient.OracleType.IntervalYearToMonth);
                this._byteSize = this._metaType.BindSize;
                break;

            case OCI.DATATYPE.INTERVAL_DS:
                this._metaType = MetaType.GetMetaTypeForType(System.Data.OracleClient.OracleType.IntervalDayToSecond);
                this._byteSize = this._metaType.BindSize;
                break;

            case OCI.DATATYPE.TIMESTAMP_LTZ:
                this._metaType = MetaType.GetMetaTypeForType(System.Data.OracleClient.OracleType.TimestampLocal);
                this._byteSize = this._metaType.BindSize;
                flag           = true;
                break;

            default:
                throw System.Data.Common.ADP.TypeNotSupported(ociType);
            }
            if (this._isNullable)
            {
                this._indicatorOffset = offset;
                offset += IntPtr.Size;
            }
            else
            {
                this._indicatorOffset = -1;
            }
            if (flag)
            {
                this._lengthOffset = offset;
                offset            += IntPtr.Size;
            }
            else
            {
                this._lengthOffset = -1;
            }
            this._valueOffset = offset;
            if ((OCI.DATATYPE.LONG == ociType) || (OCI.DATATYPE.LONGRAW == ociType))
            {
                offset += IntPtr.Size;
            }
            else
            {
                offset += this._byteSize;
            }
            offset = (offset + (IntPtr.Size - 1)) & ~(IntPtr.Size - 1);
            OciHandle.SafeDispose(ref this._describeHandle);
            return(flag2);
        }