Example #1
0
        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.");
            }
        }
Example #2
0
        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);
        }
Example #3
0
 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));
 }
Example #4
0
        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);
        }
Example #5
0
        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}.");
            }
        }
Example #6
0
        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);
        }
Example #7
0
        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);
        }
Example #8
0
        protected override void WriteMessageToBuffer(BackendABIHelper args, ResizableArray <Byte> array)
        {
            var idx = 0;

            array.Array
            .BlockCopyFrom(ref idx, this._pw)
            .WriteByteToBytes(ref idx, 0);
        }
Example #9
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);
        }
Example #10
0
 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);
 }
Example #11
0
        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);
        }
Example #12
0
 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);
 }
Example #13
0
        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);
        }
Example #14
0
        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);
        }
Example #15
0
        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;
        }
Example #16
0
        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);
        }
Example #17
0
        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);
        }
Example #18
0
        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}.");
            }
        }
Example #19
0
        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();
            }
        }
Example #20
0
 protected abstract void WriteMessageToBuffer(BackendABIHelper args, ResizableArray <Byte> array);
Example #21
0
 protected override Int32 CalculateSize(BackendABIHelper args, ResizableArray <Byte> array)
 {
     return(this._count - this._offset);
 }
Example #22
0
 protected override Int32 CalculateBufferSize(BackendABIHelper args, ResizableArray <Byte> array)
 {
     return(this._pw.Length + 1);
 }
Example #23
0
 protected abstract Task DoSendMessageAsync(BackendABIHelper args, Stream stream, Int32 size, CancellationToken token, ResizableArray <Byte> array);
Example #24
0
 protected override Int32 CalculateSize(BackendABIHelper args, ResizableArray <Byte> array)
 {
     return(sizeof(Int32));
 }
Example #25
0
 protected abstract Int32 CalculateSize(BackendABIHelper args, ResizableArray <Byte> array);
Example #26
0
 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)));
 }
Example #27
0
 protected override Int32 CalculateBufferSize(BackendABIHelper args, ResizableArray <Byte> array)
 {
     return(args.GetStringSize(this._portalName, array) + sizeof(Int32));
 }
Example #28
0
 protected sealed override Int32 CalculateSize(BackendABIHelper args, ResizableArray <Byte> array)
 {
     return(this.CalculateBufferSize(args, array));
 }
Example #29
0
 protected override Int32 CalculateBufferSize(BackendABIHelper args, ResizableArray <Byte> array)
 {
     return(args.GetStringSize(this._query, array));
 }
Example #30
0
        protected override void WriteMessageToBuffer(BackendABIHelper args, ResizableArray <Byte> array)
        {
            var idx = 0;

            array.Array.WritePgString(ref idx, args.Encoding, this._query);
        }