Beispiel #1
0
        /// <inheritdoc />
        protected internal override int ValidateAndGetLength <TAny>(TAny value, ref NpgsqlLengthCache?lengthCache, NpgsqlParameter?parameter)
        {
            if (typeof(TAny) == typeof(string) ||
                typeof(TAny) == typeof(char[]) ||
                typeof(TAny) == typeof(ArraySegment <char>) ||
                typeof(TAny) == typeof(char) ||
                typeof(TAny) == typeof(byte[]))
            {
                return(_textHandler.ValidateAndGetLength(value, ref lengthCache, parameter) + _headerLen);
            }

            if (typeof(TAny) == typeof(JsonDocument))
            {
                if (lengthCache == null)
                {
                    lengthCache = new NpgsqlLengthCache(1);
                }
                if (lengthCache.IsPopulated)
                {
                    return(lengthCache.Get());
                }

                var data = SerializeJsonDocument((JsonDocument)(object)value !);
                if (parameter != null)
                {
                    parameter.ConvertedValue = data;
                }
                return(lengthCache.Set(data.Length + _headerLen));
            }

            // User POCO, need to serialize. At least internally ArrayPool buffers are used...
            var s = JsonSerializer.Serialize(value, _serializerOptions);

            if (parameter != null)
            {
                parameter.ConvertedValue = s;
            }

            return(_textHandler.ValidateAndGetLength(s, ref lengthCache, parameter) + _headerLen);
        }
Beispiel #2
0
        public int ValidateAndGetLength(Polygon value, ref NpgsqlLengthCache lengthCache, NpgsqlParameter parameter)
        {
            var lines  = value.Coordinates;
            var length = SizeOfHeaderWithLength + SizeOfLength * lines.Count;

            if (GetSrid(value.CRS) != 0)
            {
                length += sizeof(int);
            }

            var hasZ = false;

            for (var i = 0; i < lines.Count; ++i)
            {
                var coordinates = lines[i].Coordinates;
                if (NotValid(coordinates, out var lineHasZ))
                {
                    throw AllOrNoneCoordiantesMustHaveZ(parameter, nameof(Polygon));
                }

                if (hasZ != lineHasZ)
                {
                    if (i == 0)
                    {
                        hasZ = lineHasZ;
                    }
                    else
                    {
                        throw AllOrNoneCoordiantesMustHaveZ(parameter, nameof(LineString));
                    }
                }

                length += coordinates.Count * SizeOfPoint(hasZ);
            }

            return(length);
        }
 public override Task Write(T value, NpgsqlWriteBuffer buf, NpgsqlLengthCache lengthCache, NpgsqlParameter parameter, bool async)
 => _wrappedHandler.Write(value, buf, lengthCache, parameter, async);
Beispiel #4
0
 /// <inheritdoc />
 public override int ValidateAndGetLength(byte[] value, ref NpgsqlLengthCache lengthCache, NpgsqlParameter parameter)
 => parameter == null || parameter.Size <= 0 || parameter.Size >= value.Length
             ? value.Length
             : parameter.Size;
Beispiel #5
0
 public int ValidateAndGetLength(bool value, ref NpgsqlLengthCache lengthCache, NpgsqlParameter parameter)
 => 5;
Beispiel #6
0
 public override int ValidateAndGetLength(BitArray value, ref NpgsqlLengthCache lengthCache, NpgsqlParameter parameter)
 => 4 + (value.Length + 7) / 8;
Beispiel #7
0
 public Task Write(PostgisGeometryCollection value, NpgsqlWriteBuffer buf, NpgsqlLengthCache lengthCache, NpgsqlParameter parameter, bool async)
 => Write((PostgisGeometry)value, buf, lengthCache, parameter, async);
Beispiel #8
0
        public override async Task Write(PostgisGeometry value, NpgsqlWriteBuffer buf, NpgsqlLengthCache lengthCache, NpgsqlParameter parameter, bool async)
        {
            // Common header
            if (value.SRID == 0)
            {
                if (buf.WriteSpaceLeft < 5)
                {
                    await buf.Flush(async);
                }
                buf.WriteByte(0); // We choose to ouput only XDR structure
                buf.WriteInt32((int)value.Identifier);
            }
            else
            {
                if (buf.WriteSpaceLeft < 9)
                {
                    await buf.Flush(async);
                }
                buf.WriteByte(0);
                buf.WriteInt32((int)((uint)value.Identifier | (uint)EwkbModifiers.HasSRID));
                buf.WriteInt32((int)value.SRID);
            }

            switch (value.Identifier)
            {
            case WkbIdentifier.Point:
                if (buf.WriteSpaceLeft < 16)
                {
                    await buf.Flush(async);
                }
                var p = (PostgisPoint)value;
                buf.WriteDouble(p.X);
                buf.WriteDouble(p.Y);
                return;

            case WkbIdentifier.LineString:
                var l = (PostgisLineString)value;
                if (buf.WriteSpaceLeft < 4)
                {
                    await buf.Flush(async);
                }
                buf.WriteInt32(l.PointCount);
                for (var ipts = 0; ipts < l.PointCount; ipts++)
                {
                    if (buf.WriteSpaceLeft < 16)
                    {
                        await buf.Flush(async);
                    }
                    buf.WriteDouble(l[ipts].X);
                    buf.WriteDouble(l[ipts].Y);
                }
                return;

            case WkbIdentifier.Polygon:
                var pol = (PostgisPolygon)value;
                if (buf.WriteSpaceLeft < 4)
                {
                    await buf.Flush(async);
                }
                buf.WriteInt32(pol.RingCount);
                for (var irng = 0; irng < pol.RingCount; irng++)
                {
                    if (buf.WriteSpaceLeft < 4)
                    {
                        await buf.Flush(async);
                    }
                    buf.WriteInt32(pol[irng].Length);
                    for (var ipts = 0; ipts < pol[irng].Length; ipts++)
                    {
                        if (buf.WriteSpaceLeft < 16)
                        {
                            await buf.Flush(async);
                        }
                        buf.WriteDouble(pol[irng][ipts].X);
                        buf.WriteDouble(pol[irng][ipts].Y);
                    }
                }
                return;

            case WkbIdentifier.MultiPoint:
                var mp = (PostgisMultiPoint)value;
                if (buf.WriteSpaceLeft < 4)
                {
                    await buf.Flush(async);
                }
                buf.WriteInt32(mp.PointCount);
                for (var ipts = 0; ipts < mp.PointCount; ipts++)
                {
                    if (buf.WriteSpaceLeft < 21)
                    {
                        await buf.Flush(async);
                    }
                    buf.WriteByte(0);
                    buf.WriteInt32((int)WkbIdentifier.Point);
                    buf.WriteDouble(mp[ipts].X);
                    buf.WriteDouble(mp[ipts].Y);
                }
                return;

            case WkbIdentifier.MultiLineString:
                var ml = (PostgisMultiLineString)value;
                if (buf.WriteSpaceLeft < 4)
                {
                    await buf.Flush(async);
                }
                buf.WriteInt32(ml.LineCount);
                for (var irng = 0; irng < ml.LineCount; irng++)
                {
                    if (buf.WriteSpaceLeft < 9)
                    {
                        await buf.Flush(async);
                    }
                    buf.WriteByte(0);
                    buf.WriteInt32((int)WkbIdentifier.LineString);
                    buf.WriteInt32(ml[irng].PointCount);
                    for (var ipts = 0; ipts < ml[irng].PointCount; ipts++)
                    {
                        if (buf.WriteSpaceLeft < 16)
                        {
                            await buf.Flush(async);
                        }
                        buf.WriteDouble(ml[irng][ipts].X);
                        buf.WriteDouble(ml[irng][ipts].Y);
                    }
                }
                return;

            case WkbIdentifier.MultiPolygon:
                var mpl = (PostgisMultiPolygon)value;
                if (buf.WriteSpaceLeft < 4)
                {
                    await buf.Flush(async);
                }
                buf.WriteInt32(mpl.PolygonCount);
                for (var ipol = 0; ipol < mpl.PolygonCount; ipol++)
                {
                    if (buf.WriteSpaceLeft < 9)
                    {
                        await buf.Flush(async);
                    }
                    buf.WriteByte(0);
                    buf.WriteInt32((int)WkbIdentifier.Polygon);
                    buf.WriteInt32(mpl[ipol].RingCount);
                    for (var irng = 0; irng < mpl[ipol].RingCount; irng++)
                    {
                        if (buf.WriteSpaceLeft < 4)
                        {
                            await buf.Flush(async);
                        }
                        buf.WriteInt32(mpl[ipol][irng].Length);
                        for (var ipts = 0; ipts < mpl[ipol][irng].Length; ipts++)
                        {
                            if (buf.WriteSpaceLeft < 16)
                            {
                                await buf.Flush(async);
                            }
                            buf.WriteDouble(mpl[ipol][irng][ipts].X);
                            buf.WriteDouble(mpl[ipol][irng][ipts].Y);
                        }
                    }
                }
                return;

            case WkbIdentifier.GeometryCollection:
                var coll = (PostgisGeometryCollection)value;
                if (buf.WriteSpaceLeft < 4)
                {
                    await buf.Flush(async);
                }
                buf.WriteInt32(coll.GeometryCount);

                foreach (var x in coll)
                {
                    await Write(x, buf, lengthCache, null, async);
                }
                return;

            default:
                throw new InvalidOperationException("Unknown Postgis identifier.");
            }
        }
Beispiel #9
0
 /// <summary>
 /// Responsible for validating that a value represents a value of the correct and which can be
 /// written for PostgreSQL - if the value cannot be written for any reason, an exception shold be thrown.
 /// Also returns the byte length needed to write the value.
 /// </summary>
 /// <param name="value">The value to be written to PostgreSQL</param>
 /// <param name="lengthCache">
 /// If the byte length calculation is costly (e.g. for UTF-8 strings), its result can be stored in the
 /// length cache to be reused in the writing process, preventing recalculation.
 /// </param>
 /// <param name="parameter">
 /// The <see cref="NpgsqlParameter"/> instance where this value resides. Can be used to access additional
 /// information relevant to the write process (e.g. <see cref="NpgsqlParameter.Size"/>).
 /// </param>
 /// <returns>The number of bytes required to write the value.</returns>
 protected internal abstract int ValidateObjectAndGetLength([CanBeNull] object value, ref NpgsqlLengthCache lengthCache, NpgsqlParameter parameter);
Beispiel #10
0
 /// <summary>
 /// Called to write the value of a generic <see cref="NpgsqlParameter{T}"/>.
 /// </summary>
 internal abstract Task WriteWithLengthInternal <TAny>([CanBeNull] TAny value, NpgsqlWriteBuffer buf, NpgsqlLengthCache lengthCache, NpgsqlParameter parameter, bool async);
Beispiel #11
0
 /// <summary>
 /// Called to validate and get the length of a value of a generic <see cref="NpgsqlParameter{T}"/>.
 /// </summary>
 protected internal abstract int ValidateAndGetLength <TAny>([CanBeNull] TAny value, ref NpgsqlLengthCache lengthCache, NpgsqlParameter parameter);
 protected override Task WriteWithLength <T2>(T2 value, NpgsqlWriteBuffer buf, NpgsqlLengthCache lengthCache, NpgsqlParameter parameter, bool async)
 {
     buf.WriteInt32(ValidateAndGetLength(value, ref lengthCache, parameter));
     return(Write(value, buf, lengthCache, parameter, async));
 }
 protected internal override Task WriteObjectWithLength(object value, NpgsqlWriteBuffer buf, NpgsqlLengthCache lengthCache, NpgsqlParameter parameter, bool async)
 => value == null || value is DBNull
         ? WriteWithLengthInternal <DBNull>(null, buf, lengthCache, parameter, async)
         : WriteWithLengthInternal(value, buf, lengthCache, parameter, async);
 protected internal override int ValidateAndGetLength <TAny>(TAny value, ref NpgsqlLengthCache lengthCache, NpgsqlParameter parameter)
 => ValidateAndGetLength(value, ref lengthCache, parameter);
 protected internal override int ValidateObjectAndGetLength(object value, ref NpgsqlLengthCache lengthCache, NpgsqlParameter parameter)
 => value == null || value is DBNull
         ? -1
         : ValidateAndGetLength(value, ref lengthCache, parameter);
Beispiel #16
0
 public int ValidateAndGetLength(PostgisGeometryCollection value, ref NpgsqlLengthCache lengthCache, NpgsqlParameter parameter)
 => value.GetLen(true);
Beispiel #17
0
 public int ValidateAndGetLength(byte[] value, ref NpgsqlLengthCache lengthCache, NpgsqlParameter parameter)
 => value.Length;
Beispiel #18
0
 /// <summary>
 /// Writes a value to the provided buffer, using either sync or async I/O.
 /// </summary>
 /// <param name="value">The value to write.</param>
 /// <param name="buf">The buffer to which to write.</param>
 /// <param name="lengthCache"></param>
 /// <param name="parameter">
 /// The <see cref="NpgsqlParameter"/> instance where this value resides. Can be used to access additional
 /// information relevant to the write process (e.g. <see cref="NpgsqlParameter.Size"/>).
 /// </param>
 /// <param name="async">If I/O is required to read the full length of the value, whether it should be performed synchronously or asynchronously.</param>
 protected internal abstract Task WriteObjectWithLength([CanBeNull] object value, NpgsqlWriteBuffer buf, NpgsqlLengthCache lengthCache, NpgsqlParameter parameter, bool async);
Beispiel #19
0
 public Task Write(PostgisMultiLineString value, NpgsqlWriteBuffer buf, NpgsqlLengthCache lengthCache, NpgsqlParameter parameter, bool async)
 => Write((PostgisGeometry)value, buf, lengthCache, parameter, async);
Beispiel #20
0
        protected internal override Task WriteObjectWithLength(object value, NpgsqlWriteBuffer buf, NpgsqlLengthCache lengthCache, NpgsqlParameter parameter, bool async)
        {
            if (value == null || value is DBNull)
            {
                return(base.WriteObjectWithLength(value, buf, lengthCache, parameter, async));
            }

            buf.WriteInt32(ValidateObjectAndGetLength(value, ref lengthCache, parameter));
            return(base.Write(
                       value is string asString
                    ? asString
                    : (string)parameter.ConvertedValue,
                       buf, lengthCache, parameter, async));
        }
Beispiel #21
0
 public Task Write(byte[] value, NpgsqlWriteBuffer buf, NpgsqlLengthCache lengthCache, NpgsqlParameter parameter, bool async)
 => _byteaHandler == null
         ? throw new NpgsqlException("Bytea handler was not found during initialization of PostGIS handler")
         : _byteaHandler.Write(value, buf, lengthCache, parameter, async);
Beispiel #22
0
        // Allow writing anything that is a string or can be converted to one via the unknown type handler

        public override int ValidateAndGetLength <T2>(T2 value, ref NpgsqlLengthCache lengthCache, NpgsqlParameter parameter)
        => ValidateObjectAndGetLength(value, ref lengthCache, parameter);
Beispiel #23
0
 public int ValidateAndGetLength(BitVector32 value, ref NpgsqlLengthCache lengthCache, NpgsqlParameter parameter)
 => value.Data == 0 ? 4 : 8;
 public override async Task Write(NpgsqlRange <TElement> value, NpgsqlWriteBuffer buf, NpgsqlLengthCache lengthCache, NpgsqlParameter parameter, bool async)
 {
     if (buf.WriteSpaceLeft < 1)
     {
         await buf.Flush(async);
     }
     buf.WriteByte((byte)value.Flags);
     if (value.IsEmpty)
     {
         return;
     }
     if (!value.LowerBoundInfinite)
     {
         await ElementHandler.WriteWithLengthInternal(value.LowerBound, buf, lengthCache, null, async);
     }
     if (!value.UpperBoundInfinite)
     {
         await ElementHandler.WriteWithLengthInternal(value.UpperBound, buf, lengthCache, null, async);
     }
 }
Beispiel #25
0
 public override async Task Write(ArraySegment <char> value, NpgsqlWriteBuffer buf, NpgsqlLengthCache lengthCache, NpgsqlParameter parameter, bool async)
 {
     if (buf.WriteSpaceLeft < 1)
     {
         await buf.Flush(async);
     }
     buf.WriteByte(JsonbProtocolVersion);
     await base.Write(value, buf, lengthCache, parameter, async);
 }
Beispiel #26
0
 public override int ValidateAndGetLength(PostgisGeometry value, ref NpgsqlLengthCache lengthCache, NpgsqlParameter parameter)
 => value.GetLen(true);
        protected override Task WriteObjectWithLength(object value, NpgsqlWriteBuffer buf, NpgsqlLengthCache lengthCache, NpgsqlParameter parameter, bool async)
        {
            if (parameter?.ConvertedValue != null)
            {
                value = parameter.ConvertedValue;
            }
            var s = value as string ?? JsonConvert.SerializeObject(value);

            return(base.WriteObjectWithLength(s, buf, lengthCache, parameter, async));
        }
Beispiel #28
0
 public int ValidateAndGetLength(PostgisPolygon value, ref NpgsqlLengthCache lengthCache, NpgsqlParameter parameter)
 => value.GetLen(true);
Beispiel #29
0
 /// <inheritdoc />
 public int ValidateAndGetLength(ArraySegment <byte> value, ref NpgsqlLengthCache lengthCache, NpgsqlParameter parameter)
 => parameter == null || parameter.Size <= 0 || parameter.Size >= value.Count
         ? value.Count
         : parameter.Size;
Beispiel #30
0
 public int ValidateAndGetLength(PostgisMultiLineString value, ref NpgsqlLengthCache lengthCache, NpgsqlParameter parameter)
 => value.GetLen(true);