Skip to content

Commit 4a503c7

Browse files
committed
Big refactor of type mapping system
* Significant redo of type mapping, mainly to support #1475 * All knowledge of PG types has been split out into DatabaseInfo. The PostgresType hierarchy no longer knows anything about mapping - it's purely about modeling pg_type and related. * Instead of a single TypeHandlerRegistry with special mechanisms for enum/composite, we now have a global type mapper and a connection type mapper, allowing all mappings to be user-managed at the global and connection level. * Handlers are now bound eagerly at physical connection open, much simpler. * Made several internal types public, to support writing type handlers outside Npgsql.
1 parent a24d0eb commit 4a503c7

121 files changed

Lines changed: 2913 additions & 2062 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/Npgsql/BackendMessages/AuthenticationMessages.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ class AuthenticationMD5PasswordMessage : AuthenticationRequestMessage
5959

6060
internal byte[] Salt { get; private set; }
6161

62-
internal static AuthenticationMD5PasswordMessage Load(ReadBuffer buf)
62+
internal static AuthenticationMD5PasswordMessage Load(NpgsqlReadBuffer buf)
6363
{
6464
var salt = new byte[4];
6565
buf.ReadBytes(salt, 0, 4);
@@ -94,7 +94,7 @@ class AuthenticationGSSContinueMessage : AuthenticationRequestMessage
9494

9595
internal byte[] AuthenticationData { get; private set; }
9696

97-
internal static AuthenticationGSSContinueMessage Load(ReadBuffer buf, int len)
97+
internal static AuthenticationGSSContinueMessage Load(NpgsqlReadBuffer buf, int len)
9898
{
9999
len -= 4; // The AuthRequestType code
100100
var authenticationData = new byte[len];

src/Npgsql/BackendMessages/BackendKeyDataMessage.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class BackendKeyDataMessage : IBackendMessage
3030
internal int BackendProcessId { get; private set; }
3131
internal int BackendSecretKey { get; private set; }
3232

33-
internal BackendKeyDataMessage(ReadBuffer buf)
33+
internal BackendKeyDataMessage(NpgsqlReadBuffer buf)
3434
{
3535
BackendProcessId = buf.ReadInt32();
3636
BackendSecretKey = buf.ReadInt32();

src/Npgsql/BackendMessages/CommandCompleteMessage.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ class CommandCompleteMessage : IBackendMessage
3535
internal uint OID { get; private set; }
3636
internal uint Rows { get; private set; }
3737

38-
internal CommandCompleteMessage Load(ReadBuffer buf, int len)
38+
internal CommandCompleteMessage Load(NpgsqlReadBuffer buf, int len)
3939
{
4040
Rows = 0;
4141
OID = 0;

src/Npgsql/BackendMessages/CopyMessages.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ internal CopyResponseMessageBase()
3939
ColumnFormatCodes = new List<FormatCode>();
4040
}
4141

42-
internal void Load(ReadBuffer buf)
42+
internal void Load(NpgsqlReadBuffer buf)
4343
{
4444
ColumnFormatCodes.Clear();
4545

@@ -65,7 +65,7 @@ class CopyInResponseMessage : CopyResponseMessageBase
6565
{
6666
public override BackendMessageCode Code => BackendMessageCode.CopyInResponse;
6767

68-
internal new CopyInResponseMessage Load(ReadBuffer buf)
68+
internal new CopyInResponseMessage Load(NpgsqlReadBuffer buf)
6969
{
7070
base.Load(buf);
7171
return this;
@@ -76,7 +76,7 @@ class CopyOutResponseMessage : CopyResponseMessageBase
7676
{
7777
public override BackendMessageCode Code => BackendMessageCode.CopyOutResponse;
7878

79-
internal new CopyOutResponseMessage Load(ReadBuffer buf)
79+
internal new CopyOutResponseMessage Load(NpgsqlReadBuffer buf)
8080
{
8181
base.Load(buf);
8282
return this;
@@ -87,7 +87,7 @@ class CopyBothResponseMessage : CopyResponseMessageBase
8787
{
8888
public override BackendMessageCode Code => BackendMessageCode.CopyBothResponse;
8989

90-
internal new CopyBothResponseMessage Load(ReadBuffer buf)
90+
internal new CopyBothResponseMessage Load(NpgsqlReadBuffer buf)
9191
{
9292
base.Load(buf);
9393
return this;
@@ -122,7 +122,7 @@ class CopyDoneMessage : SimpleFrontendMessage, IBackendMessage
122122

123123
internal override int Length => 5;
124124

125-
internal override void WriteFully(WriteBuffer buf)
125+
internal override void WriteFully(NpgsqlWriteBuffer buf)
126126
{
127127
buf.WriteByte((byte)BackendMessageCode.CopyDone);
128128
buf.WriteInt32(4);

src/Npgsql/BackendMessages/ErrorOrNoticeMessage.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ class ErrorOrNoticeMessage
5555
static readonly NpgsqlLogger Log = NpgsqlLogManager.GetCurrentClassLogger();
5656

5757
// ReSharper disable once FunctionComplexityOverflow
58-
internal ErrorOrNoticeMessage(ReadBuffer buf)
58+
internal ErrorOrNoticeMessage(NpgsqlReadBuffer buf)
5959
{
6060
while (true)
6161
{

src/Npgsql/BackendMessages/ParameterDescriptionMessage.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ internal ParameterDescriptionMessage()
3838
TypeOIDs = new List<uint>();
3939
}
4040

41-
internal ParameterDescriptionMessage Load(ReadBuffer buf)
41+
internal ParameterDescriptionMessage Load(NpgsqlReadBuffer buf)
4242
{
4343
var numParams = buf.ReadInt16();
4444
TypeOIDs.Clear();

src/Npgsql/BackendMessages/ReadyForQueryMessage.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class ReadyForQueryMessage : IBackendMessage
2929

3030
internal TransactionStatus TransactionStatusIndicator { get; private set; }
3131

32-
internal ReadyForQueryMessage Load(ReadBuffer buf) {
32+
internal ReadyForQueryMessage Load(NpgsqlReadBuffer buf) {
3333
TransactionStatusIndicator = (TransactionStatus)buf.ReadByte();
3434
return this;
3535
}

src/Npgsql/BackendMessages/RowDescriptionMessage.cs

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
using JetBrains.Annotations;
2828
using Npgsql.PostgresTypes;
2929
using Npgsql.TypeHandlers;
30+
using Npgsql.TypeMapping;
3031

3132
namespace Npgsql.BackendMessages
3233
{
@@ -49,7 +50,7 @@ internal RowDescriptionMessage()
4950
_caseInsensitiveNameIndex = new Dictionary<string, int>(KanaWidthCaseInsensitiveComparer.Instance);
5051
}
5152

52-
internal RowDescriptionMessage Load(ReadBuffer buf, TypeHandlerRegistry typeHandlerRegistry)
53+
internal RowDescriptionMessage Load(NpgsqlReadBuffer buf, ConnectorTypeMapper typeMapper)
5354
{
5455
Fields.Clear();
5556
_nameIndex.Clear();
@@ -61,7 +62,7 @@ internal RowDescriptionMessage Load(ReadBuffer buf, TypeHandlerRegistry typeHand
6162
// TODO: Recycle
6263
var field = new FieldDescription();
6364
field.Populate(
64-
typeHandlerRegistry,
65+
typeMapper,
6566
buf.ReadNullTerminatedString(), // Name
6667
buf.ReadUInt32(), // TableOID
6768
buf.ReadInt16(), // ColumnAttributeNumber
@@ -148,14 +149,14 @@ public int GetHashCode([NotNull] string o)
148149
/// A descriptive record on a single field received from PostgreSQL.
149150
/// See RowDescription in http://www.postgresql.org/docs/current/static/protocol-message-formats.html
150151
/// </summary>
151-
sealed class FieldDescription
152+
public sealed class FieldDescription
152153
{
153154
internal void Populate(
154-
TypeHandlerRegistry typeHandlerRegistry, string name, uint tableOID, short columnAttributeNumber,
155+
ConnectorTypeMapper typeMapper, string name, uint tableOID, short columnAttributeNumber,
155156
uint oid, short typeSize, int typeModifier, FormatCode formatCode
156157
)
157158
{
158-
_typeHandlerRegistry = typeHandlerRegistry;
159+
_typeMapper = typeMapper;
159160
Name = name;
160161
TableOID = tableOID;
161162
ColumnAttributeNumber = columnAttributeNumber;
@@ -164,7 +165,7 @@ internal void Populate(
164165
TypeModifier = typeModifier;
165166
FormatCode = formatCode;
166167

167-
RealHandler = typeHandlerRegistry[TypeOID];
168+
RealHandler = typeMapper[TypeOID];
168169
ResolveHandler();
169170
}
170171

@@ -181,12 +182,12 @@ internal void Populate(
181182
/// <summary>
182183
/// The data type size (see pg_type.typlen). Note that negative values denote variable-width types.
183184
/// </summary>
184-
internal short TypeSize { get; set; }
185+
public short TypeSize { get; set; }
185186

186187
/// <summary>
187188
/// The type modifier (see pg_attribute.atttypmod). The meaning of the modifier is type-specific.
188189
/// </summary>
189-
internal int TypeModifier { get; set; }
190+
public int TypeModifier { get; set; }
190191

191192
/// <summary>
192193
/// If the field can be identified as a column of a specific table, the object ID of the table; otherwise zero.
@@ -227,19 +228,19 @@ internal FormatCode FormatCode
227228
internal TypeHandler RealHandler { get; private set; }
228229

229230
internal PostgresType PostgresType => RealHandler.PostgresType;
230-
public Type FieldType => Handler.GetFieldType(this);
231+
internal Type FieldType => Handler.GetFieldType(this);
231232

232233
void ResolveHandler()
233234
{
234235
Handler = IsBinaryFormat
235-
? _typeHandlerRegistry[TypeOID]
236-
: _typeHandlerRegistry.UnrecognizedTypeHandler;
236+
? _typeMapper[TypeOID]
237+
: _typeMapper.UnrecognizedTypeHandler;
237238
}
238239

239-
TypeHandlerRegistry _typeHandlerRegistry;
240+
ConnectorTypeMapper _typeMapper;
240241

241-
public bool IsBinaryFormat => FormatCode == FormatCode.Binary;
242-
public bool IsTextFormat => FormatCode == FormatCode.Text;
242+
internal bool IsBinaryFormat => FormatCode == FormatCode.Binary;
243+
internal bool IsTextFormat => FormatCode == FormatCode.Text;
243244

244245
public override string ToString() => Name + (Handler == null ? "" : $"({Handler.PgDisplayName})");
245246
}

src/Npgsql/Common.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ abstract class FrontendMessage
5050
/// Whether there was enough space in the buffer to contain the entire message.
5151
/// If false, the buffer should be flushed and write should be called again.
5252
/// </returns>
53-
internal abstract Task Write(WriteBuffer buf, bool async, CancellationToken cancellationToken);
53+
internal abstract Task Write(NpgsqlWriteBuffer buf, bool async, CancellationToken cancellationToken);
5454

5555
/// <summary>
5656
/// Returns how many messages PostgreSQL is expected to send in response to this message.
@@ -74,9 +74,9 @@ abstract class SimpleFrontendMessage : FrontendMessage
7474
/// <summary>
7575
/// Writes the message contents into the buffer.
7676
/// </summary>
77-
internal abstract void WriteFully(WriteBuffer buf);
77+
internal abstract void WriteFully(NpgsqlWriteBuffer buf);
7878

79-
internal sealed override Task Write(WriteBuffer buf, bool async, CancellationToken cancellationToken)
79+
internal sealed override Task Write(NpgsqlWriteBuffer buf, bool async, CancellationToken cancellationToken)
8080
{
8181
if (buf.WriteSpaceLeft < Length)
8282
return FlushAndWrite(buf, async, cancellationToken);
@@ -85,7 +85,7 @@ internal sealed override Task Write(WriteBuffer buf, bool async, CancellationTok
8585
return PGUtil.CompletedTask;
8686
}
8787

88-
async Task FlushAndWrite(WriteBuffer buf, bool async, CancellationToken cancellationToken)
88+
async Task FlushAndWrite(NpgsqlWriteBuffer buf, bool async, CancellationToken cancellationToken)
8989
{
9090
await buf.Flush(async, cancellationToken);
9191
Debug.Assert(Length <= buf.WriteSpaceLeft, $"Message of type {GetType().Name} has length {Length} which is bigger than the buffer ({buf.WriteSpaceLeft})");

0 commit comments

Comments
 (0)