예제 #1
0
        public override async ValueTask <NpgsqlPath> Read(NpgsqlReadBuffer buf, int len, bool async, FieldDescription fieldDescription = null)
        {
            await buf.Ensure(5, async);

            bool open;
            var  openByte = buf.ReadByte();

            switch (openByte)
            {
            case 1:
                open = false;
                break;

            case 0:
                open = true;
                break;

            default:
                throw new Exception("Error decoding binary geometric path: bad open byte");
            }

            var numPoints = buf.ReadInt32();
            var result    = new NpgsqlPath(numPoints, open);

            for (var i = 0; i < numPoints; i++)
            {
                await buf.Ensure(16, async);

                result.Add(new NpgsqlPoint(buf.ReadDouble(), buf.ReadDouble()));
            }
            return(result);
        }
예제 #2
0
        public override async ValueTask <object> Read(NpgsqlReadBuffer buf, int len, bool async, FieldDescription fieldDescription = null)
        {
            if (_members == null)
            {
                ResolveFields();
            }
            Debug.Assert(_members != null);

            await buf.Ensure(4, async);

            var fieldCount = buf.ReadInt32();

            if (fieldCount != _members.Count)  // PostgreSQL sanity check
            {
                throw new Exception($"pg_attributes contains {_members.Count} rows for type {PgDisplayName}, but {fieldCount} fields were received!");
            }

            var result = (IDictionary <string, object>) new ExpandoObject();

            foreach (var member in _members)
            {
                await buf.Ensure(8, async);

                buf.ReadInt32();  // read typeOID, not used
                var fieldLen = buf.ReadInt32();
                if (fieldLen == -1)
                {
                    // Null field, simply skip it and leave at default
                    continue;
                }
                // TODO: We need name translation
                result[member.PgName] = await member.Handler.ReadAsObject(buf, fieldLen, async);
            }
            return(result);
        }
예제 #3
0
        /// <inheritdoc />
        public override async ValueTask <Dictionary <string, string?> > Read(NpgsqlReadBuffer buf, int len, bool async, FieldDescription?fieldDescription = null)
        {
            await buf.Ensure(4, async);

            var numElements = buf.ReadInt32();
            var hstore      = new Dictionary <string, string?>(numElements);

            for (var i = 0; i < numElements; i++)
            {
                await buf.Ensure(4, async);

                var keyLen = buf.ReadInt32();
                Debug.Assert(keyLen != -1);
                var key = await _textHandler.Read(buf, keyLen, async);

                await buf.Ensure(4, async);

                var valueLen = buf.ReadInt32();

                hstore[key] = valueLen == -1
                    ? null
                    : await _textHandler.Read(buf, valueLen, async);
            }
            return(hstore);
        }
예제 #4
0
        protected internal override async ValueTask <TAny> Read <TAny>(NpgsqlReadBuffer buf, int len, bool async, FieldDescription fieldDescription = null)
        {
            if (_resolvedType != typeof(TAny))
            {
                Map(typeof(TAny));
            }

            await buf.Ensure(4, async);

            var fieldCount = buf.ReadInt32();

            if (fieldCount != _members.Count)  // PostgreSQL sanity check
            {
                throw new Exception($"pg_attributes contains {_members.Count} rows for type {PgDisplayName}, but {fieldCount} fields were received!");
            }

            // If TAny is a struct, we have to box it here to properly set its fields below
            object result = Activator.CreateInstance <TAny>();

            foreach (var member in _members)
            {
                await buf.Ensure(8, async);

                buf.ReadInt32();  // read typeOID, not used
                var fieldLen = buf.ReadInt32();
                if (fieldLen == -1)
                {
                    continue;  // Null field, simply skip it and leave at default
                }
                member.Setter(result, await member.Handler.ReadAsObject(buf, fieldLen, async));
            }
            return((TAny)result);
        }
예제 #5
0
        /// <inheritdoc />
        public override async ValueTask <BitArray> Read(NpgsqlReadBuffer buf, int len, bool async, FieldDescription?fieldDescription = null)
        {
            await buf.Ensure(4, async);

            var numBits   = buf.ReadInt32();
            var result    = new BitArray(numBits);
            var bytesLeft = len - 4;  // Remove leading number of bits

            if (bytesLeft == 0)
            {
                return(result);
            }

            var bitNo = 0;

            while (true)
            {
                var iterationEndPos = bytesLeft > buf.ReadBytesLeft
                    ? bytesLeft - buf.ReadBytesLeft
                    : 1;

                for (; bytesLeft > iterationEndPos; bytesLeft--)
                {
                    // ReSharper disable ShiftExpressionRealShiftCountIsZero
                    var chunk = buf.ReadByte();
                    result[bitNo++] = (chunk & (1 << 7)) != 0;
                    result[bitNo++] = (chunk & (1 << 6)) != 0;
                    result[bitNo++] = (chunk & (1 << 5)) != 0;
                    result[bitNo++] = (chunk & (1 << 4)) != 0;
                    result[bitNo++] = (chunk & (1 << 3)) != 0;
                    result[bitNo++] = (chunk & (1 << 2)) != 0;
                    result[bitNo++] = (chunk & (1 << 1)) != 0;
                    result[bitNo++] = (chunk & (1 << 0)) != 0;
                }

                if (bytesLeft == 1)
                {
                    break;
                }

                Debug.Assert(buf.ReadBytesLeft == 0);
                await buf.Ensure(Math.Min(bytesLeft, buf.Size), async);
            }

            if (bitNo < result.Length)
            {
                var remainder = result.Length - bitNo;
                await buf.Ensure(1, async);

                var lastChunk = buf.ReadByte();
                for (var i = 7; i >= 8 - remainder; i--)
                {
                    result[bitNo++] = (lastChunk & (1 << i)) != 0;
                }
            }

            return(result);
        }
예제 #6
0
        public ValueTask <bool> MoveNextAsync()
        {
            if (_tupleEnumerable.State != RowState.Reading)
            {
                throw new ObjectDisposedException(null);
            }

            using (NoSynchronizationContextScope.Enter())
                return(MoveNextCore());

            async ValueTask <bool> MoveNextCore()
            {
                // Consume the previous column
                if (_pos != -1)
                {
                    await _value.Consume(_cancellationToken);
                }

                if (_pos + 1 == _numColumns)
                {
                    return(false);
                }
                _pos++;

                // Read the next column
                await _readBuffer.Ensure(1, async : true);

                var kind = (TupleDataKind)_readBuffer.ReadByte();
                int len;

                switch (kind)
                {
                case TupleDataKind.Null:
                case TupleDataKind.UnchangedToastedValue:
                    len = 0;
                    break;

                case TupleDataKind.TextValue:
                case TupleDataKind.BinaryValue:
                    if (_readBuffer.ReadBytesLeft < 4)
                    {
                        using var tokenRegistration = _readBuffer.Connector.StartNestedCancellableOperation(_cancellationToken);
                        await _readBuffer.Ensure(4, async : true);
                    }
                    len = _readBuffer.ReadInt32();
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                _value.Reset(kind, len, _rowDescription[_pos]);

                return(true);
            }
        }
예제 #7
0
        public override async Task <NpgsqlPolygon> Read(NpgsqlReadBuffer buf, int len, bool async, FieldDescription fieldDescription = null)
        {
            await buf.Ensure(4, async);

            var numPoints = buf.ReadInt32();
            var result    = new NpgsqlPolygon(numPoints);

            for (var i = 0; i < numPoints; i++)
            {
                await buf.Ensure(16, async);

                result.Add(new NpgsqlPoint(buf.ReadDouble(), buf.ReadDouble()));
            }
            return(result);
        }
예제 #8
0
        private protected async ValueTask <NpgsqlRange <TAny> > DoRead <TAny>(NpgsqlReadBuffer buf, int len, bool async, FieldDescription?fieldDescription)
        {
            await buf.Ensure(1, async);

            var flags = (RangeFlags)buf.ReadByte();

            if ((flags & RangeFlags.Empty) != 0)
            {
                return(NpgsqlRange <TAny> .Empty);
            }

            var lowerBound = default(TAny);
            var upperBound = default(TAny);

            if ((flags & RangeFlags.LowerBoundInfinite) == 0)
            {
                lowerBound = await _subtypeHandler.ReadWithLength <TAny>(buf, async);
            }

            if ((flags & RangeFlags.UpperBoundInfinite) == 0)
            {
                upperBound = await _subtypeHandler.ReadWithLength <TAny>(buf, async);
            }

            return(new NpgsqlRange <TAny>(lowerBound, upperBound, flags));
        }
예제 #9
0
        public override async ValueTask Read(TComposite composite, NpgsqlReadBuffer buffer, bool async, CancellationToken cancellationToken = default)
        {
            if (_set == null)
            {
                ThrowHelper.ThrowInvalidOperationException_NoPropertySetter(typeof(TComposite), MemberInfo);
            }

            await buffer.Ensure(sizeof(uint) + sizeof(int), async, cancellationToken);

            var oid = buffer.ReadUInt32();

            Debug.Assert(oid == PostgresType.OID);

            var length = buffer.ReadInt32();

            if (length == -1)
            {
                return;
            }

            var value = NullableHandler <TMember> .Exists
                ? await NullableHandler <TMember> .ReadAsync(_handler, buffer, length, async, cancellationToken : cancellationToken)
                : await _handler.Read <TMember>(buffer, length, async, cancellationToken : cancellationToken);

            _set(composite, value);
        }
예제 #10
0
        /// <inheritdoc />
        public override async ValueTask <Dictionary <string, string?> > Read(NpgsqlReadBuffer buf, int len, bool async,
                                                                             FieldDescription?fieldDescription = null, CancellationToken cancellationToken = default)
        {
            await buf.Ensure(4, async, cancellationToken);

            var numElements = buf.ReadInt32();

            return(await ReadInto(new Dictionary <string, string?>(numElements), numElements, buf, async, cancellationToken));
        }
예제 #11
0
        public override async ValueTask <NpgsqlRange <TElement>[]> Read(
            NpgsqlReadBuffer buf, int len, bool async, FieldDescription?fieldDescription = null)
        {
            await buf.Ensure(4, async);

            var numRanges  = buf.ReadInt32();
            var multirange = new NpgsqlRange <TElement> [numRanges];

            for (var i = 0; i < numRanges; i++)
            {
                await buf.Ensure(4, async);

                var rangeLen = buf.ReadInt32();
                multirange[i] = await _rangeHandler.Read(buf, rangeLen, async, fieldDescription);
            }

            return(multirange);
        }
예제 #12
0
        async ValueTask <List <NpgsqlRange <TElement> > > INpgsqlTypeHandler <List <NpgsqlRange <TElement> > > .Read(
            NpgsqlReadBuffer buf, int len, bool async, FieldDescription?fieldDescription)
        {
            await buf.Ensure(4, async);

            var numRanges  = buf.ReadInt32();
            var multirange = new List <NpgsqlRange <TElement> >(numRanges);

            for (var i = 0; i < numRanges; i++)
            {
                await buf.Ensure(4, async);

                var rangeLen = buf.ReadInt32();
                multirange.Add(await _rangeHandler.Read(buf, rangeLen, async, fieldDescription));
            }

            return(multirange);
        }
예제 #13
0
        public async ValueTask <T> Read <T>(NpgsqlReadBuffer buffer, bool async, CancellationToken cancellationToken = default)
        {
            await buffer.Ensure(sizeof(uint) + sizeof(int), async, cancellationToken);

            var oid    = buffer.ReadUInt32();
            var length = buffer.ReadInt32();

            if (length == -1)
            {
                return(default !);
예제 #14
0
        async ValueTask <ImmutableDictionary <string, string?> > INpgsqlTypeHandler <ImmutableDictionary <string, string?> > .Read(
            NpgsqlReadBuffer buf, int len, bool async, FieldDescription?fieldDescription, CancellationToken cancellationToken)
        {
            await buf.Ensure(4, async, cancellationToken);

            var numElements = buf.ReadInt32();

            return((await ReadInto(ImmutableDictionary <string, string?> .Empty.ToBuilder(), numElements, buf, async, cancellationToken))
                   .ToImmutable());
        }
예제 #15
0
        public override async Task <PostgisGeometry> Read(NpgsqlReadBuffer buf, int len, bool async, FieldDescription fieldDescription = null)
        {
            await buf.Ensure(5, async);

            var bo = (ByteOrder)buf.ReadByte();
            var id = buf.ReadUInt32(bo);

            var srid = 0u;

            if ((id & (uint)EwkbModifiers.HasSRID) != 0)
            {
                await buf.Ensure(4, async);

                srid = buf.ReadUInt32(bo);
            }

            var geom = await DoRead(buf, (WkbIdentifier)(id & 7), bo, async);

            geom.SRID = srid;
            return(geom);
        }
예제 #16
0
    async Task ReadHeader(bool async)
    {
        _leftToReadInDataMsg = Expect <CopyDataMessage>(await _connector.ReadMessage(async), _connector).Length;
        var headerLen = NpgsqlRawCopyStream.BinarySignature.Length + 4 + 4;
        await _buf.Ensure(headerLen, async);

        if (NpgsqlRawCopyStream.BinarySignature.Any(t => _buf.ReadByte() != t))
        {
            throw new NpgsqlException("Invalid COPY binary signature at beginning!");
        }

        var flags = _buf.ReadInt32();

        if (flags != 0)
        {
            throw new NotSupportedException("Unsupported flags in COPY operation (OID inclusion?)");
        }

        _buf.ReadInt32();   // Header extensions, currently unused
        _leftToReadInDataMsg -= headerLen;
    }
예제 #17
0
        internal async ValueTask <TAny> ReadWithLength <TAny>(NpgsqlReadBuffer buf, bool async, FieldDescription fieldDescription = null)
        {
            await buf.Ensure(4, async);

            var len = buf.ReadInt32();

            if (len == -1)
            {
                return(default(TAny));
            }
            return(await Read <TAny>(buf, len, async, fieldDescription));
        }
예제 #18
0
        public override async ValueTask <PostgisGeometry> Read(NpgsqlReadBuffer buf, int len, bool async, FieldDescription?fieldDescription = null, CancellationToken cancellationToken = default)
        {
            await buf.Ensure(5, async, cancellationToken);

            var le = buf.ReadByte() != 0;
            var id = buf.ReadUInt32(le);

            var srid = 0u;

            if ((id & (uint)EwkbModifiers.HasSRID) != 0)
            {
                await buf.Ensure(4, async, cancellationToken);

                srid = buf.ReadUInt32(le);
            }

            var geom = await DoRead(buf, (WkbIdentifier)(id & 7), le, async, cancellationToken);

            geom.SRID = srid;
            return(geom);
        }
예제 #19
0
        async ValueTask <T> ReadInto <T>(T dictionary, int numElements, NpgsqlReadBuffer buf, bool async, CancellationToken cancellationToken = default)
            where T : IDictionary <string, string?>
        {
            for (var i = 0; i < numElements; i++)
            {
                await buf.Ensure(4, async, cancellationToken);

                var keyLen = buf.ReadInt32();
                Debug.Assert(keyLen != -1);
                var key = await _textHandler.Read(buf, keyLen, async, cancellationToken : cancellationToken);

                await buf.Ensure(4, async, cancellationToken);

                var valueLen = buf.ReadInt32();

                dictionary[key] = valueLen == -1
                    ? null
                    : await _textHandler.Read(buf, valueLen, async, cancellationToken : cancellationToken);
            }
            return(dictionary);
        }
예제 #20
0
        public override async ValueTask <BitArray> Read(NpgsqlReadBuffer buf, int len, bool async, FieldDescription fieldDescription = null)
        {
            await buf.Ensure(4, async);

            var numBits   = buf.ReadInt32();
            var result    = new BitArray(numBits);
            var bytesLeft = len - 4;  // Remove leading number of bits
            var bitNo     = 0;

            do
            {
                var iterationEndPos = bytesLeft - Math.Min(bytesLeft, buf.ReadBytesLeft) + 1;
                for (; bytesLeft > iterationEndPos; bytesLeft--)
                {
                    var chunk = buf.ReadByte();
                    result[bitNo++] = (chunk & (1 << 7)) != 0;
                    result[bitNo++] = (chunk & (1 << 6)) != 0;
                    result[bitNo++] = (chunk & (1 << 5)) != 0;
                    result[bitNo++] = (chunk & (1 << 4)) != 0;
                    result[bitNo++] = (chunk & (1 << 3)) != 0;
                    result[bitNo++] = (chunk & (1 << 2)) != 0;
                    result[bitNo++] = (chunk & (1 << 1)) != 0;
                    result[bitNo++] = (chunk & (1 << 0)) != 0;
                }
            } while (bytesLeft > 1);

            if (bitNo < result.Length)
            {
                var remainder = result.Length - bitNo;
                await buf.Ensure(1, async);

                var lastChunk = buf.ReadByte();
                for (var i = 7; i >= 8 - remainder; i--)
                {
                    result[bitNo++] = (lastChunk & (1 << i)) != 0;
                }
            }

            return(result);
        }
예제 #21
0
        public override async ValueTask <object[]> Read(NpgsqlReadBuffer buf, int len, bool async, FieldDescription?fieldDescription = null)
        {
            await buf.Ensure(4, async);

            var fieldCount = buf.ReadInt32();
            var result     = new object[fieldCount];

            for (var i = 0; i < fieldCount; i++)
            {
                await buf.Ensure(8, async);

                var typeOID  = buf.ReadUInt32();
                var fieldLen = buf.ReadInt32();
                if (fieldLen == -1)  // Null field, simply skip it and leave at default
                {
                    continue;
                }
                result[i] = await _typeMapper.GetByOID(typeOID).ReadAsObject(buf, fieldLen, async);
            }

            return(result);
        }
예제 #22
0
        /// <inheritdoc />
        public override async ValueTask <NpgsqlPath> Read(NpgsqlReadBuffer buf, int len, bool async, FieldDescription?fieldDescription = null)
        {
            await buf.Ensure(5, async);

            var open = buf.ReadByte() switch
            {
                1 => false,
                0 => true,
                _ => throw new Exception("Error decoding binary geometric path: bad open byte")
            };

            var numPoints = buf.ReadInt32();
            var result    = new NpgsqlPath(numPoints, open);

            for (var i = 0; i < numPoints; i++)
            {
                await buf.Ensure(16, async);

                result.Add(new NpgsqlPoint(buf.ReadDouble(), buf.ReadDouble()));
            }
            return(result);
        }
예제 #23
0
    /// <inheritdoc />
    public override async ValueTask <string> Read(NpgsqlReadBuffer buf, int len, bool async, FieldDescription?fieldDescription = null)
    {
        await buf.Ensure(1, async);

        var version = buf.ReadByte();

        if (version != JsonPathVersion)
        {
            throw new NotSupportedException($"Don't know how to decode JSONPATH with wire format {version}, your connection is now broken");
        }

        return(await _textHandler.Read(buf, len - 1, async, fieldDescription));
    }
예제 #24
0
        public override async ValueTask <string> Read(NpgsqlReadBuffer buf, int len, bool async, FieldDescription?fieldDescription = null)
        {
            await buf.Ensure(1, async);

            var version = buf.ReadByte();

            if (version != LTxtQueryProtocolVersion)
            {
                throw new NotSupportedException($"Don't know how to decode ltxtquery with wire format {version}, your connection is now broken");
            }

            return(await base.Read(buf, len - 1, async, fieldDescription));
        }
예제 #25
0
        async ValueTask <bool> INpgsqlTypeHandler <bool> .Read(NpgsqlReadBuffer buf, int len, bool async, FieldDescription?fieldDescription)
        {
            await buf.Ensure(5, async);

            var bitLen = buf.ReadInt32();

            if (bitLen != 1)
            {
                throw new InvalidCastException("Can't convert a BIT(N) type to bool, only BIT(1)");
            }
            var b = buf.ReadByte();

            return((b & 128) != 0);
        }
예제 #26
0
        /// <inheritdoc />
        public override async ValueTask <NpgsqlTsVector> Read(NpgsqlReadBuffer buf, int len, bool async, FieldDescription?fieldDescription = null)
        {
            await buf.Ensure(4, async);

            var numLexemes = buf.ReadInt32();

            len -= 4;

            var lexemes = new List <NpgsqlTsVector.Lexeme>();

            for (var lexemePos = 0; lexemePos < numLexemes; lexemePos++)
            {
                await buf.Ensure(Math.Min(len, MaxSingleLexemeBytes), async);

                var posBefore = buf.ReadPosition;

                List <NpgsqlTsVector.Lexeme.WordEntryPos>?positions = null;

                var lexemeString = buf.ReadNullTerminatedString();
                int numPositions = buf.ReadInt16();
                for (var i = 0; i < numPositions; i++)
                {
                    var wordEntryPos = buf.ReadInt16();
                    if (positions == null)
                    {
                        positions = new List <NpgsqlTsVector.Lexeme.WordEntryPos>();
                    }
                    positions.Add(new NpgsqlTsVector.Lexeme.WordEntryPos(wordEntryPos));
                }

                lexemes.Add(new NpgsqlTsVector.Lexeme(lexemeString, positions, true));

                len -= buf.ReadPosition - posBefore;
            }

            return(new NpgsqlTsVector(lexemes, true));
        }
예제 #27
0
        /// <summary>
        /// Reads a generic list containing elements of type <typeparamref name="TRequestedElement"/> from the given buffer <paramref name="buf"/>.
        /// </summary>
        protected async ValueTask <List <TRequestedElement> > ReadList <TRequestedElement>(NpgsqlReadBuffer buf, bool async, CancellationToken cancellationToken = default)
        {
            await buf.Ensure(12, async, cancellationToken);

            var dimensions    = buf.ReadInt32();
            var containsNulls = buf.ReadInt32() == 1;

            buf.ReadUInt32(); // Element OID. Ignored.

            if (dimensions == 0)
            {
                return(ElementTypeInfo <TRequestedElement> .EmptyList);
            }
            if (dimensions > 1)
            {
                throw new NotSupportedException($"Can't read multidimensional array as List<{typeof(TRequestedElement).Name}>");
            }
            if (ElementTypeInfo <TRequestedElement> .IsNonNullable && containsNulls)
            {
                throw new InvalidOperationException(ReadNonNullableCollectionWithNullsExceptionMessage);
            }

            await buf.Ensure(8, async, cancellationToken);

            var length = buf.ReadInt32();

            buf.ReadInt32(); // We don't care about the lower bounds

            var list = new List <TRequestedElement>(length);

            for (var i = 0; i < length; i++)
            {
                list.Add(await ElementHandler.ReadWithLength <TRequestedElement>(buf, async, cancellationToken: cancellationToken));
            }
            return(list);
        }
예제 #28
0
        async ValueTask <BitVector32> INpgsqlTypeHandler <BitVector32> .Read(NpgsqlReadBuffer buf, int len, bool async, FieldDescription?fieldDescription)
        {
            if (len > 4 + 4)
            {
                throw new InvalidCastException("Can't read PostgreSQL bitstring with more than 32 bits into BitVector32");
            }

            await buf.Ensure(4 + 4, async);

            var numBits = buf.ReadInt32();

            return(numBits == 0
                ? new BitVector32(0)
                : new BitVector32(buf.ReadInt32()));
        }
예제 #29
0
        protected internal async ValueTask <TAny> Read <TAny>(NpgsqlReadBuffer buf, int len, bool async, FieldDescription?fieldDescription = null)
        {
            switch (this)
            {
            case INpgsqlSimpleTypeHandler <TAny> simpleTypeHandler:
                await buf.Ensure(len, async);

                return(simpleTypeHandler.Read(buf, len, fieldDescription));

            case INpgsqlTypeHandler <TAny> typeHandler:
                return(await typeHandler.Read(buf, len, async, fieldDescription));

            default:
                return(await ReadCustom <TAny>(buf, len, async, fieldDescription));
            }
        }
예제 #30
0
        async ValueTask <bool> INpgsqlTypeHandler <bool> .Read(NpgsqlReadBuffer buf, int len, bool async, FieldDescription fieldDescription)
        {
            await buf.Ensure(5, async);

            var bitLen = buf.ReadInt32();

            if (bitLen != 1)
            {
                // This isn't a single bit - error.
                // Consume the rest of the value first so the connection is left in a good state.
                buf.Skip(len - 4);
                throw new NpgsqlSafeReadException(new InvalidCastException("Can't convert a BIT(N) type to bool, only BIT(1)"));
            }
            var b = buf.ReadByte();

            return((b & 128) != 0);
        }