WriteByte() public method

public WriteByte ( byte b ) : void
b byte
return void
Beispiel #1
0
        internal Task WriteExecute(int maxRows, bool async)
        {
            // Note: non-empty portal currently not supported

            const int len = sizeof(byte) +       // Message code
                            sizeof(int) +        // Length
                            sizeof(byte) +       // Null-terminated portal name (always empty for now)
                            sizeof(int);         // Max number of rows

            if (WriteBuffer.WriteSpaceLeft < len)
            {
                return(FlushAndWrite(maxRows, async));
            }

            Write(maxRows);
            return(Task.CompletedTask);

            async Task FlushAndWrite(int maxRows, bool async)
            {
                await Flush(async);

                Debug.Assert(10 <= WriteBuffer.WriteSpaceLeft, $"Message of type {GetType().Name} has length 10 which is bigger than the buffer ({WriteBuffer.WriteSpaceLeft})");
                Write(maxRows);
            }

            void Write(int maxRows)
            {
                WriteBuffer.WriteByte(FrontendMessageCode.Execute);
                WriteBuffer.WriteInt32(len - 1);
                WriteBuffer.WriteByte(0);   // Portal is always empty for now
                WriteBuffer.WriteInt32(maxRows);
            }
        }
Beispiel #2
0
        internal Task WriteSync(bool async)
        {
            const int len = sizeof(byte) +  // Message code
                            sizeof(int);    // Length

            if (WriteBuffer.WriteSpaceLeft < len)
            {
                return(FlushAndWrite(async));
            }

            Write();
            return(Task.CompletedTask);

            async Task FlushAndWrite(bool async)
            {
                await Flush(async);

                Debug.Assert(len <= WriteBuffer.WriteSpaceLeft, $"Message of type {GetType().Name} has length {len} which is bigger than the buffer ({WriteBuffer.WriteSpaceLeft})");
                Write();
            }

            void Write()
            {
                WriteBuffer.WriteByte(FrontendMessageCode.Sync);
                WriteBuffer.WriteInt32(len - 1);
            }
        }
Beispiel #3
0
        internal async Task WriteSASLInitialResponse(string mechanism, byte[] initialResponse, bool async)
        {
            var len = sizeof(byte) +                                                // Message code
                      sizeof(int) +                                                 // Length
                      PGUtil.UTF8Encoding.GetByteCount(mechanism) + sizeof(byte) +  // Mechanism plus null terminator
                      sizeof(int) +                                                 // Initial response length
                      (initialResponse?.Length ?? 0);                               // Initial response payload

            if (WriteBuffer.WriteSpaceLeft < len)
            {
                await WriteBuffer.Flush(async);
            }

            WriteBuffer.WriteByte(FrontendMessageCode.Password);
            WriteBuffer.WriteInt32(len - 1);

            WriteBuffer.WriteString(mechanism);
            WriteBuffer.WriteByte(0);   // null terminator
            if (initialResponse == null)
            {
                WriteBuffer.WriteInt32(-1);
            }
            else
            {
                WriteBuffer.WriteInt32(initialResponse.Length);
                WriteBuffer.WriteBytes(initialResponse);
            }
        }
Beispiel #4
0
        internal void WriteStartup(Dictionary <string, string> parameters)
        {
            const int protocolVersion3 = 3 << 16; // 196608

            var len = sizeof(int) +               // Length
                      sizeof(int) +               // Protocol version
                      sizeof(byte);               // Trailing zero byte

            foreach (var kvp in parameters)
            {
                len += PGUtil.UTF8Encoding.GetByteCount(kvp.Key) + 1 +
                       PGUtil.UTF8Encoding.GetByteCount(kvp.Value) + 1;
            }

            // Should really never happen, just in case
            if (len > WriteBuffer.Size)
            {
                throw new Exception("Startup message bigger than buffer");
            }

            WriteBuffer.WriteInt32(len);
            WriteBuffer.WriteInt32(protocolVersion3);

            foreach (var kv in parameters)
            {
                WriteBuffer.WriteString(kv.Key);
                WriteBuffer.WriteByte(0);
                WriteBuffer.WriteString(kv.Value);
                WriteBuffer.WriteByte(0);
            }

            WriteBuffer.WriteByte(0);
        }
Beispiel #5
0
        internal Task WriteClose(StatementOrPortal type, string name, bool async)
        {
            var len = sizeof(byte) +               // Message code
                      sizeof(int) +                // Length
                      sizeof(byte) +               // Statement or portal
                      name.Length + sizeof(byte);  // Statement or portal name plus null terminator

            if (WriteBuffer.WriteSpaceLeft < 10)
            {
                return(FlushAndWrite(len, type, name, async));
            }

            Write(len, type, name);
            return(Task.CompletedTask);

            async Task FlushAndWrite(int len, StatementOrPortal type, string name, bool async)
            {
                await Flush(async);

                Debug.Assert(len <= WriteBuffer.WriteSpaceLeft, $"Message of type {GetType().Name} has length {len} which is bigger than the buffer ({WriteBuffer.WriteSpaceLeft})");
                Write(len, type, name);
            }

            void Write(int len, StatementOrPortal type, string name)
            {
                WriteBuffer.WriteByte(FrontendMessageCode.Close);
                WriteBuffer.WriteInt32(len - 1);
                WriteBuffer.WriteByte((byte)type);
                WriteBuffer.WriteNullTerminatedString(name);
            }
        }
Beispiel #6
0
        internal Task WriteDescribe(StatementOrPortal statementOrPortal, string name, bool async)
        {
            Debug.Assert(name.All(c => c < 128));

            var len = sizeof(byte) +       // Message code
                      sizeof(int) +        // Length
                      sizeof(byte) +       // Statement or portal
                      (name.Length + 1);   // Statement/portal name

            if (WriteBuffer.WriteSpaceLeft < len)
            {
                return(FlushAndWrite(len, statementOrPortal, name, async));
            }

            Write(len, statementOrPortal, name);
            return(Task.CompletedTask);

            async Task FlushAndWrite(int len, StatementOrPortal statementOrPortal, string name, bool async)
            {
                await Flush(async);

                Debug.Assert(len <= WriteBuffer.WriteSpaceLeft, $"Message of type {GetType().Name} has length {len} which is bigger than the buffer ({WriteBuffer.WriteSpaceLeft})");
                Write(len, statementOrPortal, name);
            }

            void Write(int len, StatementOrPortal statementOrPortal, string name)
            {
                WriteBuffer.WriteByte(FrontendMessageCode.Describe);
                WriteBuffer.WriteInt32(len - 1);
                WriteBuffer.WriteByte((byte)statementOrPortal);
                WriteBuffer.WriteNullTerminatedString(name);
            }
        }
Beispiel #7
0
        internal async Task WriteParse(string sql, string statementName, List <NpgsqlParameter> inputParameters, bool async)
        {
            Debug.Assert(statementName.All(c => c < 128));

            int queryByteLen;

            try
            {
                queryByteLen = TextEncoding.GetByteCount(sql);
            }
            catch (Exception e)
            {
                Break(e);
                throw;
            }

            if (WriteBuffer.WriteSpaceLeft < 1 + 4 + statementName.Length + 1)
            {
                await Flush(async);
            }

            var messageLength =
                sizeof(byte) +                        // Message code
                sizeof(int) +                         // Length
                statementName.Length +                // Statement name
                sizeof(byte) +                        // Null terminator for the statement name
                queryByteLen + sizeof(byte) +         // SQL query length plus null terminator
                sizeof(ushort) +                      // Number of parameters
                inputParameters.Count * sizeof(int);  // Parameter OIDs

            WriteBuffer.WriteByte(FrontendMessageCode.Parse);
            WriteBuffer.WriteInt32(messageLength - 1);
            WriteBuffer.WriteNullTerminatedString(statementName);

            await WriteBuffer.WriteString(sql, queryByteLen, async);

            if (WriteBuffer.WriteSpaceLeft < 1 + 2)
            {
                await Flush(async);
            }
            WriteBuffer.WriteByte(0); // Null terminator for the query
            WriteBuffer.WriteUInt16((ushort)inputParameters.Count);

            foreach (var p in inputParameters)
            {
                if (WriteBuffer.WriteSpaceLeft < 4)
                {
                    await Flush(async);
                }

                WriteBuffer.WriteInt32((int)p.Handler !.PostgresType.OID);
            }
        }
Beispiel #8
0
        void EnsureDataMessage()
        {
            if (_writingDataMsg)
            {
                return;
            }

            Contract.Assert(_buf.WritePosition == 0);
            _buf.WriteByte((byte)BackendMessageCode.CopyData);
            // Leave space for the message length
            _buf.WriteInt32(0);
            _writingDataMsg = true;
        }
Beispiel #9
0
        internal void WriteTerminate()
        {
            const int len = sizeof(byte) +  // Message code
                            sizeof(int);    // Length

            if (WriteBuffer.WriteSpaceLeft < len)
            {
                Flush(false).GetAwaiter().GetResult();
            }

            WriteBuffer.WriteByte(FrontendMessageCode.Terminate);
            WriteBuffer.WriteInt32(len - 1);
        }
Beispiel #10
0
        internal async Task WriteCopyDone(bool async)
        {
            const int len = sizeof(byte) +   // Message code
                            sizeof(int);     // Length

            if (WriteBuffer.WriteSpaceLeft < len)
            {
                await Flush(async);
            }

            WriteBuffer.WriteByte(FrontendMessageCode.CopyDone);
            WriteBuffer.WriteInt32(len - 1);
        }
Beispiel #11
0
        public override void Write(byte[] buffer, int offset, int count)
        {
            CheckDisposed();
            if (!CanWrite)
            {
                throw new InvalidOperationException("Stream not open for writing");
            }

            if (count == 0)
            {
                return;
            }

            EnsureDataMessage();

            if (count <= _writeBuf.WriteSpaceLeft)
            {
                _writeBuf.WriteBytes(buffer, offset, count);
                return;
            }

            try {
                // Value is too big. Flush whatever is in the buffer, then write a new CopyData
                // directly with the buffer.
                Flush();

                _writeBuf.WriteByte((byte)BackendMessageCode.CopyData);
                _writeBuf.WriteInt32(count + 4);
                _writeBuf.Flush();
                _writeBuf.DirectWrite(buffer, offset, count);
                EnsureDataMessage();
            } catch {
                _connector.Break();
                Cleanup();
                throw;
            }
        }
Beispiel #12
0
        internal async Task WriteCopyFail(bool async)
        {
            // Note: error message not supported for now

            const int len = sizeof(byte) +  // Message code
                            sizeof(int) +   // Length
                            sizeof(byte);   // Error message is always empty (only a null terminator)

            if (WriteBuffer.WriteSpaceLeft < len)
            {
                await Flush(async);
            }

            WriteBuffer.WriteByte(FrontendMessageCode.CopyFail);
            WriteBuffer.WriteInt32(len - 1);
            WriteBuffer.WriteByte(0);   // Error message is always empty (only a null terminator)
        }
Beispiel #13
0
        internal async Task WritePassword(byte[] payload, int offset, int count, bool async)
        {
            if (WriteBuffer.WriteSpaceLeft < sizeof(byte) + sizeof(int))
            {
                await WriteBuffer.Flush(async);
            }
            WriteBuffer.WriteByte(FrontendMessageCode.Password);
            WriteBuffer.WriteInt32(sizeof(int) + count);

            if (count <= WriteBuffer.WriteSpaceLeft)
            {
                // The entire array fits in our WriteBuffer, copy it into the WriteBuffer as usual.
                WriteBuffer.WriteBytes(payload, offset, count);
                return;
            }

            await WriteBuffer.Flush(async);

            await WriteBuffer.DirectWrite(payload, offset, count, async);
        }
Beispiel #14
0
        internal async Task WritePassword(byte[] payload, int offset, int count, bool async, CancellationToken cancellationToken = default)
        {
            if (WriteBuffer.WriteSpaceLeft < sizeof(byte) + sizeof(int))
            {
                await WriteBuffer.Flush(async, cancellationToken);
            }
            WriteBuffer.WriteByte(FrontendMessageCode.Password);
            WriteBuffer.WriteInt32(sizeof(int) + count);

            if (count <= WriteBuffer.WriteSpaceLeft)
            {
                // The entire array fits in our WriteBuffer, copy it into the WriteBuffer as usual.
                WriteBuffer.WriteBytes(payload, offset, count);
                return;
            }

            await WriteBuffer.Flush(async, cancellationToken);

            await WriteBuffer.DirectWrite(new ReadOnlyMemory <byte>(payload, offset, count), async, cancellationToken);
        }
Beispiel #15
0
        internal async Task WriteQuery(string sql, bool async)
        {
            var queryByteLen = TextEncoding.GetByteCount(sql);

            if (WriteBuffer.WriteSpaceLeft < 1 + 4)
            {
                await Flush(async);
            }

            WriteBuffer.WriteByte(FrontendMessageCode.Query);
            WriteBuffer.WriteInt32(
                sizeof(int) +         // Message length (including self excluding code)
                queryByteLen +        // Query byte length
                sizeof(byte));        // Null terminator

            await WriteBuffer.WriteString(sql, queryByteLen, async);

            if (WriteBuffer.WriteSpaceLeft < 1)
            {
                await Flush(async);
            }
            WriteBuffer.WriteByte(0);  // Null terminator
        }
Beispiel #16
0
        internal async Task WriteBind(
            List <NpgsqlParameter> inputParameters,
            string portal,
            string statement,
            bool allResultTypesAreUnknown,
            bool[]?unknownResultTypeList,
            bool async)
        {
            Debug.Assert(statement.All(c => c < 128));
            Debug.Assert(portal.All(c => c < 128));

            var headerLength =
                sizeof(byte) +                        // Message code
                sizeof(int) +                         // Message length
                sizeof(byte) +                        // Portal is always empty (only a null terminator)
                statement.Length + sizeof(byte) +     // Statement name plus null terminator
                sizeof(short);                        // Number of parameter format codes that follow

            if (WriteBuffer.WriteSpaceLeft < headerLength)
            {
                Debug.Assert(WriteBuffer.Size >= headerLength, "Write buffer too small for Bind header");
                await Flush(async);
            }

            var formatCodesSum = 0;
            var paramsLength   = 0;

            foreach (var p in inputParameters)
            {
                formatCodesSum += (int)p.FormatCode;
                p.LengthCache?.Rewind();
                paramsLength += p.ValidateAndGetLength();
            }

            var formatCodeListLength = formatCodesSum == 0 ? 0 : formatCodesSum == inputParameters.Count ? 1 : inputParameters.Count;

            var messageLength = headerLength +
                                sizeof(short) * formatCodeListLength +                // List of format codes
                                sizeof(short) +                                       // Number of parameters
                                sizeof(int) * inputParameters.Count +                 // Parameter lengths
                                paramsLength +                                        // Parameter values
                                sizeof(short) +                                       // Number of result format codes
                                sizeof(short) * (unknownResultTypeList?.Length ?? 1); // Result format codes

            WriteBuffer.WriteByte(FrontendMessageCode.Bind);
            WriteBuffer.WriteInt32(messageLength - 1);
            Debug.Assert(portal == string.Empty);
            WriteBuffer.WriteByte(0);  // Portal is always empty

            WriteBuffer.WriteNullTerminatedString(statement);
            WriteBuffer.WriteInt16(formatCodeListLength);

            // 0 length implicitly means all-text, 1 means all-binary, >1 means mix-and-match
            if (formatCodeListLength == 1)
            {
                if (WriteBuffer.WriteSpaceLeft < 2)
                {
                    await Flush(async);
                }
                WriteBuffer.WriteInt16((short)FormatCode.Binary);
            }
            else if (formatCodeListLength > 1)
            {
                foreach (var p in inputParameters)
                {
                    if (WriteBuffer.WriteSpaceLeft < 2)
                    {
                        await Flush(async);
                    }
                    WriteBuffer.WriteInt16((short)p.FormatCode);
                }
            }

            if (WriteBuffer.WriteSpaceLeft < 2)
            {
                await Flush(async);
            }

            WriteBuffer.WriteInt16(inputParameters.Count);

            foreach (var param in inputParameters)
            {
                param.LengthCache?.Rewind();
                await param.WriteWithLength(WriteBuffer, async);
            }

            if (unknownResultTypeList != null)
            {
                if (WriteBuffer.WriteSpaceLeft < 2 + unknownResultTypeList.Length * 2)
                {
                    await Flush(async);
                }
                WriteBuffer.WriteInt16(unknownResultTypeList.Length);
                foreach (var t in unknownResultTypeList)
                {
                    WriteBuffer.WriteInt16(t ? 0 : 1);
                }
            }
            else
            {
                if (WriteBuffer.WriteSpaceLeft < 4)
                {
                    await Flush(async);
                }
                WriteBuffer.WriteInt16(1);
                WriteBuffer.WriteInt16(allResultTypesAreUnknown ? 0 : 1);
            }
        }