Example #1
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);
        }
Example #2
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);
        }
Example #3
0
 internal ParameterDescriptionMessage Load(NpgsqlReadBuffer buf)
 {
     var numParams = buf.ReadUInt16();
     TypeOIDs.Clear();
     for (var i = 0; i < numParams; i++)
         TypeOIDs.Add(buf.ReadUInt32());
     return this;
 }
Example #4
0
        public override NpgsqlTid Read(NpgsqlReadBuffer buf, int len, FieldDescription fieldDescription = null)
        {
            Debug.Assert(len == 6);

            var blockNumber  = buf.ReadUInt32();
            var offsetNumber = buf.ReadUInt16();

            return(new NpgsqlTid(blockNumber, offsetNumber));
        }
        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 !);
Example #6
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);
        }
Example #7
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);
        }
Example #8
0
        internal RowDescriptionMessage Load(NpgsqlReadBuffer buf, ConnectorTypeMapper typeMapper)
        {
            _nameIndex.Clear();
            _insensitiveIndex?.Clear();

            var numFields = Count = buf.ReadInt16();

            if (_fields.Length < numFields)
            {
                var oldFields = _fields;
                _fields = new FieldDescription[numFields];
                Array.Copy(oldFields, _fields, oldFields.Length);
            }

            for (var i = 0; i < numFields; ++i)
            {
                var field = _fields[i] ??= new();

                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
                    );

                if (!_nameIndex.ContainsKey(field.Name))
                {
                    _nameIndex.Add(field.Name, i);
                }
            }

            return(this);
        }
Example #9
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()
            }
Example #10
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);
        }
Example #11
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);
        }
Example #12
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, CancellationToken cancellationToken = default)
        {
            await buf.Ensure(12, async, cancellationToken);

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

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

            if (ElementTypeInfo <TRequestedElement> .IsNonNullable && containsNulls)
            {
                throw new InvalidOperationException(ReadNonNullableCollectionWithNullsExceptionMessage);
            }

            if (dimensions == 0)
            {
                return(expectedDimensions > 1 ? Array.CreateInstance(typeof(TRequestedElement), new int[expectedDimensions]) : Array.Empty <TRequestedElement>());
            }

            if (expectedDimensions > 0 && dimensions != expectedDimensions)
            {
                throw new InvalidOperationException($"Cannot read an array with {expectedDimensions} dimension(s) from an array with {dimensions} dimension(s)");
            }

            if (dimensions == 1)
            {
                await buf.Ensure(8, async, cancellationToken);

                var arrayLength = buf.ReadInt32();

                buf.ReadInt32(); // Lower bound

                var oneDimensional = new TRequestedElement[arrayLength];
                for (var i = 0; i < oneDimensional.Length; i++)
                {
                    oneDimensional[i] = await ElementHandler.ReadWithLength <TRequestedElement>(buf, async, cancellationToken : cancellationToken);
                }

                return(oneDimensional);
            }

            var dimLengths = new int[dimensions];
            await buf.Ensure(dimensions * 8, async, cancellationToken);

            for (var i = 0; i < dimensions; i++)
            {
                dimLengths[i] = buf.ReadInt32();
                buf.ReadInt32(); // Lower bound
            }

            var result = Array.CreateInstance(typeof(TRequestedElement), dimLengths);

            // Multidimensional arrays
            // We can't avoid boxing here
            var indices = new int[dimensions];

            while (true)
            {
                var element = await ElementHandler.ReadWithLength <TRequestedElement>(buf, async, cancellationToken : cancellationToken);

                result.SetValue(element, indices);

                // TODO: Overly complicated/inefficient...
                indices[dimensions - 1]++;
                for (var dim = dimensions - 1; dim >= 0; dim--)
                {
                    if (indices[dim] <= result.GetUpperBound(dim))
                    {
                        continue;
                    }

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

                    for (var j = dim; j < dimensions; j++)
                    {
                        indices[j] = result.GetLowerBound(j);
                    }
                    indices[dim - 1]++;
                }
            }
        }
Example #13
0
        async Task <PostgisGeometry> DoRead(NpgsqlReadBuffer buf, WkbIdentifier id, ByteOrder bo, bool async)
        {
            switch (id)
            {
            case WkbIdentifier.Point:
                await buf.Ensure(16, async);

                return(new PostgisPoint(buf.ReadDouble(bo), buf.ReadDouble(bo)));

            case WkbIdentifier.LineString:
            {
                await buf.Ensure(4, async);

                var points = new Coordinate2D[buf.ReadInt32(bo)];
                for (var ipts = 0; ipts < points.Length; ipts++)
                {
                    await buf.Ensure(16, async);

                    points[ipts] = new Coordinate2D(buf.ReadDouble(bo), buf.ReadDouble(bo));
                }
                return(new PostgisLineString(points));
            }

            case WkbIdentifier.Polygon:
            {
                await buf.Ensure(4, async);

                var rings = new Coordinate2D[buf.ReadInt32(bo)][];

                for (var irng = 0; irng < rings.Length; irng++)
                {
                    await buf.Ensure(4, async);

                    rings[irng] = new Coordinate2D[buf.ReadInt32(bo)];
                    for (var ipts = 0; ipts < rings[irng].Length; ipts++)
                    {
                        await buf.Ensure(16, async);

                        rings[irng][ipts] = new Coordinate2D(buf.ReadDouble(bo), buf.ReadDouble(bo));
                    }
                }
                return(new PostgisPolygon(rings));
            }

            case WkbIdentifier.MultiPoint:
            {
                await buf.Ensure(4, async);

                var points = new Coordinate2D[buf.ReadInt32(bo)];
                for (var ipts = 0; ipts < points.Length; ipts++)
                {
                    await buf.Ensure(21, async);

                    await buf.Skip(5, async);

                    points[ipts] = new Coordinate2D(buf.ReadDouble(bo), buf.ReadDouble(bo));
                }
                return(new PostgisMultiPoint(points));
            }

            case WkbIdentifier.MultiLineString:
            {
                await buf.Ensure(4, async);

                var rings = new Coordinate2D[buf.ReadInt32(bo)][];

                for (var irng = 0; irng < rings.Length; irng++)
                {
                    await buf.Ensure(9, async);

                    await buf.Skip(5, async);

                    rings[irng] = new Coordinate2D[buf.ReadInt32(bo)];
                    for (var ipts = 0; ipts < rings[irng].Length; ipts++)
                    {
                        await buf.Ensure(16, async);

                        rings[irng][ipts] = new Coordinate2D(buf.ReadDouble(bo), buf.ReadDouble(bo));
                    }
                }
                return(new PostgisMultiLineString(rings));
            }

            case WkbIdentifier.MultiPolygon:
            {
                await buf.Ensure(4, async);

                var pols = new Coordinate2D[buf.ReadInt32(bo)][][];

                for (var ipol = 0; ipol < pols.Length; ipol++)
                {
                    await buf.Ensure(9, async);

                    await buf.Skip(5, async);

                    pols[ipol] = new Coordinate2D[buf.ReadInt32(bo)][];
                    for (var irng = 0; irng < pols[ipol].Length; irng++)
                    {
                        await buf.Ensure(4, async);

                        pols[ipol][irng] = new Coordinate2D[buf.ReadInt32(bo)];
                        for (var ipts = 0; ipts < pols[ipol][irng].Length; ipts++)
                        {
                            await buf.Ensure(16, async);

                            pols[ipol][irng][ipts] = new Coordinate2D(buf.ReadDouble(bo), buf.ReadDouble(bo));
                        }
                    }
                }
                return(new PostgisMultiPolygon(pols));
            }

            case WkbIdentifier.GeometryCollection:
            {
                await buf.Ensure(4, async);

                var g = new PostgisGeometry[buf.ReadInt32(bo)];

                for (var i = 0; i < g.Length; i++)
                {
                    await buf.Ensure(5, async);

                    var elemBo = (ByteOrder)buf.ReadByte();
                    var elemId = (WkbIdentifier)(buf.ReadUInt32(bo) & 7);

                    g[i] = await DoRead(buf, elemId, elemBo, async);
                }
                return(new PostgisGeometryCollection(g));
            }

            default:
                throw new InvalidOperationException("Unknown Postgis identifier.");
            }
        }
Example #14
0
        async ValueTask <GeoJSONObject> ReadGeometryCore(NpgsqlReadBuffer buf, bool async, BoundingBoxBuilder?boundingBox)
        {
            await buf.Ensure(SizeOfHeader, async);

            var littleEndian = buf.ReadByte() > 0;
            var type         = (EwkbGeometryType)buf.ReadUInt32(littleEndian);

            GeoJSONObject geometry;
            NamedCRS?     crs = null;

            if (HasSrid(type))
            {
                await buf.Ensure(4, async);

                crs = GetCrs(buf.ReadInt32(littleEndian));
            }

            switch (type & EwkbGeometryType.BaseType)
            {
            case EwkbGeometryType.Point:
            {
                await buf.Ensure(SizeOfPoint(type), async);

                var position = ReadPosition(buf, type, littleEndian);
                boundingBox?.Accumulate(position);
                geometry = new Point(position);
                break;
            }

            case EwkbGeometryType.LineString:
            {
                await buf.Ensure(SizeOfLength, async);

                var coordinates = new Position[buf.ReadInt32(littleEndian)];
                for (var i = 0; i < coordinates.Length; ++i)
                {
                    await buf.Ensure(SizeOfPoint(type), async);

                    var position = ReadPosition(buf, type, littleEndian);
                    boundingBox?.Accumulate(position);
                    coordinates[i] = position;
                }
                geometry = new LineString(coordinates);
                break;
            }

            case EwkbGeometryType.Polygon:
            {
                await buf.Ensure(SizeOfLength, async);

                var lines = new LineString[buf.ReadInt32(littleEndian)];
                for (var i = 0; i < lines.Length; ++i)
                {
                    var coordinates = new Position[buf.ReadInt32(littleEndian)];
                    for (var j = 0; j < coordinates.Length; ++j)
                    {
                        await buf.Ensure(SizeOfPoint(type), async);

                        var position = ReadPosition(buf, type, littleEndian);
                        boundingBox?.Accumulate(position);
                        coordinates[j] = position;
                    }
                    lines[i] = new LineString(coordinates);
                }
                geometry = new Polygon(lines);
                break;
            }

            case EwkbGeometryType.MultiPoint:
            {
                await buf.Ensure(SizeOfLength, async);

                var points = new Point[buf.ReadInt32(littleEndian)];
                for (var i = 0; i < points.Length; ++i)
                {
                    await buf.Ensure(SizeOfHeader + SizeOfPoint(type), async);

                    await buf.Skip(SizeOfHeader, async);

                    var position = ReadPosition(buf, type, littleEndian);
                    boundingBox?.Accumulate(position);
                    points[i] = new Point(position);
                }
                geometry = new MultiPoint(points);
                break;
            }

            case EwkbGeometryType.MultiLineString:
            {
                await buf.Ensure(SizeOfLength, async);

                var lines = new LineString[buf.ReadInt32(littleEndian)];
                for (var i = 0; i < lines.Length; ++i)
                {
                    await buf.Ensure(SizeOfHeaderWithLength, async);

                    await buf.Skip(SizeOfHeader, async);

                    var coordinates = new Position[buf.ReadInt32(littleEndian)];
                    for (var j = 0; j < coordinates.Length; ++j)
                    {
                        await buf.Ensure(SizeOfPoint(type), async);

                        var position = ReadPosition(buf, type, littleEndian);
                        boundingBox?.Accumulate(position);
                        coordinates[j] = position;
                    }
                    lines[i] = new LineString(coordinates);
                }
                geometry = new MultiLineString(lines);
                break;
            }

            case EwkbGeometryType.MultiPolygon:
            {
                await buf.Ensure(SizeOfLength, async);

                var polygons = new Polygon[buf.ReadInt32(littleEndian)];
                for (var i = 0; i < polygons.Length; ++i)
                {
                    await buf.Ensure(SizeOfHeaderWithLength, async);

                    await buf.Skip(SizeOfHeader, async);

                    var lines = new LineString[buf.ReadInt32(littleEndian)];
                    for (var j = 0; j < lines.Length; ++j)
                    {
                        var coordinates = new Position[buf.ReadInt32(littleEndian)];
                        for (var k = 0; k < coordinates.Length; ++k)
                        {
                            await buf.Ensure(SizeOfPoint(type), async);

                            var position = ReadPosition(buf, type, littleEndian);
                            boundingBox?.Accumulate(position);
                            coordinates[k] = position;
                        }
                        lines[j] = new LineString(coordinates);
                    }
                    polygons[i] = new Polygon(lines);
                }
                geometry = new MultiPolygon(polygons);
                break;
            }

            case EwkbGeometryType.GeometryCollection:
            {
                await buf.Ensure(SizeOfLength, async);

                var elements = new IGeometryObject[buf.ReadInt32(littleEndian)];
                for (var i = 0; i < elements.Length; ++i)
                {
                    elements[i] = (IGeometryObject) await ReadGeometryCore(buf, async, boundingBox);
                }
                geometry = new GeometryCollection(elements);
                break;
            }

            default:
                throw UnknownPostGisType();
            }

            geometry.CRS = crs;
            return(geometry);
        }
Example #15
0
 /// <inheritdoc />
 public override uint Read(NpgsqlReadBuffer buf, int len, FieldDescription?fieldDescription = null)
 => buf.ReadUInt32();