提交 12114244 编写于 作者: S Shay Rojansky

Mapping additions and fixes

* Added missing mappings
* Completed literal generation for all mappings and added tests
上级 953889a7
......@@ -14,7 +14,7 @@ public class NpgsqlJsonTypeMapping : NpgsqlTypeMapping
public NpgsqlJsonTypeMapping() : base("json", typeof(string), NpgsqlDbType.Json) {}
protected override string GenerateNonNullSqlLiteral(object value)
=> $"'{EscapeSqlLiteral((string)value)}'";
=> $"JSON '{EscapeSqlLiteral((string)value)}'";
string EscapeSqlLiteral([NotNull] string literal)
=> Check.NotNull(literal, nameof(literal)).Replace("'", "''");
......
......@@ -14,7 +14,7 @@ public class NpgsqlJsonbTypeMapping : NpgsqlTypeMapping
public NpgsqlJsonbTypeMapping() : base("jsonb", typeof(string), NpgsqlDbType.Jsonb) {}
protected override string GenerateNonNullSqlLiteral(object value)
=> $"'{EscapeSqlLiteral((string)value)}'";
=> $"JSONB '{EscapeSqlLiteral((string)value)}'";
string EscapeSqlLiteral([NotNull] string literal)
=> Check.NotNull(literal, nameof(literal)).Replace("'", "''");
......
......@@ -13,6 +13,14 @@ public class NpgsqlBitTypeMapping : NpgsqlTypeMapping
public NpgsqlBitTypeMapping() : base("bit", typeof(BitArray), NpgsqlDbType.Bit) {}
protected override string GenerateNonNullSqlLiteral(object value)
=> ((BitArray)value).ToString();
}
{
var bits = (BitArray)value;
var sb = new StringBuilder();
sb.Append("BIT B'");
for (var i = 0; i < bits.Count; i++)
sb.Append(bits[i] ? '1' : '0');
sb.Append('\'');
return sb.ToString();
} }
}
using System.Globalization;
using NpgsqlTypes;
namespace Microsoft.EntityFrameworkCore.Storage.Internal.Mapping
{
public class NpgsqlBoxTypeMapping : NpgsqlTypeMapping
{
public NpgsqlBoxTypeMapping() : base("box", typeof(NpgsqlBox), NpgsqlDbType.Box) {}
protected override string GenerateNonNullSqlLiteral(object value)
{
var box = (NpgsqlBox)value;
var right = box.Right.ToString("G17", CultureInfo.InvariantCulture);
var top = box.Top.ToString("G17", CultureInfo.InvariantCulture);
var left = box.Left.ToString("G17", CultureInfo.InvariantCulture);
var bottom = box.Bottom.ToString("G17", CultureInfo.InvariantCulture);
return $"({right},{top},{left},{bottom})";
}
}
}
......@@ -38,7 +38,7 @@ protected override string GenerateNonNullSqlLiteral(object value)
var builder = new StringBuilder(bytea.Length * 2 + 6);
builder.Append("E'\\\\x");
builder.Append("BYTEA E'\\\\x");
foreach (var b in bytea)
builder.Append(b.ToString("X2", CultureInfo.InvariantCulture));
builder.Append('\'');
......
using System.Globalization;
using NpgsqlTypes;
namespace Microsoft.EntityFrameworkCore.Storage.Internal.Mapping
{
public class NpgsqlCircleTypeMapping : NpgsqlTypeMapping
{
public NpgsqlCircleTypeMapping() : base("circle", typeof(NpgsqlCircle), NpgsqlDbType.Circle) {}
protected override string GenerateNonNullSqlLiteral(object value)
{
var circle = (NpgsqlCircle)value;
var x = circle.X.ToString("G17", CultureInfo.InvariantCulture);
var y = circle.Y.ToString("G17", CultureInfo.InvariantCulture);
var radius = circle.Radius.ToString("G17", CultureInfo.InvariantCulture);
return $"(({x},{y}),{radius})";
}
}
}
using System;
using Microsoft.EntityFrameworkCore.Storage.Converters;
using NpgsqlTypes;
namespace Microsoft.EntityFrameworkCore.Storage.Internal.Mapping
{
public class NpgsqlTimestampTypeMapping : NpgsqlTypeMapping
{
public NpgsqlTimestampTypeMapping() : base("timestamp without time zone", typeof(DateTime), NpgsqlDbType.Timestamp) {}
protected override string GenerateNonNullSqlLiteral(object value)
=> $"TIMESTAMP '{(DateTime)value:yyyy-MM-dd HH:mm:ss.FFF}'";
}
public class NpgsqlTimestampTzTypeMapping : NpgsqlTypeMapping
{
public NpgsqlTimestampTzTypeMapping() : base("timestamp with time zone", typeof(DateTime), NpgsqlDbType.TimestampTZ) {}
protected override string GenerateNonNullSqlLiteral(object value)
{
var dt = (DateTime)value;
var tz = dt.Kind == DateTimeKind.Local
? $"{dt:zzz}"
: " UTC";
return $"TIMESTAMPTZ '{dt:yyyy-MM-dd HH:mm:ss.FFF}{tz}'";
}
}
public class NpgsqlDateTypeMapping : RelationalTypeMapping
{
public NpgsqlDateTypeMapping()
: this(null) {}
public NpgsqlDateTypeMapping(ValueConverter converter)
: base("date", typeof(DateTime), converter, null, System.Data.DbType.Date) {}
public override RelationalTypeMapping Clone(string storeType, int? size)
=> new NpgsqlDateTypeMapping(Converter);
protected override string GenerateNonNullSqlLiteral(object value)
=> $"DATE '{(DateTime)value:yyyy-MM-dd}'";
}
public class NpgsqlTimeTypeMapping : NpgsqlTypeMapping
{
public NpgsqlTimeTypeMapping() : base("time without time zone", typeof(DateTime), NpgsqlDbType.Time) {}
protected override string GenerateNonNullSqlLiteral(object value)
=> $"TIME '{(DateTime)value:HH:mm:ss.FFF}'";
}
public class NpgsqlTimeTzTypeMapping : NpgsqlTypeMapping
{
public NpgsqlTimeTzTypeMapping() : base("time with time zone", typeof(DateTimeOffset), NpgsqlDbType.TimeTZ) {}
protected override string GenerateNonNullSqlLiteral(object value)
=> $"TIMETZ '{(DateTimeOffset)value:HH:mm:ss.FFFz}'";
}
public class NpgsqlIntervalTypeMapping : NpgsqlTypeMapping
{
public NpgsqlIntervalTypeMapping() : base("interval", typeof(TimeSpan), NpgsqlDbType.Interval) {}
protected override string GenerateNonNullSqlLiteral(object value)
{
var ts = (TimeSpan)value;
return $"INTERVAL '{ts.ToString($@"{(ts < TimeSpan.Zero ? "\\-" : "")}{(ts.Days == 0 ? "" : "d\\ ")}hh\:mm\:ss{(ts.Milliseconds == 0 ? "" : $"\\.FFF")}")}'";
}
}
}
using System;
using Microsoft.EntityFrameworkCore.Storage.Converters;
namespace Microsoft.EntityFrameworkCore.Storage.Internal.Mapping
{
public class NpgsqlDateTypeMapping : RelationalTypeMapping
{
public NpgsqlDateTypeMapping()
: this(null) {}
public NpgsqlDateTypeMapping(ValueConverter converter)
: base("date", typeof(DateTime), converter, null, System.Data.DbType.Date) {}
public override RelationalTypeMapping Clone(string storeType, int? size)
=> new NpgsqlDateTypeMapping(Converter);
protected override string GenerateNonNullSqlLiteral(object value)
=> ((DateTime)value).ToString("yyyy-MM-dd");
}
}
using System.Globalization;
using System.Text;
using NpgsqlTypes;
namespace Microsoft.EntityFrameworkCore.Storage.Internal.Mapping
{
public class NpgsqlPointTypeMapping : NpgsqlTypeMapping
{
public NpgsqlPointTypeMapping() : base("point", typeof(NpgsqlPoint), NpgsqlDbType.Point) {}
protected override string GenerateNonNullSqlLiteral(object value)
{
var point = (NpgsqlPoint)value;
return $"POINT '({point.X.ToString("G17", CultureInfo.InvariantCulture)},{point.Y.ToString("G17", CultureInfo.InvariantCulture)})'";
}
}
public class NpgsqlLineTypeMapping : NpgsqlTypeMapping
{
public NpgsqlLineTypeMapping() : base("line", typeof(NpgsqlLine), NpgsqlDbType.Line) {}
protected override string GenerateNonNullSqlLiteral(object value)
{
var line = (NpgsqlLine)value;
return $"LINE '{{{line.A.ToString("G17", CultureInfo.InvariantCulture)},{line.B.ToString("G17", CultureInfo.InvariantCulture)},{line.C.ToString("G17", CultureInfo.InvariantCulture)}}}'";
}
}
public class NpgsqlLineSegmentTypeMapping : NpgsqlTypeMapping
{
public NpgsqlLineSegmentTypeMapping() : base("lseg", typeof(NpgsqlLSeg), NpgsqlDbType.LSeg) {}
protected override string GenerateNonNullSqlLiteral(object value)
{
var lseg = (NpgsqlLSeg)value;
var x1 = lseg.Start.X.ToString("G17", CultureInfo.InvariantCulture);
var y1 = lseg.Start.Y.ToString("G17", CultureInfo.InvariantCulture);
var x2 = lseg.End.X.ToString("G17", CultureInfo.InvariantCulture);
var y2 = lseg.End.Y.ToString("G17", CultureInfo.InvariantCulture);
return $"LSEG '[({x1},{y1}),({x2},{y2})]'";
}
}
public class NpgsqlBoxTypeMapping : NpgsqlTypeMapping
{
public NpgsqlBoxTypeMapping() : base("box", typeof(NpgsqlBox), NpgsqlDbType.Box) {}
protected override string GenerateNonNullSqlLiteral(object value)
{
var box = (NpgsqlBox)value;
var right = box.Right.ToString("G17", CultureInfo.InvariantCulture);
var top = box.Top.ToString("G17", CultureInfo.InvariantCulture);
var left = box.Left.ToString("G17", CultureInfo.InvariantCulture);
var bottom = box.Bottom.ToString("G17", CultureInfo.InvariantCulture);
return $"BOX '(({right},{top}),({left},{bottom}))'";
}
}
public class NpgsqlPathTypeMapping : NpgsqlTypeMapping
{
public NpgsqlPathTypeMapping() : base("path", typeof(NpgsqlPath), NpgsqlDbType.Path) {}
protected override string GenerateNonNullSqlLiteral(object value)
{
var path = (NpgsqlPath)value;
var sb = new StringBuilder();
sb.Append("PATH '");
sb.Append(path.Open ? '[' : '(');
for (var i = 0; i < path.Count; i++)
{
sb.Append('(');
sb.Append(path[i].X.ToString("G17", CultureInfo.InvariantCulture));
sb.Append(',');
sb.Append(path[i].Y.ToString("G17", CultureInfo.InvariantCulture));
sb.Append(')');
if (i < path.Count - 1)
sb.Append(',');
}
sb.Append(path.Open ? ']' : ')');
sb.Append('\'');
return sb.ToString();
}
}
public class NpgsqlPolygonTypeMapping : NpgsqlTypeMapping
{
public NpgsqlPolygonTypeMapping() : base("polygon", typeof(NpgsqlPolygon), NpgsqlDbType.Polygon) {}
protected override string GenerateNonNullSqlLiteral(object value)
{
var polygon = (NpgsqlPolygon)value;
var sb = new StringBuilder();
sb.Append("POLYGON '(");
for (var i = 0; i < polygon.Count; i++)
{
sb.Append('(');
sb.Append(polygon[i].X.ToString("G17", CultureInfo.InvariantCulture));
sb.Append(',');
sb.Append(polygon[i].Y.ToString("G17", CultureInfo.InvariantCulture));
sb.Append(')');
if (i < polygon.Count - 1)
sb.Append(',');
}
sb.Append(")'");
return sb.ToString();
}
}
public class NpgsqlCircleTypeMapping : NpgsqlTypeMapping
{
public NpgsqlCircleTypeMapping() : base("circle", typeof(NpgsqlCircle), NpgsqlDbType.Circle) {}
protected override string GenerateNonNullSqlLiteral(object value)
{
var circle = (NpgsqlCircle)value;
var x = circle.X.ToString("G17", CultureInfo.InvariantCulture);
var y = circle.Y.ToString("G17", CultureInfo.InvariantCulture);
var radius = circle.Radius.ToString("G17", CultureInfo.InvariantCulture);
return $"CIRCLE '<({x},{y}),{radius}>'";
}
}
}
......@@ -12,7 +12,7 @@ public class NpgsqlHstoreTypeMapping : NpgsqlTypeMapping
protected override string GenerateNonNullSqlLiteral(object value)
{
var sb = new StringBuilder("'");
var sb = new StringBuilder("HSTORE '");
foreach (var kv in (Dictionary<string, string>)value)
{
sb.Append('"');
......@@ -30,7 +30,7 @@ protected override string GenerateNonNullSqlLiteral(object value)
sb.Remove(sb.Length - 1, 1);
sb.Append("'::hstore");
sb.Append('\'');
return sb.ToString();
}
}
......
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Net.NetworkInformation;
using System.Text;
using NpgsqlTypes;
namespace Microsoft.EntityFrameworkCore.Storage.Internal.Mapping
{
public class NpgsqlIntervalTypeMapping : NpgsqlTypeMapping
/// <remarks>
/// This mapping is only used in Npgsql 3.2 and below.
/// Later versions use type plugins to set up mappings, and corresponding EF Core
/// plugins need to be used.
/// </remarks>
public class NpgsqlLegacyPostgisTypeMapping : NpgsqlTypeMapping
{
public NpgsqlIntervalTypeMapping() : base("interval", typeof(TimeSpan), NpgsqlDbType.Interval) {}
protected override string GenerateNonNullSqlLiteral(object value)
=> throw new NotImplementedException();
public NpgsqlLegacyPostgisTypeMapping() : base("geometry", typeof(PostgisGeometry), NpgsqlDbType.Geometry) {}
}
}
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Net.NetworkInformation;
using System.Text;
using NpgsqlTypes;
namespace Microsoft.EntityFrameworkCore.Storage.Internal.Mapping
{
public class NpgsqlLineSegmentTypeMapping : NpgsqlTypeMapping
{
public NpgsqlLineSegmentTypeMapping() : base("lseg", typeof(NpgsqlLSeg), NpgsqlDbType.LSeg) {}
protected override string GenerateNonNullSqlLiteral(object value)
{
var lseg = (NpgsqlLSeg)value;
var x1 = lseg.Start.X.ToString("G17", CultureInfo.InvariantCulture);
var y1 = lseg.Start.Y.ToString("G17", CultureInfo.InvariantCulture);
var x2 = lseg.End.X.ToString("G17", CultureInfo.InvariantCulture);
var y2 = lseg.End.Y.ToString("G17", CultureInfo.InvariantCulture);
return $"(({x1}, {y2}), ({x2}, {y2}))";
}
}
}
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Net.NetworkInformation;
using System.Text;
using NpgsqlTypes;
namespace Microsoft.EntityFrameworkCore.Storage.Internal.Mapping
{
public class NpgsqlLineTypeMapping : NpgsqlTypeMapping
{
public NpgsqlLineTypeMapping() : base("line", typeof(NpgsqlLine), NpgsqlDbType.Line) {}
protected override string GenerateNonNullSqlLiteral(object value)
{
var line = (NpgsqlLine)value;
return $"({line.A.ToString("G17", CultureInfo.InvariantCulture)},{line.B.ToString("G17", CultureInfo.InvariantCulture)},{line.C.ToString("G17", CultureInfo.InvariantCulture)})";
}
}
}
......@@ -10,10 +10,32 @@ namespace Microsoft.EntityFrameworkCore.Storage.Internal.Mapping
public class NpgsqlMacaddrTypeMapping : NpgsqlTypeMapping
{
public NpgsqlMacaddrTypeMapping() : base("macaddr", typeof(PhysicalAddress), NpgsqlDbType.MacAddr) {}
protected override string GenerateNonNullSqlLiteral(object value)
=> $"MACADDR '{(PhysicalAddress)value}'";
}
public class NpgsqlMacaddr8TypeMapping : NpgsqlTypeMapping
{
public NpgsqlMacaddr8TypeMapping() : base("macaddr8", typeof(PhysicalAddress), NpgsqlDbType.MacAddr) {}
protected override string GenerateNonNullSqlLiteral(object value)
=> $"MACADDR8 '{(PhysicalAddress)value}'";
}
public class NpgsqlInetTypeMapping : NpgsqlTypeMapping
{
public NpgsqlInetTypeMapping() : base("inet", typeof(IPAddress), NpgsqlDbType.Inet) {}
protected override string GenerateNonNullSqlLiteral(object value)
=> $"INET '{(IPAddress)value}'";
}
public class NpgsqlCidrTypeMapping : NpgsqlTypeMapping
{
public NpgsqlCidrTypeMapping() : base("cidr", typeof(NpgsqlInet), NpgsqlDbType.Cidr) {}
protected override string GenerateNonNullSqlLiteral(object value)
=> $"CIDR '{(NpgsqlInet)value}'";
}
}
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Net.NetworkInformation;
using System.Text;
using NpgsqlTypes;
namespace Microsoft.EntityFrameworkCore.Storage.Internal.Mapping
{
public class NpgsqlPathTypeMapping : NpgsqlTypeMapping
{
public NpgsqlPathTypeMapping() : base("path", typeof(NpgsqlPath), NpgsqlDbType.Path) {}
protected override string GenerateNonNullSqlLiteral(object value)
{
var path = (NpgsqlPath)value;
var sb = new StringBuilder();
sb.Append(path.Open ? '[' : '(');
for (var i = 0; i < path.Count; i++)
{
sb.Append('(');
sb.Append(path[i].X.ToString("G17", CultureInfo.InvariantCulture));
sb.Append(',');
sb.Append(path[i].Y.ToString("G17", CultureInfo.InvariantCulture));
sb.Append(')');
if (i < path.Count - 1)
sb.Append(',');
}
sb.Append(path.Open ? ']' : ')');
return sb.ToString();
}
}
}
using System.Globalization;
using NpgsqlTypes;
namespace Microsoft.EntityFrameworkCore.Storage.Internal.Mapping
{
public class NpgsqlPointTypeMapping : NpgsqlTypeMapping
{
public NpgsqlPointTypeMapping() : base("point", typeof(NpgsqlPoint), NpgsqlDbType.Point) {}
protected override string GenerateNonNullSqlLiteral(object value)
{
var point = (NpgsqlPoint)value;
return $"({point.X.ToString("G17", CultureInfo.InvariantCulture)},{point.Y.ToString("G17", CultureInfo.InvariantCulture)})";
}
}
}
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Net.NetworkInformation;
using System.Text;
using NpgsqlTypes;
namespace Microsoft.EntityFrameworkCore.Storage.Internal.Mapping
{
public class NpgsqlPolygonTypeMapping : NpgsqlTypeMapping
{
public NpgsqlPolygonTypeMapping() : base("polygon", typeof(NpgsqlPolygon), NpgsqlDbType.Polygon) {}
protected override string GenerateNonNullSqlLiteral(object value)
{
var path = (NpgsqlPath)value;
var sb = new StringBuilder();
sb.Append('(');
for (var i = 0; i < path.Count; i++)
{
sb.Append('(');
sb.Append(path[i].X.ToString("G17", CultureInfo.InvariantCulture));
sb.Append(',');
sb.Append(path[i].Y.ToString("G17", CultureInfo.InvariantCulture));
sb.Append(')');
if (i < path.Count - 1)
sb.Append(',');
}
sb.Append(')');
return sb.ToString();
}
}
}
using System;
using NpgsqlTypes;
namespace Microsoft.EntityFrameworkCore.Storage.Internal.Mapping
{
public class NpgsqlTimeTypeMapping : NpgsqlTypeMapping
{
public NpgsqlTimeTypeMapping() : base("time without time zone", typeof(DateTime), NpgsqlDbType.Time) {}
protected override string GenerateNonNullSqlLiteral(object value)
=> throw new NotImplementedException();
}
}
using System;
using NpgsqlTypes;
namespace Microsoft.EntityFrameworkCore.Storage.Internal.Mapping
{
public class NpgsqlTimeTzTypeMapping : NpgsqlTypeMapping
{
public NpgsqlTimeTzTypeMapping() : base("time with time zone", typeof(DateTimeOffset), NpgsqlDbType.TimeTZ) {}
protected override string GenerateNonNullSqlLiteral(object value)
=> throw new NotImplementedException();
}
}
......@@ -2,6 +2,7 @@
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net.NetworkInformation;
using System.Text;
using NpgsqlTypes;
......@@ -13,6 +14,15 @@ public class NpgsqlVarbitTypeMapping : NpgsqlTypeMapping
public NpgsqlVarbitTypeMapping() : base("bit varying", typeof(BitArray), NpgsqlDbType.Varbit) {}
protected override string GenerateNonNullSqlLiteral(object value)
=> ((BitArray)value).ToString();
{
var bits = (BitArray)value;
var sb = new StringBuilder();
sb.Append("VARBIT B'");
for (var i = 0; i < bits.Count; i++)
sb.Append(bits[i] ? '1' : '0');
sb.Append('\'');
return sb.ToString();
}
}
}
......@@ -68,13 +68,15 @@ public class NpgsqlTypeMappingSource : RelationalTypeMappingSource
readonly NpgsqlJsonbTypeMapping _jsonb = new NpgsqlJsonbTypeMapping();
readonly NpgsqlJsonTypeMapping _json = new NpgsqlJsonTypeMapping();
readonly NpgsqlDateTypeMapping _date = new NpgsqlDateTypeMapping();
readonly DateTimeTypeMapping _timestamp = new DateTimeTypeMapping("timestamp without time zone", DbType.DateTime);
readonly DateTimeTypeMapping _timestamptz = new DateTimeTypeMapping("timestamp with time zone", DbType.DateTime);
readonly NpgsqlTimestampTypeMapping _timestamp = new NpgsqlTimestampTypeMapping();
readonly NpgsqlTimestampTzTypeMapping _timestamptz = new NpgsqlTimestampTzTypeMapping();
readonly NpgsqlIntervalTypeMapping _interval = new NpgsqlIntervalTypeMapping();
readonly NpgsqlTimeTypeMapping _time = new NpgsqlTimeTypeMapping();
readonly NpgsqlTimeTzTypeMapping _timetz = new NpgsqlTimeTzTypeMapping();
readonly NpgsqlMacaddrTypeMapping _macaddr = new NpgsqlMacaddrTypeMapping();
readonly NpgsqlMacaddr8TypeMapping _macaddr8 = new NpgsqlMacaddr8TypeMapping();
readonly NpgsqlInetTypeMapping _inet = new NpgsqlInetTypeMapping();
readonly NpgsqlCidrTypeMapping _cidr = new NpgsqlCidrTypeMapping();
readonly NpgsqlBitTypeMapping _bit = new NpgsqlBitTypeMapping();
readonly NpgsqlVarbitTypeMapping _varbit = new NpgsqlVarbitTypeMapping();
readonly NpgsqlHstoreTypeMapping _hstore = new NpgsqlHstoreTypeMapping();
......@@ -90,8 +92,6 @@ public class NpgsqlTypeMappingSource : RelationalTypeMappingSource
readonly NpgsqlCidTypeMapping _cid = new NpgsqlCidTypeMapping();
readonly NpgsqlRegtypeTypeMapping _regtype = new NpgsqlRegtypeTypeMapping();
// TODO: PostGIS? But the plugins in vNext...
#endregion Mappings
public NpgsqlTypeMappingSource([NotNull] TypeMappingSourceDependencies dependencies,
......@@ -139,7 +139,9 @@ public class NpgsqlTypeMappingSource : RelationalTypeMappingSource
{ "time with time zone", _timetz },
{ "timetz", _timetz },
{ "macaddr", _macaddr },
{ "macaddr8", _macaddr8 },
{ "inet", _inet },
{ "cidr", _cidr },
{ "bit", _bit },
{ "bit varying", _varbit },
{ "varbit", _varbit },
......@@ -186,6 +188,19 @@ public class NpgsqlTypeMappingSource : RelationalTypeMappingSource
_storeTypeMappings = new ConcurrentDictionary<string, RelationalTypeMapping>(storeTypeMappings);
_clrTypeMappings = new ConcurrentDictionary<Type, RelationalTypeMapping>(clrTypeMappings);
if (typeof(NpgsqlConnection).Assembly.GetName().Version < new Version(3, 3))
SetupLegacyPostgisMappings();
}
void SetupLegacyPostgisMappings()
{
// This mapping is only used in Npgsql 3.2 and below.
// Later versions use type plugins to set up mappings, and corresponding EF Core
// plugins need to be used.
var legacyPostgisMapping = new NpgsqlLegacyPostgisTypeMapping();
_storeTypeMappings["geometry"] = legacyPostgisMapping;
_clrTypeMappings[typeof(PostgisGeometry)] = legacyPostgisMapping;
}
protected override RelationalTypeMapping FindMapping(RelationalTypeMappingInfo mappingInfo)
......
using System;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.NetworkInformation;
using Microsoft.EntityFrameworkCore.Storage.Converters;
using Microsoft.EntityFrameworkCore.Storage.Internal;
using Microsoft.EntityFrameworkCore.TestUtilities;
using NpgsqlTypes;
using Xunit;
namespace Microsoft.EntityFrameworkCore.Storage
{
public class NpgsqlTypeMappingTest
{
#region Date/Time
[Fact]
public void GenerateSqlLiteral_returns_date_literal()
=> Assert.Equal("DATE '2015-03-12'",
GetMapping("date").GenerateSqlLiteral(new DateTime(2015, 3, 12)));
[Fact]
public void GenerateSqlLiteral_returns_timestamp_literal()
{
var mapping = GetMapping("timestamp");
Assert.Equal("TIMESTAMP '1997-12-17 07:37:16'",
mapping.GenerateSqlLiteral(new DateTime(1997, 12, 17, 7, 37, 16, DateTimeKind.Utc)));
Assert.Equal("TIMESTAMP '1997-12-17 07:37:16'",
mapping.GenerateSqlLiteral(new DateTime(1997, 12, 17, 7, 37, 16, DateTimeKind.Local)));
Assert.Equal("TIMESTAMP '1997-12-17 07:37:16'",
mapping.GenerateSqlLiteral(new DateTime(1997, 12, 17, 7, 37, 16, DateTimeKind.Unspecified)));
Assert.Equal("TIMESTAMP '1997-12-17 07:37:16.345'",
mapping.GenerateSqlLiteral(new DateTime(1997, 12, 17, 7, 37, 16, 345)));
}
[Fact]
public void GenerateSqlLiteral_returns_timestamptz_literal()
{
var mapping = GetMapping("timestamptz");
Assert.Equal("TIMESTAMPTZ '1997-12-17 07:37:16 UTC'",
mapping.GenerateSqlLiteral(new DateTime(1997, 12, 17, 7, 37, 16, DateTimeKind.Utc)));
Assert.Equal("TIMESTAMPTZ '1997-12-17 07:37:16 UTC'",
mapping.GenerateSqlLiteral(new DateTime(1997, 12, 17, 7, 37, 16, DateTimeKind.Unspecified)));
var offset = TimeZoneInfo.Local.BaseUtcOffset.Hours;
var offsetStr = offset < 10 ? $"0{offset}" : offset.ToString();
Assert.StartsWith($"TIMESTAMPTZ '1997-12-17 07:37:16+{offsetStr}",
mapping.GenerateSqlLiteral(new DateTime(1997, 12, 17, 7, 37, 16, DateTimeKind.Local)));
Assert.Equal("TIMESTAMPTZ '1997-12-17 07:37:16.345 UTC'",
mapping.GenerateSqlLiteral(new DateTime(1997, 12, 17, 7, 37, 16, 345, DateTimeKind.Utc)));
}
[Fact]
public void GenerateSqlLiteral_returns_time_literal()
{
var mapping = GetMapping("time");
Assert.Equal("TIME '04:05:06.789'", mapping.GenerateSqlLiteral(new DateTime(2015, 3, 12, 4, 5, 6, 789)));
Assert.Equal("TIME '04:05:06'", mapping.GenerateSqlLiteral(new DateTime(2015, 3, 12, 4, 5, 6)));
}
[Fact]
public void GenerateSqlLiteral_returns_timetz_literal()
{
var mapping = GetMapping("timetz");
Assert.Equal("TIMETZ '04:05:06.789+3'", mapping.GenerateSqlLiteral(new DateTimeOffset(2015, 3, 12, 4, 5, 6, 789, TimeSpan.FromHours(3))));
Assert.Equal("TIMETZ '04:05:06-3'", mapping.GenerateSqlLiteral(new DateTimeOffset(2015, 3, 12, 4, 5, 6, TimeSpan.FromHours(-3))));
}
[Fact]
public void GenerateSqlLiteral_returns_interval_literal()
{
var mapping = GetMapping("interval");
Assert.Equal("INTERVAL '3 04:05:06.007'", mapping.GenerateSqlLiteral(new TimeSpan(3, 4, 5, 6, 7)));
Assert.Equal("INTERVAL '3 04:05:06'", mapping.GenerateSqlLiteral(new TimeSpan(3, 4, 5, 6)));
Assert.Equal("INTERVAL '04:05:06'", mapping.GenerateSqlLiteral(new TimeSpan(4, 5, 6)));
Assert.Equal("INTERVAL '-3 04:05:06.007'", mapping.GenerateSqlLiteral(new TimeSpan(-3, -4, -5, -6, -7)));
}
#endregion Date/Time
#region Networking
[Fact]
public void GenerateSqlLiteral_returns_macaddr_literal()
=> Assert.Equal("MACADDR '001122334455'", GetMapping("macaddr").GenerateSqlLiteral(PhysicalAddress.Parse("00-11-22-33-44-55")));
[Fact]
public void GenerateSqlLiteral_returns_macaddr8_literal()
=> Assert.Equal("MACADDR8 '0011223344556677'", GetMapping("macaddr8").GenerateSqlLiteral(PhysicalAddress.Parse("00-11-22-33-44-55-66-77")));
[Fact]
public void GenerateSqlLiteral_returns_inet_literal()
=> Assert.Equal("INET '192.168.1.1'", GetMapping("inet").GenerateSqlLiteral(IPAddress.Parse("192.168.1.1")));
[Fact]
public void GenerateSqlLiteral_returns_cidr_literal()
=> Assert.Equal("CIDR '192.168.1.0/24'", GetMapping("cidr").GenerateSqlLiteral(new NpgsqlInet(IPAddress.Parse("192.168.1.0"), 24)));
#endregion Networking
#region Geometric
[Fact]
public void GenerateSqlLiteral_returns_point_literal()
=> Assert.Equal("POINT '(3.5,4.5)'", GetMapping("point").GenerateSqlLiteral(new NpgsqlPoint(3.5, 4.5)));
[Fact]
public void GenerateSqlLiteral_returns_line_literal()
=> Assert.Equal("LINE '{3.5,4.5,10}'", GetMapping("line").GenerateSqlLiteral(new NpgsqlLine(3.5, 4.5, 10)));
[Fact]
public void GenerateSqlLiteral_returns_lseg_literal()
=> Assert.Equal("LSEG '[(3.5,4.5),(5.5,6.5)]'", GetMapping("lseg").GenerateSqlLiteral(new NpgsqlLSeg(3.5, 4.5, 5.5, 6.5)));
[Fact]
public void GenerateSqlLiteral_returns_box_literal()
=> Assert.Equal("BOX '((2,1),(4,3))'", GetMapping("box").GenerateSqlLiteral(new NpgsqlBox(1, 2, 3, 4)));
[Fact]
public void GenerateSqlLiteral_returns_path_closed_literal()
=> Assert.Equal("PATH '((1,2),(3,4))'", GetMapping("path").GenerateSqlLiteral(new NpgsqlPath(
new NpgsqlPoint(1, 2),
new NpgsqlPoint(3, 4)
)));
[Fact]
public void GenerateSqlLiteral_returns_path_open_literal()
=> Assert.Equal("PATH '[(1,2),(3,4)]'", GetMapping("path").GenerateSqlLiteral(new NpgsqlPath(
new NpgsqlPoint(1, 2),
new NpgsqlPoint(3, 4)
) { Open = true }));
[Fact]
public void GenerateSqlLiteral_returns_polygon_literal()
=> Assert.Equal("POLYGON '((1,2),(3,4))'", GetMapping("polygon").GenerateSqlLiteral(new NpgsqlPolygon(
new NpgsqlPoint(1, 2),
new NpgsqlPoint(3, 4)
)));
[Fact]
public void GenerateSqlLiteral_returns_circle_literal()
=> Assert.Equal("CIRCLE '<(3.5,4.5),5.5>'", GetMapping("circle").GenerateSqlLiteral(new NpgsqlCircle(3.5, 4.5, 5.5)));
#endregion Geometric
#region Misc
[Fact]
public void GenerateSqlLiteral_returns_bool_literal()
=> Assert.Equal("TRUE", GetMapping("bool").GenerateSqlLiteral(true));
[Fact]
public void GenerateSqlLiteral_returns_varbit_literal()
=> Assert.Equal("VARBIT B'10'", GetMapping("varbit").GenerateSqlLiteral(new BitArray(new[] { true, false })));
[Fact]
public void GenerateSqlLiteral_returns_bit_literal()
=> Assert.Equal("BIT B'10'", GetMapping("bit").GenerateSqlLiteral(new BitArray(new[] { true, false })));
[Fact]
public void GenerateSqlLiteral_returns_array_literal()
=> Assert.Equal("ARRAY[3,4]", GetMapping(typeof(int[])).GenerateSqlLiteral(new[] {3, 4}));
[Fact]
public void GenerateSqlLiteral_returns_bytea_literal()
=> Assert.Equal(@"BYTEA E'\\xDEADBEEF'", GetMapping("bytea").GenerateSqlLiteral(new byte[] { 222, 173, 190, 239 }));
[Fact]
public void GenerateSqlLiteral_returns_hstore_literal()
=> Assert.Equal(@"HSTORE '""k1""=>""v1"",""k2""=>""v2""'",
GetMapping("hstore").GenerateSqlLiteral(new Dictionary<string, string>
{
{ "k1", "v1" },
{ "k2", "v2" }
}));
[Fact]
public void GenerateSqlLiteral_returns_jsonb_literal()
=> Assert.Equal(@"JSONB '{""a"":1}'", GetMapping("jsonb").GenerateSqlLiteral(@"{""a"":1}"));
[Fact]
public void GenerateSqlLiteral_returns_json_literal()
=> Assert.Equal(@"JSON '{""a"":1}'", GetMapping("json").GenerateSqlLiteral(@"{""a"":1}"));
#endregion Misc
#region Support
public static RelationalTypeMapping GetMapping(string storeType)
=> new NpgsqlTypeMappingSource(
new TypeMappingSourceDependencies (
new ValueConverterSelector(new ValueConverterSelectorDependencies())
), new RelationalTypeMappingSourceDependencies())
.FindMapping(storeType);
public static RelationalTypeMapping GetMapping(Type clrType)
=> (RelationalTypeMapping)new NpgsqlTypeMappingSource(
new TypeMappingSourceDependencies (
new ValueConverterSelector(new ValueConverterSelectorDependencies())
), new RelationalTypeMappingSourceDependencies())
.FindMapping(clrType);
#endregion Support
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册