Example #1
0
        T DoRead <T>(TypeHandler handler)
        {
            ReadColumnLenIfNeeded();
            if (_columnLen == -1)
            {
                // TODO: What actual exception to throw here? Oracle throws InvalidCast, SqlClient throws its
                // own SqlNullValueException
                throw new InvalidCastException("Column is null");
            }

            var result = handler.Read <T>(_buf, _columnLen);

            _leftToReadInDataMsg -= _columnLen;
            _columnLen            = int.MinValue; // Mark that the (next) column length hasn't been read yet
            _column++;
            return(result);
        }
Example #2
0
        void ActivateEnumType(TypeHandler handler, BackendType backendType)
        {
            handler.PgName                  = backendType.Name;
            handler.OID                     = backendType.OID;
            handler.NpgsqlDbType            = NpgsqlDbType.Enum;
            _oidIndex[backendType.OID]      = handler;
            _byType[handler.GetFieldType()] = handler;

            if (backendType.ArrayOID != 0)
            {
                var arrayHandler = RegisterArrayType(backendType.ArrayOID, handler, backendType.ArrayTextDelimiter);
                if (_byEnumTypeAsArray == null)
                {
                    _byEnumTypeAsArray = new Dictionary <Type, TypeHandler>();
                }
                var enumType = handler.GetType().GetGenericArguments()[0];
                Contract.Assert(enumType.IsEnum);
                _byEnumTypeAsArray[enumType] = arrayHandler;
            }
        }
Example #3
0
 void DoWrite <T>(TypeHandler handler, [CanBeNull] T value)
 {
     try
     {
         // We simulate the regular writing process with a validation/length calculation pass,
         // followed by a write pass
         _dummyParam.ConvertedValue = null;
         _lengthCache.Clear();
         handler.ValidateAndGetLength(value, ref _lengthCache, _dummyParam);
         _lengthCache.Rewind();
         handler.WriteWithLength(value, _buf, _lengthCache, _dummyParam, false, CancellationToken.None);
         _column++;
     }
     catch
     {
         _connector.Break();
         Cleanup();
         throw;
     }
 }
Example #4
0
        T DoRead <T>(TypeHandler handler)
        {
            try {
                ReadColumnLenIfNeeded();
                if (_columnLen == -1)
                {
                    throw new InvalidCastException("Column is null");
                }

                var result = handler.ReadFully <T>(_buf, _columnLen);
                _leftToReadInDataMsg -= _columnLen;
                _columnLen            = int.MinValue; // Mark that the (next) column length hasn't been read yet
                _column++;
                return(result);
            } catch {
                _connector.Break();
                Cleanup();
                throw;
            }
        }
Example #5
0
        void DoWrite <T>(TypeHandler handler, T value)
        {
            if (_buf.WriteSpaceLeft < 4)
            {
                Flush();
            }
            EnsureDataMessage();

            var asObject = (object)value;   // TODO: Implement boxless writing in the future

            if (asObject == null)
            {
                _buf.WriteInt32(-1);
                _column++;
                return;
            }

            var asSimple = handler as ISimpleTypeWriter;

            if (asSimple != null)
            {
                var len = asSimple.ValidateAndGetLength(asObject);
                _buf.WriteInt32(len);
                if (_buf.WriteSpaceLeft < len)
                {
                    Contract.Assume(_buf.Size >= len);
                    FlushAndStartDataMessage();
                }
                asSimple.Write(asObject, _buf);
                _column++;
                return;
            }

            var asChunking = handler as IChunkingTypeWriter;

            if (asChunking != null)
            {
                _lengthCache.Clear();
                var len = asChunking.ValidateAndGetLength(asObject, ref _lengthCache);
                _buf.WriteInt32(len);
                _lengthCache.Rewind();
                _lengthCache.Get();  // Hack
                asChunking.PrepareWrite(asObject, _buf, _lengthCache);
                var directBuf = new DirectBuffer();
                while (!asChunking.Write(ref directBuf))
                {
                    FlushAndStartDataMessage();

                    // The following is an optimization hack for writing large byte arrays without passing
                    // through our buffer
                    if (directBuf.Buffer != null)
                    {
                        len = directBuf.Size == 0 ? directBuf.Buffer.Length : directBuf.Size;
                        _buf.WriteInt32(len);
                        Flush();
                        _buf.Underlying.Write(directBuf.Buffer, directBuf.Offset, len);
                        directBuf.Buffer = null;
                        directBuf.Size   = 0;
                    }
                }
                _column++;
                return;
            }

            throw PGUtil.ThrowIfReached();
        }
        void DoWrite <T>(TypeHandler handler, T value)
        {
            try
            {
                if (_buf.WriteSpaceLeft < 4)
                {
                    FlushAndStartDataMessage();
                }

                var asObject = (object)value;  // TODO: Implement boxless writing in the future
                if (asObject == null)
                {
                    _buf.WriteInt32(-1);
                    _column++;
                    return;
                }

                _dummyParam.ConvertedValue = null;

                var asSimple = handler as ISimpleTypeWriter;
                if (asSimple != null)
                {
                    var len = asSimple.ValidateAndGetLength(asObject, _dummyParam);
                    _buf.WriteInt32(len);
                    if (_buf.WriteSpaceLeft < len)
                    {
                        Contract.Assume(_buf.Size >= len);
                        FlushAndStartDataMessage();
                    }
                    asSimple.Write(asObject, _buf, _dummyParam);
                    _column++;
                    return;
                }

                var asChunking = handler as IChunkingTypeWriter;
                if (asChunking != null)
                {
                    _lengthCache.Clear();
                    var len = asChunking.ValidateAndGetLength(asObject, ref _lengthCache, _dummyParam);
                    _buf.WriteInt32(len);

                    // If the type handler used the length cache, rewind it to skip the first position:
                    // it contains the entire value length which we already have in len.
                    if (_lengthCache.Position > 0)
                    {
                        _lengthCache.Rewind();
                        _lengthCache.Position++;
                    }

                    asChunking.PrepareWrite(asObject, _buf, _lengthCache, _dummyParam);
                    var directBuf = new DirectBuffer();
                    while (!asChunking.Write(ref directBuf))
                    {
                        Flush();

                        // The following is an optimization hack for writing large byte arrays without passing
                        // through our buffer
                        if (directBuf.Buffer != null)
                        {
                            len = directBuf.Size == 0 ? directBuf.Buffer.Length : directBuf.Size;
                            _buf.WritePosition = 1;
                            _buf.WriteInt32(len + 4);
                            _buf.Flush();
                            _writingDataMsg = false;
                            _buf.Underlying.Write(directBuf.Buffer, directBuf.Offset, len);
                            directBuf.Buffer = null;
                            directBuf.Size   = 0;
                        }
                        EnsureDataMessage();
                    }
                    _column++;
                    return;
                }

                throw PGUtil.ThrowIfReached();
            }
            catch
            {
                _connector.Break();
                Cleanup();
                throw;
            }
        }
Example #7
0
        T DoRead <T>(TypeHandler handler)
        {
            try {
                ReadColumnLenIfNeeded();
                if (_columnLen == -1)
                {
                    throw new InvalidCastException("Column is null");
                }

                // TODO: Duplication with NpgsqlDataReader.GetFieldValueInternal

                T result;

                // The type handler supports the requested type directly
                var tHandler = handler as ITypeHandler <T>;
                if (tHandler != null)
                {
                    result = handler.Read <T>(_buf, _columnLen, false).Result;
                }
                else
                {
                    var t = typeof(T);
                    if (!t.IsArray)
                    {
                        throw new InvalidCastException($"Can't cast database type {handler.PgDisplayName} to {typeof(T).Name}");
                    }

                    // Getting an array

                    // We need to treat this as an actual array type, these need special treatment because of
                    // typing/generics reasons (there is no way to express "array of X" with generics
                    var elementType  = t.GetElementType();
                    var arrayHandler = handler as ArrayHandler;
                    if (arrayHandler == null)
                    {
                        throw new InvalidCastException($"Can't cast database type {handler.PgDisplayName} to {typeof(T).Name}");
                    }

                    if (arrayHandler.GetElementFieldType() == elementType)
                    {
                        result = (T)handler.ReadAsObject(_buf, _columnLen, false).Result;
                    }
                    else if (arrayHandler.GetElementPsvType() == elementType)
                    {
                        result = (T)handler.ReadPsvAsObject(_buf, _columnLen, false).Result;
                    }
                    else
                    {
                        throw new InvalidCastException($"Can't cast database type {handler.PgDisplayName} to {typeof(T).Name}");
                    }
                }

                _leftToReadInDataMsg -= _columnLen;
                _columnLen            = int.MinValue; // Mark that the (next) column length hasn't been read yet
                _column++;
                return(result);
            } catch {
                _connector.Break();
                Cleanup();
                throw;
            }
        }