示例#1
0
        private static ByteBufferWriter CreateCapabilitiesPayload(ProtocolCapabilities serverCapabilities, ConnectionSettings cs, bool useCompression, CharacterSet characterSet, ProtocolCapabilities additionalCapabilities = 0)
        {
            var writer = new ByteBufferWriter();

            writer.Write((int)(
                             ProtocolCapabilities.Protocol41 |
                             (cs.InteractiveSession ? (serverCapabilities & ProtocolCapabilities.Interactive) : 0) |
                             ProtocolCapabilities.LongPassword |
                             (serverCapabilities & ProtocolCapabilities.Transactions) |
                             ProtocolCapabilities.SecureConnection |
                             (serverCapabilities & ProtocolCapabilities.PluginAuth) |
                             (serverCapabilities & ProtocolCapabilities.PluginAuthLengthEncodedClientData) |
                             ProtocolCapabilities.MultiStatements |
                             ProtocolCapabilities.MultiResults |
                             ProtocolCapabilities.LocalFiles |
                             (string.IsNullOrWhiteSpace(cs.Database) ? 0 : ProtocolCapabilities.ConnectWithDatabase) |
                             (cs.UseAffectedRows ? 0 : ProtocolCapabilities.FoundRows) |
                             (useCompression ? ProtocolCapabilities.Compress : ProtocolCapabilities.None) |
                             (serverCapabilities & ProtocolCapabilities.ConnectionAttributes) |
                             (serverCapabilities & ProtocolCapabilities.SessionTrack) |
                             (serverCapabilities & ProtocolCapabilities.DeprecateEof) |
                             additionalCapabilities));
            writer.Write(0x4000_0000);
            writer.Write((byte)characterSet);
            writer.Write(s_padding);

            return(writer);
        }
示例#2
0
        public bool WriteQueryCommand(ref CommandListPosition commandListPosition, IDictionary <string, CachedProcedure?> cachedProcedures, ByteBufferWriter writer)
        {
            writer.Write((byte)CommandKind.Multi);
            bool?firstResult = default;
            bool wroteCommand;

            do
            {
                // save room for command length
                var position = writer.Position;
                writer.Write(Padding);

                wroteCommand = SingleCommandPayloadCreator.Instance.WriteQueryCommand(ref commandListPosition, cachedProcedures, writer);
                if (firstResult is null)
                {
                    firstResult = wroteCommand;
                }

                // write command length
                var commandLength = writer.Position - position - Padding.Length;
                var span          = writer.ArraySegment.AsSpan().Slice(position);
                span[0] = 0xFE;
                BinaryPrimitives.WriteUInt64LittleEndian(span.Slice(1), (ulong)commandLength);
            } while (wroteCommand);

            // remove the padding that was saved for the final command (which wasn't written)
            writer.TrimEnd(Padding.Length);
            return(firstResult.Value);
        }
示例#3
0
        private static void WritePreparedStatement(IMySqlCommand command, PreparedStatement preparedStatement, ByteBufferWriter writer)
        {
            var parameterCollection = command.RawParameters;

            if (Log.IsDebugEnabled())
            {
                Log.Debug("Session{0} Preparing command payload; CommandId: {1}; CommandText: {2}", command.Connection !.Session.Id, preparedStatement.StatementId, command.CommandText);
            }

            writer.Write(preparedStatement.StatementId);
            writer.Write((byte)0);
            writer.Write(1);
            if (preparedStatement.Parameters?.Length > 0)
            {
                // TODO: How to handle incorrect number of parameters?

                // build subset of parameters for this statement
                var parameters = new MySqlParameter[preparedStatement.Statement.ParameterNames.Count];
                for (var i = 0; i < preparedStatement.Statement.ParameterNames.Count; i++)
                {
                    var parameterName  = preparedStatement.Statement.ParameterNames[i];
                    var parameterIndex = parameterName is object?(parameterCollection?.NormalizedIndexOf(parameterName) ?? -1) : preparedStatement.Statement.ParameterIndexes[i];
                    if (parameterIndex == -1 && parameterName is object)
                    {
                        throw new MySqlException("Parameter '{0}' must be defined.".FormatInvariant(parameterName));
                    }
                    else if (parameterIndex < 0 || parameterIndex >= (parameterCollection?.Count ?? 0))
                    {
                        throw new MySqlException("Parameter index {0} is invalid when only {1} parameter{2} defined.".FormatInvariant(parameterIndex, parameterCollection?.Count ?? 0, parameterCollection?.Count == 1 ? " is" : "s are"));
                    }
                    parameters[i] = parameterCollection ![parameterIndex];
        public static PayloadData Create(string databaseName)
        {
            var writer = new ByteBufferWriter();

            writer.Write((byte)CommandKind.InitDatabase);
            writer.Write(databaseName);

            return(writer.ToPayloadData());
        }
示例#5
0
        public static PayloadData Create(string filename)
        {
            var writer   = new ByteBufferWriter();
            var position = 4;
            var flags    = (ushort)BinlogFlags.NonBlock;
            var serverId = 10;

            writer.Write((byte)CommandKind.BinlogDump);
            writer.Write(position);
            writer.Write(flags);
            writer.Write(serverId);
            writer.Write(filename);

            return(writer.ToPayloadData());
        }
        private PayloadData CreateQueryPayload(PreparedStatement preparedStatement, MySqlParameterCollection parameterCollection, MySqlGuidFormat guidFormat)
        {
            var writer = new ByteBufferWriter();

            writer.Write((byte)CommandKind.StatementExecute);
            writer.Write(preparedStatement.StatementId);
            writer.Write((byte)0);
            writer.Write(1);
            if (preparedStatement.Parameters?.Length > 0)
            {
                // TODO: How to handle incorrect number of parameters?

                // build subset of parameters for this statement
                var parameters = new MySqlParameter[preparedStatement.Statement.ParameterNames.Count];
                for (var i = 0; i < preparedStatement.Statement.ParameterNames.Count; i++)
                {
                    var parameterName  = preparedStatement.Statement.ParameterNames[i];
                    var parameterIndex = parameterName != null?parameterCollection.NormalizedIndexOf(parameterName) : preparedStatement.Statement.ParameterIndexes[i];

                    parameters[i] = parameterCollection[parameterIndex];
                }

                // write null bitmap
                byte nullBitmap = 0;
                for (var i = 0; i < parameters.Length; i++)
                {
                    var parameter = parameters[i];
                    if (parameter.Value == null || parameter.Value == DBNull.Value)
                    {
                        if (i > 0 && i % 8 == 0)
                        {
                            writer.Write(nullBitmap);
                            nullBitmap = 0;
                        }

                        nullBitmap |= (byte)(1 << (i % 8));
                    }
                }
                writer.Write(nullBitmap);

                // write "new parameters bound" flag
                writer.Write((byte)1);

                foreach (var parameter in parameters)
                {
                    writer.Write(TypeMapper.ConvertToColumnTypeAndFlags(parameter.MySqlDbType, guidFormat));
                }

                var options = m_command.CreateStatementPreparerOptions();
                foreach (var parameter in parameters)
                {
                    parameter.AppendBinary(writer, options);
                }
            }

            return(writer.ToPayloadData());
        }
        public void can_continue_on_a_partial_write()
        {
            var buffer = new byte[] { 1, 2, 3, 4, 5, 6, 7 };
            var mgr = new BufferManager(100, 10);
            var context = new WriterContext(mgr);
            context.BytesLeftToEnqueue = 4;

            var sut = new ByteBufferWriter(buffer, 0, buffer.Length);
            context.BytesLeftToEnqueue = 4;
            sut.Write(context);
            context.BytesLeftToEnqueue = 10;
            var actual = sut.Write(context);

            actual.Should().BeTrue();
            var packet = context.GetPackets()[1];
            packet.Buffer[packet.Offset + 2].Should().Be(7);
        }
示例#8
0
 public void ParseAndBindParameters(ByteBufferWriter writer)
 {
     if (!string.IsNullOrWhiteSpace(m_commandText))
     {
         writer.Write((byte)CommandKind.Query);
         var parser = new ParameterSqlParser(this, writer);
         parser.Parse(m_commandText);
     }
 }
        private static ByteBufferWriter CreateCapabilitiesPayload(ProtocolCapabilities serverCapabilities, ConnectionSettings cs, bool useCompression, CharacterSet characterSet, ProtocolCapabilities additionalCapabilities = 0)
        {
            var writer = new ByteBufferWriter();

            writer.Write((int)(
                             ProtocolCapabilities.Protocol41 |
                             (cs.InteractiveSession ? (serverCapabilities & ProtocolCapabilities.Interactive) : 0) |
                             (serverCapabilities & ProtocolCapabilities.LongPassword) |
                             (serverCapabilities & ProtocolCapabilities.Transactions) |
                             ProtocolCapabilities.SecureConnection |
                             (serverCapabilities & ProtocolCapabilities.PluginAuth) |
                             (serverCapabilities & ProtocolCapabilities.PluginAuthLengthEncodedClientData) |
                             ProtocolCapabilities.MultiStatements |
                             ProtocolCapabilities.MultiResults |
                             (cs.AllowLoadLocalInfile ? ProtocolCapabilities.LocalFiles : 0) |
                             (string.IsNullOrWhiteSpace(cs.Database) ? 0 : ProtocolCapabilities.ConnectWithDatabase) |
                             (cs.UseAffectedRows ? 0 : ProtocolCapabilities.FoundRows) |
                             (useCompression ? ProtocolCapabilities.Compress : ProtocolCapabilities.None) |
                             (serverCapabilities & ProtocolCapabilities.ConnectionAttributes) |
                             (serverCapabilities & ProtocolCapabilities.SessionTrack) |
                             (serverCapabilities & ProtocolCapabilities.DeprecateEof) |
                             additionalCapabilities));
            writer.Write(0x4000_0000);
            writer.Write((byte)characterSet);

            // NOTE: not new byte[19]; see https://github.com/dotnet/roslyn/issues/33088
            ReadOnlySpan <byte> padding = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

            writer.Write(padding);

            if ((serverCapabilities & ProtocolCapabilities.LongPassword) == 0)
            {
                // MariaDB writes extended capabilities at the end of the padding
                writer.Write((int)(((long)(serverCapabilities & ProtocolCapabilities.MariaDbComMulti)) >> 32));
            }
            else
            {
                writer.Write(0u);
            }

            return(writer);
        }
        public void can_write_to_our_context()
        {
            var buffer = new byte[] {1, 2, 3, 4, 5, 6, 7};
            var mgr = new BufferManager(100, 10);
            var context = new WriterContext(mgr);

            var sut = new ByteBufferWriter(buffer, 0, buffer.Length);
            sut.Write(context);

            context.GetPackets()[0].Buffer.Should().BeSubsetOf(buffer);
        }
        public void can_continue_on_a_partial_write()
        {
            var buffer  = new byte[] { 1, 2, 3, 4, 5, 6, 7 };
            var mgr     = new BufferManager(100, 10);
            var context = new WriterContext(mgr);

            context.BytesLeftToEnqueue = 4;

            var sut = new ByteBufferWriter(buffer, 0, buffer.Length);

            context.BytesLeftToEnqueue = 4;
            sut.Write(context);
            context.BytesLeftToEnqueue = 10;
            var actual = sut.Write(context);

            actual.Should().BeTrue();
            var packet = context.GetPackets()[1];

            packet.Buffer[packet.Offset + 2].Should().Be(7);
        }
        public void can_do_partial_write()
        {
            var buffer = new byte[] { 1, 2, 3, 4, 5, 6, 7 };
            var mgr = new BufferManager(100, 10);
            var context = new WriterContext(mgr);
            context.BytesLeftToEnqueue = 4;

            var sut = new ByteBufferWriter(buffer, 0, buffer.Length);
            var actual = sut.Write(context);

            actual.Should().BeFalse();
        }
        public void can_write_to_our_context()
        {
            var buffer  = new byte[] { 1, 2, 3, 4, 5, 6, 7 };
            var mgr     = new BufferManager(100, 10);
            var context = new WriterContext(mgr);

            var sut = new ByteBufferWriter(buffer, 0, buffer.Length);

            sut.Write(context);

            context.GetPackets()[0].Buffer.Should().BeSubsetOf(buffer);
        }
        public void partial_bytes_are_copied()
        {
            var buffer = new byte[] { 1, 2, 3, 4, 5, 6, 7 };
            var mgr = new BufferManager(100, 10);
            var context = new WriterContext(mgr);
            context.BytesLeftToEnqueue = 4;

            var sut = new ByteBufferWriter(buffer, 0, buffer.Length);
            sut.Write(context);

            context.GetPackets()[0].Buffer[3].Should().Be(4);
        }
        public void can_do_partial_write()
        {
            var buffer  = new byte[] { 1, 2, 3, 4, 5, 6, 7 };
            var mgr     = new BufferManager(100, 10);
            var context = new WriterContext(mgr);

            context.BytesLeftToEnqueue = 4;

            var sut    = new ByteBufferWriter(buffer, 0, buffer.Length);
            var actual = sut.Write(context);

            actual.Should().BeFalse();
        }
        public void partial_bytes_are_copied()
        {
            var buffer  = new byte[] { 1, 2, 3, 4, 5, 6, 7 };
            var mgr     = new BufferManager(100, 10);
            var context = new WriterContext(mgr);

            context.BytesLeftToEnqueue = 4;

            var sut = new ByteBufferWriter(buffer, 0, buffer.Length);

            sut.Write(context);

            context.GetPackets()[0].Buffer[3].Should().Be(4);
        }
示例#17
0
        public ArraySegment <byte> ParseAndBindParameters()
        {
            var writer = new ByteBufferWriter(m_commandText.Length + 1);

            writer.Write((byte)CommandKind.Query);

            if (!string.IsNullOrWhiteSpace(m_commandText))
            {
                var parser = new ParameterSqlParser(this, writer);
                parser.Parse(m_commandText);
            }

            return(writer.ArraySegment);
        }
示例#18
0
        public bool WriteQueryCommand(ref CommandListPosition commandListPosition, IDictionary <string, CachedProcedure?> cachedProcedures, ByteBufferWriter writer)
        {
            if (commandListPosition.CommandIndex == commandListPosition.Commands.Count)
            {
                return(false);
            }

            var command            = commandListPosition.Commands[commandListPosition.CommandIndex];
            var preparedStatements = command.TryGetPreparedStatements();

            if (preparedStatements is null)
            {
                if (Log.IsDebugEnabled())
                {
                    Log.Debug("Session{0} Preparing command payload; CommandText: {1}", command.Connection !.Session.Id, command.CommandText);
                }

                writer.Write((byte)CommandKind.Query);
                WriteQueryPayload(command, cachedProcedures, writer);

                commandListPosition.CommandIndex++;
            }
            else
            {
                writer.Write((byte)CommandKind.StatementExecute);
                WritePreparedStatement(command, preparedStatements.Statements[commandListPosition.PreparedStatementIndex], writer);

                // advance to next prepared statement or next command
                if (++commandListPosition.PreparedStatementIndex == preparedStatements.Statements.Count)
                {
                    commandListPosition.CommandIndex++;
                    commandListPosition.PreparedStatementIndex = 0;
                }
            }
            return(true);
        }
        public void WriteString(int length)
        {
            var expected = new byte[length * 3];

            for (var i = 0; i < length; i++)
            {
                expected[i * 3]     = 0xEE;
                expected[i * 3 + 1] = 0x80;
                expected[i * 3 + 2] = 0x81;
            }

            var writer = new ByteBufferWriter();
            var input  = char.ConvertFromUtf32(0xE001);

            for (var i = 0; i < length; i++)
            {
                writer.Write(input);
            }
            Assert.Equal(expected, writer.ArraySegment);
        }
        public bool WriteQueryCommand(ref CommandListPosition commandListPosition, IDictionary <string, CachedProcedure?> cachedProcedures, ByteBufferWriter writer)
        {
            if (commandListPosition.CommandIndex == commandListPosition.Commands.Count)
            {
                return(false);
            }

            writer.Write((byte)CommandKind.Query);
            bool isComplete;

            do
            {
                var command = commandListPosition.Commands[commandListPosition.CommandIndex];
                if (Log.IsTraceEnabled())
                {
                    Log.Trace("Session{0} Preparing command payload; CommandText: {1}", command.Connection !.Session.Id, command.CommandText);
                }

                isComplete = SingleCommandPayloadCreator.WriteQueryPayload(command, cachedProcedures, writer);
                commandListPosition.CommandIndex++;
            }while (commandListPosition.CommandIndex < commandListPosition.Commands.Count && isComplete);

            return(true);
        }
示例#21
0
        public static PayloadData Create(string user, ReadOnlySpan <byte> authResponse, string?schemaName, CharacterSet characterSet, byte[]?connectionAttributes)
        {
            var writer = new ByteBufferWriter();

            writer.Write((byte)CommandKind.ChangeUser);
            writer.WriteNullTerminatedString(user);
            writer.Write(checked ((byte)authResponse.Length));
            writer.Write(authResponse);
            writer.WriteNullTerminatedString(schemaName ?? "");
            writer.Write((byte)characterSet);
            writer.Write((byte)0);
            writer.WriteNullTerminatedString("mysql_native_password");
            if (connectionAttributes is not null)
            {
                writer.Write(connectionAttributes);
            }

            return(writer.ToPayloadData());
        }
示例#22
0
        public static PayloadData Create(string user, byte[] authResponse, string schemaName, byte[] connectionAttributes)
        {
            var writer = new ByteBufferWriter();

            writer.Write((byte)CommandKind.ChangeUser);
            writer.WriteNullTerminatedString(user);
            writer.Write(checked ((byte)authResponse.Length));
            writer.Write(authResponse);
            writer.WriteNullTerminatedString(schemaName ?? "");
            writer.Write((byte)CharacterSet.Utf8Mb4Binary);
            writer.Write((byte)0);
            writer.WriteNullTerminatedString("mysql_native_password");
            if (connectionAttributes != null)
            {
                writer.Write(connectionAttributes);
            }

            return(writer.ToPayloadData());
        }
示例#23
0
        private void WritePreparedStatement(IMySqlCommand command, PreparedStatement preparedStatement, ByteBufferWriter writer)
        {
            var parameterCollection = command.Parameters;

            if (Log.IsDebugEnabled())
            {
                Log.Debug("Session{0} Preparing command payload; CommandId: {1}; CommandText: {2}", command.Connection.Session.Id, preparedStatement.StatementId, command.CommandText);
            }

            writer.Write((byte)CommandKind.StatementExecute);
            writer.Write(preparedStatement.StatementId);
            writer.Write((byte)0);
            writer.Write(1);
            if (preparedStatement.Parameters?.Length > 0)
            {
                // TODO: How to handle incorrect number of parameters?

                // build subset of parameters for this statement
                var parameters = new MySqlParameter[preparedStatement.Statement.ParameterNames.Count];
                for (var i = 0; i < preparedStatement.Statement.ParameterNames.Count; i++)
                {
                    var parameterName  = preparedStatement.Statement.ParameterNames[i];
                    var parameterIndex = parameterName != null ? (parameterCollection?.NormalizedIndexOf(parameterName) ?? -1) : preparedStatement.Statement.ParameterIndexes[i];
                    if (parameterIndex == -1 && parameterName != null)
                    {
                        throw new MySqlException("Parameter '{0}' must be defined.".FormatInvariant(parameterName));
                    }
                    else if (parameterIndex < 0 || parameterIndex >= (parameterCollection?.Count ?? 0))
                    {
                        throw new MySqlException("Parameter index {0} is invalid when only {1} parameter{2} defined.".FormatInvariant(parameterIndex, parameterCollection?.Count ?? 0, parameterCollection?.Count == 1 ? " is" : "s are"));
                    }
                    parameters[i] = parameterCollection[parameterIndex];
                }

                // write null bitmap
                byte nullBitmap = 0;
                for (var i = 0; i < parameters.Length; i++)
                {
                    var parameter = parameters[i];
                    if (parameter.Value is null || parameter.Value == DBNull.Value)
                    {
                        nullBitmap |= (byte)(1 << (i % 8));
                    }

                    if (i % 8 == 7)
                    {
                        writer.Write(nullBitmap);
                        nullBitmap = 0;
                    }
                }
                if (parameters.Length % 8 != 0)
                {
                    writer.Write(nullBitmap);
                }

                // write "new parameters bound" flag
                writer.Write((byte)1);

                foreach (var parameter in parameters)
                {
                    writer.Write(TypeMapper.ConvertToColumnTypeAndFlags(parameter.MySqlDbType, command.Connection.GuidFormat));
                }

                var options = command.CreateStatementPreparerOptions();
                foreach (var parameter in parameters)
                {
                    parameter.AppendBinary(writer, options);
                }
            }
        }
示例#24
0
        private PayloadData CreateQueryPayload(PreparedStatement preparedStatement, MySqlParameterCollection parameterCollection, MySqlGuidFormat guidFormat)
        {
            var writer = new ByteBufferWriter();

            writer.Write((byte)CommandKind.StatementExecute);
            writer.Write(preparedStatement.StatementId);
            writer.Write((byte)0);
            writer.Write(1);
            if (preparedStatement.Parameters?.Length > 0)
            {
                // TODO: How to handle incorrect number of parameters?

                // build subset of parameters for this statement
                var parameters = new MySqlParameter[preparedStatement.Statement.ParameterNames.Count];
                for (var i = 0; i < preparedStatement.Statement.ParameterNames.Count; i++)
                {
                    var parameterName  = preparedStatement.Statement.ParameterNames[i];
                    var parameterIndex = parameterName != null ? (parameterCollection?.NormalizedIndexOf(parameterName) ?? -1) : preparedStatement.Statement.ParameterIndexes[i];
                    if (parameterIndex == -1 && parameterName != null)
                    {
                        throw new MySqlException("Parameter '{0}' must be defined.".FormatInvariant(parameterName));
                    }
                    else if (parameterIndex < 0 || parameterIndex >= (parameterCollection?.Count ?? 0))
                    {
                        throw new MySqlException("Parameter index {0} is invalid when only {1} parameter{2} defined.".FormatInvariant(parameterIndex, parameterCollection?.Count ?? 0, parameterCollection?.Count == 1 ? " is" : "s are"));
                    }
                    parameters[i] = parameterCollection[parameterIndex];
                }

                // write null bitmap
                byte nullBitmap = 0;
                for (var i = 0; i < parameters.Length; i++)
                {
                    var parameter = parameters[i];
                    if (parameter.Value == null || parameter.Value == DBNull.Value)
                    {
                        if (i > 0 && i % 8 == 0)
                        {
                            writer.Write(nullBitmap);
                            nullBitmap = 0;
                        }

                        nullBitmap |= (byte)(1 << (i % 8));
                    }
                }
                writer.Write(nullBitmap);

                // write "new parameters bound" flag
                writer.Write((byte)1);

                foreach (var parameter in parameters)
                {
                    writer.Write(TypeMapper.ConvertToColumnTypeAndFlags(parameter.MySqlDbType, guidFormat));
                }

                var options = m_command.CreateStatementPreparerOptions();
                foreach (var parameter in parameters)
                {
                    parameter.AppendBinary(writer, options);
                }
            }

            return(writer.ToPayloadData());
        }