示例#1
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);
        }
        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);
        }
        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);
        }
示例#4
0
        internal async Task Startup()
        {
            // Read and skip the startup message
            await _readBuffer.EnsureAsync(4);

            var startupMessageLen = _readBuffer.ReadInt32();
            await _readBuffer.EnsureAsync(startupMessageLen - 4);

            _readBuffer.Skip(startupMessageLen - 4);

            WriteAuthenticateOk();
            WriteParameterStatuses(new Dictionary <string, string>
            {
                { "server_version", "13" },
                { "server_encoding", "UTF8" },
                { "client_encoding", "UTF8" },
                { "application_name", "Mock" },
                { "is_superuser", "on" },
                { "session_authorization", "foo" },
                { "DateStyle", "ISO, MDY" },
                { "IntervalStyle", "postgres" },
                { "TimeZone", "UTC" },
                { "integer_datetimes", "on" },
                { "standard_conforming_strings", "on" }
            });
            WriteBackendKeyData(ProcessId, BackendSecret);
            WriteReadyForQuery();

            await FlushAsync();
        }
示例#5
0
    NpgsqlInterval INpgsqlSimpleTypeHandler <NpgsqlInterval> .Read(NpgsqlReadBuffer buf, int len, FieldDescription?fieldDescription)
    {
        var ticks = buf.ReadInt64();
        var day   = buf.ReadInt32();
        var month = buf.ReadInt32();

        return(new NpgsqlInterval(month, day, ticks));
    }
        /// <inheritdoc />
        protected override NpgsqlTimeSpan ReadPsv(NpgsqlReadBuffer buf, int len, FieldDescription?fieldDescription = null)
        {
            var ticks = buf.ReadInt64();
            var day   = buf.ReadInt32();
            var month = buf.ReadInt32();

            return(new NpgsqlTimeSpan(month, day, ticks * 10));
        }
示例#7
0
        internal async Task SkipMessage()
        {
            await _readBuffer.EnsureAsync(4);

            var len = _readBuffer.ReadInt32();
            await _readBuffer.EnsureAsync(len - 4);

            _readBuffer.Skip(len - 4);
        }
示例#8
0
    /// <inheritdoc />
    public override TimeSpan Read(NpgsqlReadBuffer buf, int len, FieldDescription?fieldDescription = null)
    {
        var microseconds = buf.ReadInt64();
        var days         = buf.ReadInt32();
        var months       = buf.ReadInt32();

        if (months > 0)
        {
            throw new InvalidCastException("Cannot convert interval value with non-zero months to TimeSpan");
        }

        return(new(microseconds * 10 + days * TimeSpan.TicksPerDay));
    }
        Duration INpgsqlSimpleTypeHandler <Duration> .Read(NpgsqlReadBuffer buf, int len, FieldDescription?fieldDescription)
        {
            var microsecondsInDay = buf.ReadInt64();
            var days        = buf.ReadInt32();
            var totalMonths = buf.ReadInt32();

            if (totalMonths != 0)
            {
                throw new NpgsqlException("Cannot read PostgreSQL interval with non-zero months to NodaTime Duration. Try reading as a NodaTime Period instead.");
            }

            return(Duration.FromDays(days) + Duration.FromNanoseconds(microsecondsInDay * 1000));
        }
示例#10
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()));
        }
示例#11
0
        internal RowDescriptionMessage Load(NpgsqlReadBuffer buf, ConnectorTypeMapper typeMapper)
        {
            Fields.Clear();
            _nameIndex.Clear();
            _caseInsensitiveNameIndex.Clear();

            var numFields = buf.ReadInt16();

            for (var i = 0; i != numFields; ++i)
            {
                // TODO: Recycle
                var field = new FieldDescription();
                field.Populate(
                    typeMapper,
                    buf.ReadNullTerminatedString(),  // Name
                    buf.ReadUInt32(),                // TableOID
                    buf.ReadInt16(),                 // ColumnAttributeNumber
                    buf.ReadUInt32(),                // TypeOID
                    buf.ReadInt16(),                 // TypeSize
                    buf.ReadInt32(),                 // TypeModifier
                    (FormatCode)buf.ReadInt16()      // FormatCode
                    );

                Fields.Add(field);
                if (!_nameIndex.ContainsKey(field.Name))
                {
                    _nameIndex.Add(field.Name, i);
                    if (!_caseInsensitiveNameIndex.ContainsKey(field.Name))
                    {
                        _caseInsensitiveNameIndex.Add(field.Name, i);
                    }
                }
            }
            return(this);
        }
示例#12
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);
        }
示例#13
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);
        }
示例#14
0
        /// <inheritdoc />
        public override DateTimeOffset Read(NpgsqlReadBuffer buf, int len, FieldDescription?fieldDescription = null)
        {
            // Adjust from 1 microsecond to 100ns. Time zone (in seconds) is inverted.
            var ticks  = buf.ReadInt64() * 10;
            var offset = new TimeSpan(0, 0, -buf.ReadInt32());

            return(new DateTimeOffset(ticks + TimeSpan.TicksPerDay, offset));
        }
示例#15
0
 protected override NpgsqlTimeSpan ReadPsv(NpgsqlReadBuffer buf, int len, FieldDescription fieldDescription = null)
 {
     if (_integerFormat)
     {
         var ticks = buf.ReadInt64();
         var day   = buf.ReadInt32();
         var month = buf.ReadInt32();
         return(new NpgsqlTimeSpan(month, day, ticks * 10));
     }
     else
     {
         var seconds = buf.ReadDouble();
         var day     = buf.ReadInt32();
         var month   = buf.ReadInt32();
         return(new NpgsqlTimeSpan(month, day, (long)(seconds * TimeSpan.TicksPerSecond)));
     }
 }
示例#16
0
        // Binary Format: int64 expressing microseconds, int32 expressing timezone in seconds, negative

        #region Read

        public override DateTimeOffset Read(NpgsqlReadBuffer buf, int len, FieldDescription fieldDescription = null)
        {
            // Adjust from 1 microsecond to 100ns. Time zone (in seconds) is inverted.
            var ticks  = _integerFormat ? buf.ReadInt64() * 10 : (long)(buf.ReadDouble() * TimeSpan.TicksPerSecond);
            var offset = new TimeSpan(0, 0, -buf.ReadInt32());

            return(new DateTimeOffset(ticks, offset));
        }
示例#17
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);
        }
示例#18
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);
        }
示例#19
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));
        }
示例#20
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);
        }
示例#21
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);
            }
        }
        public override Period Read(NpgsqlReadBuffer buf, int len, FieldDescription?fieldDescription = null)
        {
            var microsecondsInDay = buf.ReadInt64();
            var days        = buf.ReadInt32();
            var totalMonths = buf.ReadInt32();

            // NodaTime will normalize most things (i.e. nanoseconds to milliseconds, seconds...)
            // but it will not normalize months to years.
            var months = totalMonths % 12;
            var years  = totalMonths / 12;

            return(new PeriodBuilder
            {
                Nanoseconds = microsecondsInDay * 1000,
                Days = days,
                Months = months,
                Years = years
            }.Build().Normalize());
        }
示例#23
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());
        }
        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 !);
示例#25
0
        /// <remarks>
        /// Copied wholesale from Postgresql backend/utils/adt/datetime.c:j2date
        /// </remarks>
        protected override NpgsqlDate ReadPsv(NpgsqlReadBuffer buf, int len, FieldDescription?fieldDescription = null)
        {
            var binDate = buf.ReadInt32();

            return(binDate switch
            {
                int.MaxValue => NpgsqlDate.Infinity,
                int.MinValue => NpgsqlDate.NegativeInfinity,
                _ => new NpgsqlDate(binDate + 730119)
            });
        public override Guid Read(NpgsqlReadBuffer buf, int len, FieldDescription fieldDescription = null)
        {
            var a = buf.ReadInt32();
            var b = buf.ReadInt16();
            var c = buf.ReadInt16();
            var d = new byte[8];

            buf.ReadBytes(d, 0, 8);
            return(new Guid(a, b, c, d));
        }
示例#27
0
        /// <inheritdoc />
        public override Guid Read(NpgsqlReadBuffer buf, int len, FieldDescription?fieldDescription = null)
        {
            var raw = new GuidRaw
            {
                Data1 = buf.ReadInt32(),
                Data2 = buf.ReadInt16(),
                Data3 = buf.ReadInt16(),
                Data4 = buf.ReadInt64(BitConverter.IsLittleEndian)
            };

            return(raw.Value);
        }
示例#28
0
        /// <summary>
        /// Reads an array of element type <typeparamref name="TRequestedElement"/> from the given buffer <paramref name="buf"/>.
        /// </summary>
        protected async ValueTask <Array> ReadArray <TRequestedElement>(NpgsqlReadBuffer buf, bool async, int expectedDimensions = 0, bool readAsObject = false)
        {
            await buf.Ensure(12, async);

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

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

            var returnType = readAsObject
                ? ArrayNullabilityMode switch
            {
                ArrayNullabilityMode.Never => ElementTypeInfo <TRequestedElement> .IsNonNullable && containsNulls
                        ? throw new InvalidOperationException(ReadNonNullableCollectionWithNullsExceptionMessage)
                        : typeof(TRequestedElement),
                      ArrayNullabilityMode.Always => ElementTypeInfo <TRequestedElement> .NullableElementType,
                      ArrayNullabilityMode.PerInstance => containsNulls
                        ? ElementTypeInfo <TRequestedElement> .NullableElementType
                        : typeof(TRequestedElement),
                      _ => throw new ArgumentOutOfRangeException()
            }
示例#29
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);
        }
示例#30
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));
        }