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); }
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); }
internal ParameterDescriptionMessage Load(NpgsqlReadBuffer buf) { var numParams = buf.ReadUInt16(); TypeOIDs.Clear(); for (var i = 0; i < numParams; i++) TypeOIDs.Add(buf.ReadUInt32()); return this; }
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 !);
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); }
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); }
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); }
/// <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() }
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); }
/// <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); }
/// <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]++; } } }
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."); } }
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); }
/// <inheritdoc /> public override uint Read(NpgsqlReadBuffer buf, int len, FieldDescription?fieldDescription = null) => buf.ReadUInt32();