Pgnoli is a .NET implementation of the PostgreSQL wire protocol v3. It gives you some traits to implement your own PostgreSQL compatible servers (and client if there is case Npgsql does not fit).
Postgresql wire protocol is actually a general purpose Layer-7 application protocol. It is not bound with SQL, and can be used for any query language, data format or even natural language. It is possible to build a chat bot that use psql as client.
- (De)serialization of messages for Startup flow
- (De)serialization of messages for Simple Query flow
- (De)serialization of messages for Extended Query flow
- (De)serialization of types for binary encoding
- (De)serialization of types for text encoding
- Support of DateStyle for encoding Date/Time related types
Continuous integration builds:
Pgnoli is a .NET assembly and can be installed as a package next to your project with the help of Nuget CLI
or dotnet.exe
dotnet add package Pgnoli
When receiving a message from the client your solution can use the FrontendParser
class to deserialize the message contained in an array of bytes.
var parser = new FrontendParser();
var msg = parser.Parse(bytes);
The parser returns a strongly typed message implementing the interface IMessage
. Most of the messages inherits from the class CodeMessage
exposing a property Code of one char.
Once the message is parsed, you can access its payload, using the property Payload
. The content of the payload depends of the message class, i.e. for a Query message, the payload contains the SQL query.
var queryMsg = msg as Query;
Console.WriteLine(queryMsh.Sql);
To create a message, you can use the static methods offered by the class implementing these messages. These methods depends of the messages, i.e. to create a message ReadyForQuery
, you can use the static method Idle
.
To effectively get your message you should call the Build()
method.
var msg = ReadyForQuery.Idle.Build();
Some messages accept optional informations. You can communicate them with the help of With(...)
functions. i.e. the message Bind
can create messages for named and unnamed portals but also accept the different parameters and how the result should be serialized. This last element can be defined with the methods WithAllResultsAsText()
or WithAllResultsAsBinary()
or for each column of the result, we can define the encoding by chaining the calls to WithResultFormat(...)
.
var msg = Bind.Portal("destination", "source").WithAllResultsAsBinary().Build();
The handling of the encoding in both text and binary formats is done with the classes from the TypeHandlers
namespace.
However in most cases, you won't need them as the handling is directly managed within the class implementing the messages.