public override async Task WriteBackendValue( DataFormat dataFormat, PgSQLTypeDatabaseData boundData, BackendABIHelper helper, StreamWriterWithResizableBufferAndLimitedSize stream, Object value, BackendSizeInfo sizeInfo, Boolean isArrayElement ) { switch (dataFormat) { case DataFormat.Text: await this.WriteArrayText(boundData, helper, stream, (Array)value, sizeInfo); break; case DataFormat.Binary: await this.WriteArrayBinary(boundData, helper, stream, (Array)value, sizeInfo); break; default: throw new NotSupportedException($"Data format {dataFormat} is not recognized."); } }
protected override async Task DoSendMessageAsync( BackendABIHelper args, Stream stream, Int32 size, CancellationToken token, ResizableArray <Byte> array ) { // As documentation states, "For historical reasons, the very first message sent by the client (the startup message) has no initial message-type byte." // Hence we don't inherit the FrontEndMessageObjectWithCode class array.CurrentMaxCapacity = PREFIX; var idx = 0; array.Array .WritePgInt32(ref idx, size) .WritePgInt32(ref idx, this._protocolVersion); await stream.WriteAsync(array.Array, 0, PREFIX, token); foreach (var kvp in this._parameters) { await args.WriteString(stream, kvp.Key, token, array); await args.WriteString(stream, kvp.Value, token, array); } array.Array[0] = 0; await stream.WriteAsync(array.Array, 0, 1, token); }
protected override Int32 CalculateSize(BackendABIHelper args, ResizableArray <Byte> array) { return(args.GetStringSize(this._statementName, array) + args.GetStringSize(this._sql, array) + sizeof(Int16) + this._typeIDs.GetLengthOrDefault() * sizeof(Int32)); }
public override async ValueTask <Object> ReadBackendValue( DataFormat dataFormat, PgSQLTypeDatabaseData boundData, BackendABIHelper helper, StreamReaderWithResizableBufferAndLimitedSize stream ) { Array retVal; switch (dataFormat) { case DataFormat.Text: if (stream.TotalByteCount > 2 * helper.Encoding.BytesPerASCIICharacter) { retVal = await this.ReadArrayText(boundData, helper, stream); } else { // Empty array retVal = this._emptyArray; } break; case DataFormat.Binary: retVal = await this.ReadArrayBinary(boundData, helper, stream); break; default: throw new NotSupportedException($"Data format {dataFormat} is not recognized."); } return(retVal); }
public override async Task WriteBackendValue( DataFormat dataFormat, PgSQLTypeDatabaseData boundData, BackendABIHelper helper, StreamWriterWithResizableBufferAndLimitedSize stream, Object value, BackendSizeInfo additionalInfoFromSize, Boolean isArrayElement ) { // No truly async support for serializing JTokens in Newtonsoft, at least yet, so let's do it ourselves switch (dataFormat) { case DataFormat.Text: await stream.WriteJSONTTokenAsync(helper.Encoding, (JToken)value); break; case DataFormat.Binary: throw new InvalidOperationException("This data format is not supported"); default: throw new NotSupportedException($"Unrecognized data format: ${dataFormat}."); } }
protected override async Task PerformSendAfterWriteAsync( BackendABIHelper args, Stream stream, Int32 size, CancellationToken token, ResizableArray <Byte> buffer ) { await args.WriteString(stream, this._statementName, token, buffer); await args.WriteString(stream, this._sql, token, buffer); var typesCount = this._typeIDs.GetLengthOrDefault(); buffer.CurrentMaxCapacity = sizeof(Int16) + 4 * typesCount; var array = buffer.Array; var idx = 0; array.WritePgInt16(ref idx, typesCount); if (typesCount > 0) { foreach (var typeID in this._typeIDs) { array.WritePgInt32(ref idx, typeID); } } await stream.WriteAsync(array, 0, idx, token); }
protected override void WriteMessageToBuffer(BackendABIHelper args, ResizableArray <Byte> array) { var idx = 0; array.Array .WritePgString(ref idx, args.Encoding, this._portalName) .WritePgInt32(ref idx, this._maxRows); }
protected override void WriteMessageToBuffer(BackendABIHelper args, ResizableArray <Byte> array) { var idx = 0; array.Array .BlockCopyFrom(ref idx, this._pw) .WriteByteToBytes(ref idx, 0); }
protected override void WriteMessageToBuffer(BackendABIHelper args, ResizableArray <Byte> array) { var idx = 0; array.Array .WriteByteToBytes(ref idx, (Byte)(this._isStatement ? 'S' : 'P')) .WritePgString(ref idx, args.Encoding, this._name); }
protected override async Task PerformSendAfterWriteAsync( BackendABIHelper args, Stream stream, Int32 size, CancellationToken token, ResizableArray <Byte> array ) { await stream.WriteAsync(this._data, this._offset, this._count, token); }
private async ValueTask <(Int32 LowestEncounteredArrayEnd, Int32[] Lengths, Boolean HasMore)> ReadArrayTextDimensionEnd( PgSQLTypeDatabaseData boundData, BackendABIHelper helper, StreamReaderWithResizableBufferAndLimitedSize stream, Int32 lowestEncounteredArrayEnd, Int32[] lengths, Int32 rank ) { stream.EraseReadBytesFromBuffer(); var wasArrayEnd = true; var innermostArrayIndex = rank - 1; var curArrayIndex = innermostArrayIndex; Char curChar; var charReader = helper.CharacterReader; while (wasArrayEnd && --curArrayIndex >= 0) { // End current array block lowestEncounteredArrayEnd = Math.Min(lowestEncounteredArrayEnd, curArrayIndex); if (curArrayIndex <= lowestEncounteredArrayEnd) { lengths[curArrayIndex]++; } // Read next character curChar = await charReader.ReadNextCharacterAsync(stream); wasArrayEnd = curChar == ARRAY_END; } var hasMore = curArrayIndex >= 0; if (hasMore) { // More arrays follow // Read until we are at innermost array level again while (curArrayIndex < innermostArrayIndex) { curChar = await charReader.ReadNextCharacterAsync(stream); if (curChar == ARRAY_START) { ++curArrayIndex; } } } stream.EraseReadBytesFromBuffer(); return(lowestEncounteredArrayEnd, lengths, hasMore); }
protected sealed override async Task PerformSendAfterWriteAsync( BackendABIHelper args, Stream stream, Int32 size, CancellationToken token, ResizableArray <Byte> array ) { // Given size includes the integer that already has been written size -= sizeof(Int32); array.CurrentMaxCapacity = size; this.WriteMessageToBuffer(args, array); await stream.WriteAsync(array.Array, 0, size, token); }
protected override async Task DoSendMessageAsync( BackendABIHelper args, Stream stream, Int32 size, CancellationToken token, ResizableArray <Byte> array ) { var idx = 0; // We don't have front end message code, so we need to write size ourselves. array.Array .WritePgInt32(ref idx, size) .WritePgInt32(ref idx, 80877103); // As per spec await stream.WriteAsync(array.Array, 0, idx, token); }
public static async Task <(DataRowObject, Int32)> ReadDataRow( BackendABIHelper args, Stream stream, CancellationToken token, Byte[] array, ResizableArray <ResettableTransformable <Int32?, Int32> > columnSizes, Int32 msgSize ) { await stream.ReadSpecificAmountAsync(array, 0, sizeof(Int16), token); msgSize -= sizeof(Int16); var idx = 0; var colCount = array.ReadPgInt16Count(ref idx); return(new DataRowObject(args, colCount, columnSizes), msgSize); }
public PostgreSQLProtocol( PgSQLConnectionVendorFunctionality vendorFunctionality, Boolean disableBinaryProtocolSend, Boolean disableBinaryProtocolReceive, BackendABIHelper messageIOArgs, Stream stream, ResizableArray <Byte> buffer, Socket socket, IDictionary <String, String> serverParameters, TransactionStatus status, Int32 backendPID ) { this.DisableBinaryProtocolSend = disableBinaryProtocolSend; this.DisableBinaryProtocolReceive = disableBinaryProtocolReceive; this.MessageIOArgs = ArgumentValidator.ValidateNotNull(nameof(messageIOArgs), messageIOArgs); this.Stream = ArgumentValidator.ValidateNotNull(nameof(stream), stream); this.Socket = ArgumentValidator.ValidateNotNull(nameof(socket), socket); this.Buffer = buffer ?? new ResizableArray <Byte>(8, exponentialResize: true); this.DataRowColumnSizes = new ResizableArray <ResettableTransformable <Int32?, Int32> >(exponentialResize: false); this._serverParameters = ArgumentValidator.ValidateNotNull(nameof(serverParameters), serverParameters); this.TypeRegistry = new TypeRegistryImpl(vendorFunctionality, this); if (serverParameters.TryGetValue("server_version", out var serverVersionString)) { // Parse server version var i = 0; var version = serverVersionString.Trim(); while (i < version.Length && (Char.IsDigit(version[i]) || version[i] == '.')) { ++i; } this._serverVersion = new Version(version.Substring(0, i)); } // Min supported version is 8.4. var serverVersion = this._serverVersion; if (serverVersion != null && (serverVersion.Major < 8 || (serverVersion.Major == 8 && serverVersion.Minor < 4))) { throw new PgSQLException("Unsupported server version: " + serverVersion + "."); } this.LastSeenTransactionStatus = status; this.BackendProcessID = backendPID; }
protected override async Task DoSendMessageAsync( BackendABIHelper args, Stream stream, Int32 size, CancellationToken token, ResizableArray <Byte> array ) { array.CurrentMaxCapacity = PREFIX_SIZE; var idx = 0; array.Array .WriteByteToBytes(ref idx, (Byte)this._code) .WritePgInt32(ref idx, size); await stream.WriteAsync(array.Array, 0, PREFIX_SIZE, token); await this.PerformSendAfterWriteAsync(args, stream, size, token, array); }
public async Task <Int32> ReadColumnByteCount( BackendABIHelper args, Stream stream, CancellationToken token, Int32 columnIndex, ResizableArray <Byte> array ) { var columnSizeHolder = this._columnSizes[columnIndex]; await columnSizeHolder.TryTransitionOrWaitAsync(async unused => { await stream.ReadSpecificAmountAsync(array.Array, 0, sizeof(Int32), token); var idx = 0; return(array.Array.ReadPgInt32(ref idx)); }); return(columnSizeHolder.Transformed); }
public override async ValueTask <Object> ReadBackendValue( DataFormat dataFormat, PgSQLTypeDatabaseData boundData, BackendABIHelper helper, StreamReaderWithResizableBufferAndLimitedSize stream ) { // No truly async support for deserializing JTokens in Newtonsoft, at least yet, so let's do it ourselves switch (dataFormat) { case DataFormat.Text: return(await stream.ReadJSONTTokenAsync(helper.CharacterReader)); case DataFormat.Binary: throw new InvalidOperationException("This data format is not supported"); default: throw new NotSupportedException($"Unrecognized data format: ${dataFormat}."); } }
private DataRowObject( BackendABIHelper args, Int32 columnCount, ResizableArray <ResettableTransformable <Int32?, Int32> > columnSizes ) : base(BackendMessageCode.DataRow) { this._columnCount = columnCount; columnSizes.CurrentMaxCapacity = columnCount; var array = columnSizes.Array; this._columnSizes = array; for (var i = 0; i < columnCount; ++i) { var cur = array[i]; if (cur == null) { cur = new ResettableTransformable <Int32?, Int32>(null); array[i] = cur; } cur.TryReset(); } }
protected abstract void WriteMessageToBuffer(BackendABIHelper args, ResizableArray <Byte> array);
protected override Int32 CalculateSize(BackendABIHelper args, ResizableArray <Byte> array) { return(this._count - this._offset); }
protected override Int32 CalculateBufferSize(BackendABIHelper args, ResizableArray <Byte> array) { return(this._pw.Length + 1); }
protected abstract Task DoSendMessageAsync(BackendABIHelper args, Stream stream, Int32 size, CancellationToken token, ResizableArray <Byte> array);
protected override Int32 CalculateSize(BackendABIHelper args, ResizableArray <Byte> array) { return(sizeof(Int32)); }
protected abstract Int32 CalculateSize(BackendABIHelper args, ResizableArray <Byte> array);
protected override Int32 CalculateSize(BackendABIHelper args, ResizableArray <Byte> array) { return(5 // int32 (protocol version) + end-byte (after message, zero) + this._parameters.Sum(kvp => args.GetStringSize(kvp.Key, array) + args.GetStringSize(kvp.Value, array))); }
protected override Int32 CalculateBufferSize(BackendABIHelper args, ResizableArray <Byte> array) { return(args.GetStringSize(this._portalName, array) + sizeof(Int32)); }
protected sealed override Int32 CalculateSize(BackendABIHelper args, ResizableArray <Byte> array) { return(this.CalculateBufferSize(args, array)); }
protected override Int32 CalculateBufferSize(BackendABIHelper args, ResizableArray <Byte> array) { return(args.GetStringSize(this._query, array)); }
protected override void WriteMessageToBuffer(BackendABIHelper args, ResizableArray <Byte> array) { var idx = 0; array.Array.WritePgString(ref idx, args.Encoding, this._query); }