MySQL 9.3.0
Source Code Documentation
classic_protocol_codec_message.h
Go to the documentation of this file.
1/*
2 Copyright (c) 2019, 2025, Oracle and/or its affiliates.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is designed to work with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have either included with
14 the program or referenced in the documentation.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24*/
25
26#ifndef MYSQL_ROUTER_CLASSIC_PROTOCOL_CODEC_MESSAGE_H_
27#define MYSQL_ROUTER_CLASSIC_PROTOCOL_CODEC_MESSAGE_H_
28
29#include <cassert>
30#include <cstddef> // size_t
31#include <cstdint> // uint8_t
32#include <system_error> // error_code
33#include <utility> // move
34
44
45namespace classic_protocol {
46
47/**
48 * codec for server Greeting message.
49 *
50 * 3.21 (protocol_version 9)
51 *
52 * FixedInt<1> protocol_version [0x09]
53 * NulTermString server_version
54 * FixedInt<4> connection_id
55 * NulTermString auth-method-data
56 *
57 * 3.21 and later (protocol_version 10)
58 *
59 * FixedInt<1> protocol_version [0x0a]
60 * NulTermString server_version
61 * FixedInt<4> connection_id
62 * NulTermString auth-method-data
63 * FixedInt<2> capabilities (lower 16bit)
64 *
65 * 3.23 and later add:
66 *
67 * FixedInt<1> collation
68 * FixedInt<2> status flags
69 * FixedInt<2> capabilities (upper 16bit)
70 * FixedInt<1> length of auth-method-data or 0x00
71 * String<10> reserved
72 *
73 * if capabilities.secure_connection is set, adds
74 *
75 * String<len> auth-method-data-2
76 *
77 * if capabilities.plugin_auth is set, adds
78 *
79 * NulTermString auth-method
80 */
81template <bool Borrowed>
82class Codec<borrowable::message::server::Greeting<Borrowed>>
83 : public impl::EncodeBase<
84 Codec<borrowable::message::server::Greeting<Borrowed>>> {
85 template <class Accumulator>
86 constexpr auto accumulate_fields(Accumulator &&accu) const {
87 namespace bw = borrowable::wire;
88
89 if (v_.protocol_version() == 0x09) {
90 return accu.step(bw::FixedInt<1>(v_.protocol_version()))
91 .step(bw::NulTermString<Borrowed>(v_.version()))
92 .step(bw::FixedInt<4>(v_.connection_id()))
93 .step(bw::NulTermString<Borrowed>(v_.auth_method_data().substr(0, 8)))
94 .result();
95 } else {
96 uint8_t auth_method_data_size{0};
98 auth_method_data_size = v_.auth_method_data().size();
99 }
100
101 accu.step(bw::FixedInt<1>(v_.protocol_version()))
102 .step(bw::NulTermString<Borrowed>(v_.version()))
103 .step(bw::FixedInt<4>(v_.connection_id()))
104 .step(bw::NulTermString<Borrowed>(v_.auth_method_data().substr(0, 8)))
105 .step(bw::FixedInt<2>(v_.capabilities().to_ulong() & 0xffff));
106
107 if ((v_.capabilities().to_ullong() >= (1 << 16)) ||
108 v_.status_flags().any() || (v_.collation() != 0)) {
109 accu.step(bw::FixedInt<1>(v_.collation()))
110 .step(bw::FixedInt<2>(v_.status_flags().to_ulong()))
111 .step(
112 bw::FixedInt<2>((v_.capabilities().to_ulong() >> 16) & 0xffff))
113 .step(bw::FixedInt<1>(auth_method_data_size))
114 .step(bw::String<Borrowed>(std::string(10, '\0')));
115 if (v_.capabilities()
117 accu.step(bw::String<Borrowed>(v_.auth_method_data().substr(8)));
118 if (v_.capabilities()
120 accu.step(bw::NulTermString<Borrowed>(v_.auth_method_name()));
121 }
122 }
123 }
124 return accu.result();
125 }
126 }
127
128 public:
129 using value_type = borrowable::message::server::Greeting<Borrowed>;
131
132 friend __base;
133
135 : __base(caps), v_{std::move(v)} {}
136
140
141 namespace bw = borrowable::wire;
142
143 // proto-version
144 auto protocol_version_res = accu.template step<bw::FixedInt<1>>();
145 if (!accu.result()) return stdx::unexpected(accu.result().error());
146
147 if (protocol_version_res->value() != 0x09 &&
148 protocol_version_res->value() != 0x0a) {
150 }
151
152 auto version_res = accu.template step<bw::NulTermString<Borrowed>>();
153 auto connection_id_res = accu.template step<bw::FixedInt<4>>();
154 auto auth_method_data_res =
155 accu.template step<bw::NulTermString<Borrowed>>();
156
157 if (protocol_version_res->value() == 0x09) {
158 return std::make_pair(
159 accu.result().value(),
160 value_type(protocol_version_res->value(), version_res->value(),
161 connection_id_res->value(), auth_method_data_res->value(),
162 0, 0, 0, {}));
163 } else {
164 // capabilities are split into two a lower-2-byte part and a
165 // higher-2-byte
166 auto cap_lower_res = accu.template step<bw::FixedInt<2>>();
167 if (!accu.result()) return stdx::unexpected(accu.result().error());
168
169 // 3.21.x doesn't send more.
170 if (buffer_size(buffer) <= accu.result().value()) {
171 return std::make_pair(
172 accu.result().value(),
173 value_type(protocol_version_res->value(), version_res->value(),
174 connection_id_res->value(),
175 auth_method_data_res->value(), cap_lower_res->value(),
176 0x0, 0x0, {}));
177 }
178
179 // if there's more data
180 auto collation_res = accu.template step<bw::FixedInt<1>>();
181 auto status_flags_res = accu.template step<bw::FixedInt<2>>();
182 auto cap_hi_res = accu.template step<bw::FixedInt<2>>();
183
184 // before we use cap_hi|cap_low check they don't have an error
185 if (!accu.result()) return stdx::unexpected(accu.result().error());
186
188 cap_lower_res->value() | (cap_hi_res->value() << 16));
189
190 size_t auth_method_data_len{13};
192 auto auth_method_data_len_res = accu.template step<bw::FixedInt<1>>();
193 if (!accu.result()) return stdx::unexpected(accu.result().error());
194
195 // should be 21, but least 8
196 if (auth_method_data_len_res->value() < 8) {
198 }
199 auth_method_data_len = auth_method_data_len_res->value() - 8;
200 } else {
201 accu.template step<void>(1); // should be 0 ...
202 }
203
204 accu.template step<void>(10); // skip the filler
205
207 auth_method_data_2_res;
209 auth_method_res;
210 if (capabilities
212 // auth-method-data
213 auth_method_data_2_res =
214 accu.template step<bw::String<Borrowed>>(auth_method_data_len);
215
217 // auth_method
218 auth_method_res = accu.template step<bw::NulTermString<Borrowed>>();
219 }
220 }
221
222 if (!accu.result()) return stdx::unexpected(accu.result().error());
223
224 return std::make_pair(
225 accu.result().value(),
227 protocol_version_res->value(), version_res->value(),
228 connection_id_res->value(),
229 auth_method_data_res->value() + auth_method_data_2_res->value(),
230 capabilities, collation_res->value(), status_flags_res->value(),
231 auth_method_res->value()));
232 }
233 }
234
235 private:
237};
238
239/**
240 * codec for server::AuthMethodSwitch message.
241 */
242template <bool Borrowed>
243class Codec<borrowable::message::server::AuthMethodSwitch<Borrowed>>
244 : public impl::EncodeBase<
245 Codec<borrowable::message::server::AuthMethodSwitch<Borrowed>>> {
246 template <class Accumulator>
247 constexpr auto accumulate_fields(Accumulator &&accu) const {
248 namespace bw = borrowable::wire;
249
250 accu.step(bw::FixedInt<1>(cmd_byte()));
251
253 accu.step(bw::NulTermString<Borrowed>(v_.auth_method()))
254 .step(bw::String<Borrowed>(v_.auth_method_data()));
255 }
256
257 return accu.result();
258 }
259
260 public:
261 using value_type = borrowable::message::server::AuthMethodSwitch<Borrowed>;
263
264 friend __base;
265
267 : __base(caps), v_{std::move(v)} {}
268
269 static constexpr uint8_t cmd_byte() noexcept { return 0xfe; }
270
271 /**
272 * capabilities the codec depends on.
273 */
276 }
277
281
282 namespace bw = borrowable::wire;
283
284 // proto-version
285 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
286 if (!accu.result()) return stdx::unexpected(accu.result().error());
287
288 if (cmd_byte_res->value() != cmd_byte()) {
290 }
291
293 return std::make_pair(accu.result().value(), value_type());
294 }
295
296 auto auth_method_res = accu.template step<bw::NulTermString<Borrowed>>();
297 auto auth_method_data_res = accu.template step<bw::String<Borrowed>>();
298
299 if (!accu.result()) return stdx::unexpected(accu.result().error());
300
301 return std::make_pair(
302 accu.result().value(),
303 value_type(auth_method_res->value(), auth_method_data_res->value()));
304 }
305
306 private:
308};
309
310/**
311 * codec for server::AuthMethodData message.
312 */
313template <bool Borrowed>
314class Codec<borrowable::message::server::AuthMethodData<Borrowed>>
315 : public impl::EncodeBase<
316 Codec<borrowable::message::server::AuthMethodData<Borrowed>>> {
317 template <class Accumulator>
318 constexpr auto accumulate_fields(Accumulator &&accu) const {
319 namespace bw = borrowable::wire;
320
321 return accu.step(bw::FixedInt<1>(cmd_byte()))
322 .step(bw::String<Borrowed>(v_.auth_method_data()))
323 .result();
324 }
325
326 public:
327 using value_type = borrowable::message::server::AuthMethodData<Borrowed>;
329
330 friend __base;
331
333 : __base(caps), v_{std::move(v)} {}
334
335 static constexpr uint8_t cmd_byte() noexcept { return 0x01; }
336
337 /**
338 * capabilities the codec depends on.
339 */
341 return {};
342 }
343
347
348 namespace bw = borrowable::wire;
349
350 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
351 if (!accu.result()) return stdx::unexpected(accu.result().error());
352
353 if (cmd_byte_res->value() != cmd_byte()) {
355 }
356 auto auth_method_data_res = accu.template step<bw::String<Borrowed>>();
357
358 if (!accu.result()) return stdx::unexpected(accu.result().error());
359
360 return std::make_pair(accu.result().value(),
361 value_type(auth_method_data_res->value()));
362 }
363
364 private:
366};
367
368/**
369 * codec for server-side Ok message.
370 */
371template <bool Borrowed>
372class Codec<borrowable::message::server::Ok<Borrowed>>
373 : public impl::EncodeBase<
374 Codec<borrowable::message::server::Ok<Borrowed>>> {
375 template <class Accumulator>
376 constexpr auto accumulate_fields(Accumulator &&accu) const {
377 namespace bw = borrowable::wire;
378
379 accu.step(bw::FixedInt<1>(cmd_byte()))
380 .step(bw::VarInt(v_.affected_rows()))
381 .step(bw::VarInt(v_.last_insert_id()));
382
383 if (this->caps()[capabilities::pos::protocol_41] ||
384 this->caps()[capabilities::pos::transactions]) {
385 accu.step(bw::FixedInt<2>(v_.status_flags().to_ulong()));
386 if (this->caps().test(capabilities::pos::protocol_41)) {
387 accu.step(bw::FixedInt<2>(v_.warning_count()));
388 }
389 }
390
391 // if there is only empty "message" or "session-data", skip the rest.
392 const bool has_session_track_cap =
393 this->caps().test(capabilities::pos::session_track);
394
395 if (!v_.message().empty() || has_session_track_cap) {
396 accu.step(bw::VarString<Borrowed>(v_.message()));
397 if (has_session_track_cap &&
398 v_.status_flags().test(status::pos::session_state_changed)) {
399 accu.step(bw::VarString<Borrowed>(v_.session_changes()));
400 }
401 }
402
403 return accu.result();
404 }
405
406 public:
407 using value_type = borrowable::message::server::Ok<Borrowed>;
409
410 friend __base;
411
413 : __base(caps), v_{std::move(v)} {}
414
415 static constexpr uint8_t cmd_byte() noexcept { return 0x00; }
416
417 /**
418 * capabilities the codec depends on.
419 */
423 }
424
425 /**
426 * decode a server::Ok message from a buffer-sequence.
427 *
428 * precondition:
429 * - input starts with cmd_byte()
430 *
431 * @param buffer input buffser sequence
432 * @param caps protocol capabilities
433 *
434 * @retval std::pair<size_t, message::server::Ok> on success, with bytes
435 * processed
436 * @retval codec_errc::invalid_input if preconditions aren't met
437 * @retval codec_errc::not_enough_input not enough data to parse the whole
438 * message
439 */
443
444 namespace bw = borrowable::wire;
445
446 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
447 if (!accu.result()) return stdx::unexpected(accu.result().error());
448
449 if (cmd_byte_res->value() != cmd_byte()) {
451 }
452
453 auto affected_rows_res = accu.template step<bw::VarInt>();
454 auto last_insert_id_res = accu.template step<bw::VarInt>();
455
456 stdx::expected<bw::FixedInt<2>, std::error_code> status_flags_res(0);
457 stdx::expected<bw::FixedInt<2>, std::error_code> warning_count_res(0);
460 status_flags_res = accu.template step<bw::FixedInt<2>>();
462 warning_count_res = accu.template step<bw::FixedInt<2>>();
463 }
464 }
465
467 session_changes_res;
468 // if there is more data.
469 auto message_res = accu.template try_step<bw::VarString<Borrowed>>();
470 if (message_res) {
472 if (status_flags_res->value() &
474 session_changes_res = accu.template step<bw::VarString<Borrowed>>();
475 }
476 }
477 } else {
478 // no message field == empty message.
479 message_res = {};
480 }
481
482 if (!accu.result()) return stdx::unexpected(accu.result().error());
483
484 return std::make_pair(
485 accu.result().value(),
486 value_type(affected_rows_res->value(), last_insert_id_res->value(),
487 status_flags_res->value(), warning_count_res->value(),
488 message_res->value(), session_changes_res->value()));
489 }
490
491 private:
493};
494
495/**
496 * codec for server-side Eof message.
497 *
498 * Eof message is encoded differently dependending on protocol capabiltiies,
499 * but always starts with:
500 *
501 * - 0xef
502 *
503 * If capabilities has text_result_with_session_tracking, it is followed by
504 * - [rest of Ok packet]
505 *
506 * otherwise, if capabilities has protocol_41
507 * - FixedInt<2> warning-count
508 * - FixedInt<2> status flags
509 *
510 * otherwise
511 * - nothing
512 */
513template <bool Borrowed>
514class Codec<borrowable::message::server::Eof<Borrowed>>
515 : public impl::EncodeBase<
516 Codec<borrowable::message::server::Eof<Borrowed>>> {
517 template <class Accumulator>
518 constexpr auto accumulate_fields(Accumulator &&accu) const {
519 namespace bw = borrowable::wire;
520
521 accu.step(bw::FixedInt<1>(cmd_byte()));
522
523 auto shared_caps = this->caps();
524
525 if (shared_caps.test(
527 accu.step(bw::VarInt(v_.affected_rows()))
528 .step(bw::VarInt(v_.last_insert_id()));
529
530 if (shared_caps[capabilities::pos::protocol_41] ||
531 shared_caps[capabilities::pos::transactions]) {
532 accu.step(bw::FixedInt<2>(v_.status_flags().to_ulong()));
533 if (shared_caps[capabilities::pos::protocol_41]) {
534 accu.step(bw::FixedInt<2>(v_.warning_count()));
535 }
536 }
537
538 if (shared_caps[capabilities::pos::session_track]) {
539 if (!v_.message().empty() ||
540 v_.status_flags()[status::pos::session_state_changed]) {
541 // only write message and session-changes if both of them aren't
542 // empty.
543 accu.step(bw::VarString<Borrowed>(v_.message()));
544 if (v_.status_flags()[status::pos::session_state_changed]) {
545 accu.step(bw::VarString<Borrowed>(v_.session_changes()));
546 }
547 }
548 } else {
549 accu.step(bw::String<Borrowed>(v_.message()));
550 }
551 } else if (shared_caps[capabilities::pos::protocol_41]) {
552 accu.step(bw::FixedInt<2>(v_.warning_count()))
553 .step(bw::FixedInt<2>(v_.status_flags().to_ulong()));
554 }
555
556 return accu.result();
557 }
558
559 public:
560 using value_type = borrowable::message::server::Eof<Borrowed>;
562
563 friend __base;
564
566 : __base(caps), v_{std::move(v)} {}
567
568 static constexpr uint8_t cmd_byte() noexcept { return 0xfe; }
569
570 /**
571 * capabilities the codec depends on.
572 */
577 }
578
579 /**
580 * decode a server::Eof message from a buffer-sequence.
581 *
582 * capabilities checked:
583 * - protocol_41
584 * - text_resultset_with_session_tracking
585 *
586 * precondition:
587 * - input starts with cmd_byte()
588 *
589 * @param buffer input buffser sequence
590 * @param caps protocol capabilities
591 *
592 * @retval std::pair<size_t, message::server::Eof> on success, with bytes
593 * processed
594 * @retval codec_errc::invalid_input if preconditions aren't met
595 * @retval codec_errc::not_enough_input not enough data to parse the whole
596 * message
597 */
601
602 namespace bw = borrowable::wire;
603
604 const auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
605 if (!accu.result()) return stdx::unexpected(accu.result().error());
606
607 if (cmd_byte_res->value() != cmd_byte()) {
609 }
610
612 const auto affected_rows_res = accu.template step<bw::VarInt>();
613 const auto last_insert_id_res = accu.template step<bw::VarInt>();
614
615 stdx::expected<bw::FixedInt<2>, std::error_code> status_flags_res(0);
616 stdx::expected<bw::FixedInt<2>, std::error_code> warning_count_res(0);
619 status_flags_res = accu.template step<bw::FixedInt<2>>();
621 warning_count_res = accu.template step<bw::FixedInt<2>>();
622 }
623 }
624
625 stdx::expected<bw::String<Borrowed>, std::error_code> message_res;
627 session_state_info_res;
629 // when session-track is supported, the 'message' part is a VarString.
630 // But only if there is actually session-data and the message has data.
631 const auto var_message_res =
632 accu.template try_step<bw::VarString<Borrowed>>();
633 if (var_message_res) {
634 // set the message from the var-string
635 message_res = var_message_res.value();
636 }
637
638 if (status_flags_res->value() &
640 session_state_info_res =
641 accu.template step<bw::VarString<Borrowed>>();
642 }
643 } else {
644 message_res = accu.template step<bw::String<Borrowed>>();
645 }
646
647 if (!accu.result()) return stdx::unexpected(accu.result().error());
648
649 return std::make_pair(
650 accu.result().value(),
651 value_type(affected_rows_res->value(), last_insert_id_res->value(),
652 status_flags_res->value(), warning_count_res->value(),
653 message_res->value(), session_state_info_res->value()));
654 } else if (caps[capabilities::pos::protocol_41]) {
655 const auto warning_count_res = accu.template step<bw::FixedInt<2>>();
656 const auto status_flags_res = accu.template step<bw::FixedInt<2>>();
657
658 return std::make_pair(
659 accu.result().value(),
660 value_type(status_flags_res->value(), warning_count_res->value()));
661 } else {
662 return std::make_pair(accu.result().value(), value_type());
663 }
664 }
665
666 private:
668};
669
670/**
671 * codec for Error message.
672 *
673 * note: Format overview:
674 *
675 * 3.21: protocol_version <= 9 [not supported]
676 *
677 * FixedInt<1> 0xff
678 * String message
679 *
680 * 3.21: protocol_version > 9
681 *
682 * FixedInt<1> 0xff
683 * FixedInt<2> error_code
684 * String message
685 *
686 * 4.1 and later:
687 *
688 * FixedInt<1> 0xff
689 * FixedInt<2> error_code
690 * '#'
691 * String<5> sql_state
692 * String message
693 */
694template <bool Borrowed>
695class Codec<borrowable::message::server::Error<Borrowed>>
696 : public impl::EncodeBase<
697 Codec<borrowable::message::server::Error<Borrowed>>> {
698 template <class Accumulator>
699 constexpr auto accumulate_fields(Accumulator &&accu) const {
700 namespace bw = borrowable::wire;
701
702 accu.step(bw::FixedInt<1>(cmd_byte()))
703 .step(bw::FixedInt<2>(v_.error_code()));
704 if (this->caps()[capabilities::pos::protocol_41]) {
705 accu.step(bw::FixedInt<1>('#'))
706 .step(bw::String<Borrowed>(v_.sql_state()));
707 }
708
709 return accu.step(bw::String<Borrowed>(v_.message())).result();
710 }
711
712 public:
713 using value_type = borrowable::message::server::Error<Borrowed>;
715
716 friend __base;
717
719 : __base(caps), v_{std::move(v)} {}
720
721 static constexpr uint8_t cmd_byte() { return 0xff; }
722
723 /**
724 * capabilities the codec depends on.
725 */
728 }
729
730 static constexpr size_t max_size() noexcept {
732 }
733
737
738 namespace bw = borrowable::wire;
739
740 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
741 if (!accu.result()) return stdx::unexpected(accu.result().error());
742
743 if (cmd_byte_res->value() != cmd_byte()) {
745 }
746
747 // decode all fields, check result later before they are used.
748 auto error_code_res = accu.template step<bw::FixedInt<2>>();
749 stdx::expected<bw::String<Borrowed>, std::error_code> sql_state_res;
751 auto sql_state_hash_res = accu.template step<bw::FixedInt<1>>();
752 if (!sql_state_hash_res) {
753 return stdx::unexpected(sql_state_hash_res.error());
754 }
755 sql_state_res = accu.template step<bw::String<Borrowed>>(5);
756 }
757 auto message_res = accu.template step<bw::String<Borrowed>>();
758
759 if (!accu.result()) return stdx::unexpected(accu.result().error());
760
761 return std::make_pair(
762 accu.result().value(),
763 value_type(error_code_res->value(), message_res->value(),
764 sql_state_res->value()));
765 }
766
767 private:
769};
770
771/**
772 * codec for ColumnCount message.
773 */
774template <>
776 : public impl::EncodeBase<Codec<borrowable::message::server::ColumnCount>> {
777 template <class Accumulator>
778 constexpr auto accumulate_fields(Accumulator &&accu) const {
779 namespace bw = borrowable::wire;
780
781 return accu.step(bw::VarInt(v_.count())).result();
782 }
783
784 public:
787
788 friend __base;
789
791 : __base(caps), v_{std::move(v)} {}
792
793 static constexpr size_t max_size() noexcept {
795 }
796
800
801 namespace bw = borrowable::wire;
802
803 auto count_res = accu.template step<bw::VarInt>();
804 if (!accu.result()) return stdx::unexpected(accu.result().error());
805
806 return std::make_pair(accu.result().value(),
807 value_type(count_res->value()));
808 }
809
810 private:
812};
813
814/**
815 * Codec of ColumnMeta.
816 *
817 * capabilities checked:
818 * - protocol_41
819 */
820template <bool Borrowed>
821class Codec<borrowable::message::server::ColumnMeta<Borrowed>>
822 : public impl::EncodeBase<
823 Codec<borrowable::message::server::ColumnMeta<Borrowed>>> {
824 template <class Accumulator>
825 auto accumulate_fields(Accumulator &&accu) const {
826 namespace bw = borrowable::wire;
827
828 if (!this->caps()[capabilities::pos::protocol_41]) {
829 accu.step(bw::VarString<Borrowed>(v_.table()))
830 .step(bw::VarString<Borrowed>(v_.name()))
831 .step(bw::VarInt(3))
832 .step(bw::FixedInt<3>(v_.column_length()))
833 .step(bw::VarInt(1))
834 .step(bw::FixedInt<1>(v_.type()));
835
836 if (this->caps()[capabilities::pos::long_flag]) {
837 accu.step(bw::VarInt(3))
838 .step(bw::FixedInt<2>(v_.flags().to_ulong()))
839 .step(bw::FixedInt<1>(v_.decimals()));
840 } else {
841 accu.step(bw::VarInt(2))
842 .step(bw::FixedInt<1>(v_.flags().to_ulong()))
843 .step(bw::FixedInt<1>(v_.decimals()));
844 }
845
846 return accu.result();
847 } else {
848 return accu.step(bw::VarString<Borrowed>(v_.catalog()))
849 .step(bw::VarString<Borrowed>(v_.schema()))
850 .step(bw::VarString<Borrowed>(v_.table()))
851 .step(bw::VarString<Borrowed>(v_.orig_table()))
852 .step(bw::VarString<Borrowed>(v_.name()))
853 .step(bw::VarString<Borrowed>(v_.orig_name()))
854 .step(bw::VarInt(12))
855 .step(bw::FixedInt<2>(v_.collation()))
856 .step(bw::FixedInt<4>(v_.column_length()))
857 .step(bw::FixedInt<1>(v_.type()))
858 .step(bw::FixedInt<2>(v_.flags().to_ulong()))
859 .step(bw::FixedInt<1>(v_.decimals()))
860 .step(bw::FixedInt<2>(0))
861 .result();
862 }
863 }
864
865 public:
866 using value_type = borrowable::message::server::ColumnMeta<Borrowed>;
868
869 friend __base;
870
872 : __base(caps), v_{std::move(v)} {}
873
874 static size_t max_size() noexcept {
876 }
877
881
882 namespace bw = borrowable::wire;
883
885 // 3.2x protocol used up to 4.0.x
886
887 // bit-size of the 'flags' field
888 const uint8_t flags_size = caps[capabilities::pos::long_flag] ? 2 : 1;
889
890 const auto table_res = accu.template step<bw::VarString<Borrowed>>();
891 const auto name_res = accu.template step<bw::VarString<Borrowed>>();
892
893 const auto column_length_len_res = accu.template step<bw::VarInt>();
894 if (!accu.result()) return stdx::unexpected(accu.result().error());
895
896 if (column_length_len_res->value() != 3) {
898 }
899
900 const auto column_length_res = accu.template step<bw::FixedInt<3>>();
901 const auto type_len_res = accu.template step<bw::VarInt>();
902 if (!accu.result()) return stdx::unexpected(accu.result().error());
903
904 if (type_len_res->value() != 1) {
906 }
907
908 const auto type_res = accu.template step<bw::FixedInt<1>>();
909 const auto flags_and_decimals_len_res = accu.template step<bw::VarInt>();
910 if (!accu.result()) return stdx::unexpected(accu.result().error());
911
912 if (flags_and_decimals_len_res->value() != flags_size + 1) {
914 }
915
916 stdx::expected<bw::FixedInt<3>, std::error_code> flags_and_decimals_res(
917 0);
918 if (flags_size == 2) {
919 flags_and_decimals_res = accu.template step<bw::FixedInt<3>>();
920 } else {
921 const auto small_flags_and_decimals_res =
922 accu.template step<bw::FixedInt<2>>();
923 if (small_flags_and_decimals_res) {
924 flags_and_decimals_res =
925 bw::FixedInt<3>(small_flags_and_decimals_res->value());
926 }
927 }
928
929 if (!accu.result()) return stdx::unexpected(accu.result().error());
930
931 const uint16_t flags =
932 flags_and_decimals_res->value() & ((1 << (flags_size * 8)) - 1);
933 const uint8_t decimals =
934 flags_and_decimals_res->value() >> (flags_size * 8);
935
936 return std::make_pair(
937 accu.result().value(),
938 value_type({}, {}, table_res->value(), {}, name_res->value(), {}, {},
939 column_length_res->value(), type_res->value(), flags,
940 decimals));
941 } else {
942 const auto catalog_res = accu.template step<bw::VarString<Borrowed>>();
943 const auto schema_res = accu.template step<bw::VarString<Borrowed>>();
944 const auto table_res = accu.template step<bw::VarString<Borrowed>>();
945 const auto orig_table_res = accu.template step<bw::VarString<Borrowed>>();
946 const auto name_res = accu.template step<bw::VarString<Borrowed>>();
947 const auto orig_name_res = accu.template step<bw::VarString<Borrowed>>();
948
949 /* next is a collection of fields which is wrapped inside a varstring of
950 * 12-bytes size */
951 const auto other_len_res = accu.template step<bw::VarInt>();
952
953 if (other_len_res->value() != 12) {
955 }
956
957 const auto collation_res = accu.template step<bw::FixedInt<2>>();
958 const auto column_length_res = accu.template step<bw::FixedInt<4>>();
959 const auto type_res = accu.template step<bw::FixedInt<1>>();
960 const auto flags_res = accu.template step<bw::FixedInt<2>>();
961 const auto decimals_res = accu.template step<bw::FixedInt<1>>();
962
963 accu.template step<void>(2); // fillers
964
965 if (!accu.result()) return stdx::unexpected(accu.result().error());
966
967 return std::make_pair(
968 accu.result().value(),
969 value_type(catalog_res->value(), schema_res->value(),
970 table_res->value(), orig_table_res->value(),
971 name_res->value(), orig_name_res->value(),
972 collation_res->value(), column_length_res->value(),
973 type_res->value(), flags_res->value(),
974 decimals_res->value()));
975 }
976 }
977
978 private:
980};
981
982/**
983 * codec for server's SendFileRequest response.
984 *
985 * sent as response after client::Query
986 *
987 * layout:
988 *
989 * 0xfb<filename>
990 */
991template <bool Borrowed>
992class Codec<borrowable::message::server::SendFileRequest<Borrowed>>
993 : public impl::EncodeBase<
994 Codec<borrowable::message::server::SendFileRequest<Borrowed>>> {
995 template <class Accumulator>
996 constexpr auto accumulate_fields(Accumulator &&accu) const {
997 namespace bw = borrowable::wire;
998
999 return accu.step(bw::FixedInt<1>(cmd_byte()))
1000 .step(bw::String<Borrowed>(v_.filename()))
1001 .result();
1002 }
1003
1004 public:
1005 using value_type = borrowable::message::server::SendFileRequest<Borrowed>;
1007
1008 friend __base;
1009
1011 : __base(caps), v_{std::move(v)} {}
1012
1013 static constexpr uint8_t cmd_byte() noexcept { return 0xfb; }
1014
1015 /**
1016 * capabilities the codec depends on.
1017 */
1019 return {};
1020 }
1021
1025
1026 namespace bw = borrowable::wire;
1027
1028 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
1029 if (!accu.result()) return stdx::unexpected(accu.result().error());
1030
1031 if (cmd_byte_res->value() != cmd_byte()) {
1033 }
1034
1035 auto filename_res = accu.template step<bw::String<Borrowed>>();
1036 if (!accu.result()) return stdx::unexpected(accu.result().error());
1037
1038 return std::make_pair(accu.result().value(),
1039 value_type(filename_res->value()));
1040 }
1041
1042 private:
1044};
1045
1046/**
1047 * codec for server::StmtPrepareOk message.
1048 *
1049 * format:
1050 *
1051 * - FixedInt<1> == 0x00 [ok]
1052 * - FixedInt<4> stmt-id
1053 * - FixedInt<2> column-count
1054 * - FixedInt<2> param-count
1055 * - FixedInt<1> == 0x00 [filler]
1056 * - FixedInt<2> warning-count
1057 *
1058 * If caps contains optional_resultset_metadata:
1059 *
1060 * - FixedInt<1> with_metadata
1061 *
1062 * sent as response after a client::StmtPrepare
1063 */
1064template <>
1066 : public impl::EncodeBase<
1067 Codec<borrowable::message::server::StmtPrepareOk>> {
1068 template <class Accumulator>
1069 constexpr auto accumulate_fields(Accumulator &&accu) const {
1070 namespace bw = borrowable::wire;
1071
1072 accu.step(bw::FixedInt<1>(cmd_byte()))
1073 .step(bw::FixedInt<4>(v_.statement_id()))
1074 .step(bw::FixedInt<2>(v_.column_count()))
1075 .step(bw::FixedInt<2>(v_.param_count()))
1076 .step(bw::FixedInt<1>(0))
1077 .step(bw::FixedInt<2>(v_.warning_count()));
1078
1080 accu.step(bw::FixedInt<1>(v_.with_metadata()));
1081 }
1082
1083 return accu.result();
1084 }
1085
1086 public:
1089
1090 friend __base;
1091
1093 : __base(caps), v_{std::move(v)} {}
1094
1095 constexpr static uint8_t cmd_byte() noexcept { return 0x00; }
1096
1097 /**
1098 * capabilities the codec depends on.
1099 */
1102 }
1103
1107
1108 namespace bw = borrowable::wire;
1109
1110 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
1111 if (!cmd_byte_res) return stdx::unexpected(cmd_byte_res.error());
1112 auto stmt_id_res = accu.template step<bw::FixedInt<4>>();
1113 auto column_count_res = accu.template step<bw::FixedInt<2>>();
1114 auto param_count_res = accu.template step<bw::FixedInt<2>>();
1115 auto filler_res = accu.template step<bw::FixedInt<1>>();
1116 if (!filler_res) return stdx::unexpected(filler_res.error());
1117 auto warning_count_res = accu.template step<bw::FixedInt<2>>();
1118
1119 // by default, metadata isn't optional
1120 int8_t with_metadata{1};
1122 auto with_metadata_res = accu.template step<bw::FixedInt<1>>();
1123
1124 if (with_metadata_res) {
1125 with_metadata = with_metadata_res->value();
1126 }
1127 }
1128
1129 if (!accu.result()) return stdx::unexpected(accu.result().error());
1130
1131 return std::make_pair(
1132 accu.result().value(),
1133 value_type(stmt_id_res->value(), column_count_res->value(),
1134 param_count_res->value(), warning_count_res->value(),
1135 with_metadata));
1136 }
1137
1138 private:
1140};
1141
1142/**
1143 * codec for a Row from the server.
1144 */
1145template <bool Borrowed>
1146class Codec<borrowable::message::server::Row<Borrowed>>
1147 : public impl::EncodeBase<
1148 Codec<borrowable::message::server::Row<Borrowed>>> {
1149 template <class Accumulator>
1150 auto accumulate_fields(Accumulator &&accu) const {
1151 namespace bw = borrowable::wire;
1152
1153 for (const auto &field : v_) {
1154 if (field) {
1155 accu.step(bw::VarString<Borrowed>(*field));
1156 } else {
1157 accu.step(bw::Null());
1158 }
1159 }
1160
1161 return accu.result();
1162 }
1163
1164 public:
1165 using value_type = borrowable::message::server::Row<Borrowed>;
1167
1168 friend __base;
1169
1171 : __base(caps), v_{std::move(v)} {}
1172
1173 static size_t max_size() noexcept {
1175 }
1176
1180
1181 namespace bw = borrowable::wire;
1182
1183 std::vector<typename value_type::value_type> fields;
1184
1185 const size_t buf_size = buffer_size(buffer);
1186
1187 while (accu.result() && (accu.result().value() < buf_size)) {
1188 // field may other be a Null or a VarString
1189 auto null_res = accu.template try_step<bw::Null>();
1190 if (null_res) {
1191 fields.emplace_back(std::nullopt);
1192 } else {
1193 auto field_res = accu.template step<bw::VarString<Borrowed>>();
1194 if (!field_res) return stdx::unexpected(field_res.error());
1195
1196 fields.emplace_back(field_res->value());
1197 }
1198 }
1199
1200 if (!accu.result()) return stdx::unexpected(accu.result().error());
1201
1202 return std::make_pair(accu.result().value(), value_type(fields));
1203 }
1204
1205 private:
1207};
1208
1209/**
1210 * codec for a StmtRow from the server.
1211 *
1212 * StmtRow is the Row of a StmtExecute's resultset.
1213 *
1214 * - 0x00
1215 * - NULL bitmap
1216 * - non-NULL-values in binary encoding
1217 *
1218 * both encode and decode require type information to know:
1219 *
1220 * - size the NULL bitmap
1221 * - length of each field
1222 */
1223template <bool Borrowed>
1224class Codec<borrowable::message::server::StmtRow<Borrowed>>
1225 : public impl::EncodeBase<
1226 Codec<borrowable::message::server::StmtRow<Borrowed>>> {
1227 template <class Accumulator>
1228 auto accumulate_fields(Accumulator &&accu) const {
1229 namespace bw = borrowable::wire;
1230
1231 accu.step(bw::FixedInt<1>(0));
1232
1233 // null-bitmap starts with a 2-bit offset
1234 size_t bit_pos{2};
1235 uint8_t null_bit_byte{};
1236
1237 for (auto const &field : v_) {
1238 if (!field) null_bit_byte |= (1 << bit_pos);
1239
1240 if (++bit_pos > 7) {
1241 accu.step(bw::FixedInt<1>(null_bit_byte));
1242
1243 bit_pos = 0;
1244 null_bit_byte = 0;
1245 }
1246 }
1247
1248 if (bit_pos != 0) accu.step(bw::FixedInt<1>(null_bit_byte));
1249
1250 for (auto [n, field] : stdx::views::enumerate(v_)) {
1251 if (!field) continue;
1252
1253 switch (v_.types()[n]) {
1254 case field_type::Bit:
1255 case field_type::Blob:
1258 case field_type::Set:
1259 case field_type::String:
1260 case field_type::Enum:
1267 accu.step(bw::VarInt(field->size()));
1268 break;
1269 case field_type::Date:
1272 case field_type::Time:
1273 accu.step(bw::FixedInt<1>(field->size()));
1274 break;
1276 case field_type::Double:
1277 case field_type::Long:
1278 case field_type::Int24:
1279 case field_type::Float:
1280 case field_type::Short:
1281 case field_type::Year:
1282 case field_type::Tiny:
1283 // fixed size
1284 break;
1285 }
1286 accu.step(borrowed::wire::String(*field));
1287 }
1288
1289 return accu.result();
1290 }
1291
1292 public:
1293 using value_type = borrowable::message::server::StmtRow<Borrowed>;
1295
1296 friend __base;
1297
1299 : __base(caps), v_{std::move(v)} {}
1300
1301 static size_t max_size() noexcept {
1303 }
1304
1307 std::vector<field_type::value_type> types) {
1308 namespace bw = borrowable::wire;
1309
1311
1312 const auto row_byte_res = accu.template step<bw::FixedInt<1>>();
1313 if (!accu.result()) return stdx::unexpected(accu.result().error());
1314
1315 // first byte is 0x00
1316 if (row_byte_res->value() != 0x00) {
1318 }
1319
1320 const auto nullbits_res =
1321 accu.template step<bw::String<Borrowed>>(bytes_per_bits(types.size()));
1322 if (!accu.result()) return stdx::unexpected(accu.result().error());
1323
1324 const auto nullbits = nullbits_res->value();
1325
1326 std::vector<typename value_type::value_type> values;
1327
1328 for (size_t n{}, bit_pos{2}, byte_pos{}; n < types.size(); ++n, ++bit_pos) {
1329 if (bit_pos > 7) {
1330 bit_pos = 0;
1331 ++byte_pos;
1332 }
1333
1334 if (!(nullbits[byte_pos] & (1 << bit_pos))) {
1336 stdx::unexpected(make_error_code(std::errc::invalid_argument)));
1337 switch (types[n]) {
1338 case field_type::Bit:
1339 case field_type::Blob:
1342 case field_type::Set:
1343 case field_type::String:
1344 case field_type::Enum:
1350 case field_type::Geometry: {
1351 auto string_field_size_res = accu.template step<bw::VarInt>();
1352 if (!accu.result()) return stdx::unexpected(accu.result().error());
1353
1354 field_size_res = string_field_size_res->value();
1355 } break;
1356 case field_type::Date:
1359 case field_type::Time: {
1360 auto time_field_size_res = accu.template step<bw::FixedInt<1>>();
1361 if (!accu.result()) return stdx::unexpected(accu.result().error());
1362
1363 field_size_res = time_field_size_res->value();
1364 } break;
1366 case field_type::Double:
1367 field_size_res = 8;
1368 break;
1369 case field_type::Long:
1370 case field_type::Int24:
1371 case field_type::Float:
1372 field_size_res = 4;
1373 break;
1374 case field_type::Short:
1375 case field_type::Year:
1376 field_size_res = 2;
1377 break;
1378 case field_type::Tiny:
1379 field_size_res = 1;
1380 break;
1381 }
1382
1383 if (!field_size_res) {
1384 return stdx::unexpected(
1386 }
1387
1388 const auto value_res =
1389 accu.template step<bw::String<Borrowed>>(field_size_res.value());
1390 if (!accu.result()) return stdx::unexpected(accu.result().error());
1391
1392 values.push_back(value_res->value());
1393 } else {
1394 values.emplace_back(std::nullopt);
1395 }
1396 }
1397
1398 if (!accu.result()) return stdx::unexpected(accu.result().error());
1399
1400 return std::make_pair(accu.result().value(), value_type(types, values));
1401 }
1402
1403 private:
1405};
1406
1407/**
1408 * codec for server::Statistics message.
1409 */
1410template <bool Borrowed>
1411class Codec<borrowable::message::server::Statistics<Borrowed>>
1412 : public impl::EncodeBase<
1413 Codec<borrowable::message::server::Statistics<Borrowed>>> {
1414 template <class Accumulator>
1415 constexpr auto accumulate_fields(Accumulator &&accu) const {
1416 namespace bw = borrowable::wire;
1417
1418 return accu.step(bw::String<Borrowed>(v_.stats())).result();
1419 }
1420
1421 public:
1422 using value_type = borrowable::message::server::Statistics<Borrowed>;
1424
1425 friend __base;
1426
1428 : __base(caps), v_{std::move(v)} {}
1429
1433
1434 namespace bw = borrowable::wire;
1435
1436 auto stats_res = accu.template step<bw::String<Borrowed>>();
1437
1438 if (!accu.result()) return stdx::unexpected(accu.result().error());
1439
1440 return std::make_pair(accu.result().value(),
1441 value_type(stats_res->value()));
1442 }
1443
1444 private:
1446};
1447
1448/**
1449 * CRTP base for client-side commands that are encoded as a single byte.
1450 */
1451template <class Base, class ValueType>
1453 : public impl::EncodeBase<CodecSimpleCommand<Base, ValueType>> {
1454 template <class Accumulator>
1455 constexpr auto accumulate_fields(Accumulator &&accu) const {
1456 namespace bw = borrowable::wire;
1457
1458 return accu.step(bw::FixedInt<1>(Base::cmd_byte())).result();
1459 }
1460
1461 public:
1463
1464 friend __base;
1465
1467
1468 static constexpr size_t max_size() noexcept { return 1; }
1469
1473
1474 namespace bw = borrowable::wire;
1475
1476 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
1477 if (!accu.result()) return stdx::unexpected(accu.result().error());
1478
1479 if (cmd_byte_res->value() != Base::cmd_byte()) {
1481 }
1482
1483 return std::make_pair(accu.result().value(), ValueType());
1484 }
1485};
1486
1487enum class CommandByte {
1488 Quit = 0x01,
1489 InitSchema,
1490 Query,
1491 ListFields,
1492 CreateDb,
1493 DropDb,
1494 Refresh,
1495 Shutdown,
1496 Statistics,
1498 Connect,
1500 Debug,
1501 Ping,
1502 Time,
1504 ChangeUser,
1505 BinlogDump,
1506 TableDump,
1507 ConnectOut,
1512 StmtClose,
1513 StmtReset,
1514 SetOption,
1515 StmtFetch,
1516 Deamon,
1519 Clone
1520};
1521
1522/**
1523 * codec for client's Quit command.
1524 */
1525template <>
1527 : public CodecSimpleCommand<Codec<borrowable::message::client::Quit>,
1528 borrowable::message::client::Quit> {
1529 public:
1532
1534
1535 constexpr static uint8_t cmd_byte() noexcept {
1536 return static_cast<uint8_t>(CommandByte::Quit);
1537 }
1538
1539 /**
1540 * capabilities the codec depends on.
1541 */
1543 return {};
1544 }
1545};
1546
1547/**
1548 * codec for client's ResetConnection command.
1549 */
1550template <>
1552 : public CodecSimpleCommand<
1553 Codec<borrowable::message::client::ResetConnection>,
1554 borrowable::message::client::ResetConnection> {
1555 public:
1558
1560
1561 constexpr static uint8_t cmd_byte() noexcept {
1562 return static_cast<uint8_t>(CommandByte::ResetConnection);
1563 }
1564
1565 /**
1566 * capabilities the codec depends on.
1567 */
1569 return {};
1570 }
1571};
1572
1573/**
1574 * codec for client's Ping command.
1575 */
1576template <>
1578 : public CodecSimpleCommand<Codec<borrowable::message::client::Ping>,
1579 borrowable::message::client::Ping> {
1580 public:
1583
1585
1586 constexpr static uint8_t cmd_byte() noexcept {
1587 return static_cast<uint8_t>(CommandByte::Ping);
1588 }
1589
1590 /**
1591 * capabilities the codec depends on.
1592 */
1594 return {};
1595 }
1596};
1597
1598/**
1599 * codec for client's Statistics command.
1600 */
1601template <>
1603 : public CodecSimpleCommand<Codec<borrowable::message::client::Statistics>,
1604 borrowable::message::client::Statistics> {
1605 public:
1608
1610
1611 constexpr static uint8_t cmd_byte() noexcept {
1612 return static_cast<uint8_t>(CommandByte::Statistics);
1613 }
1614
1615 /**
1616 * capabilities the codec depends on.
1617 */
1619 return {};
1620 }
1621};
1622
1623/**
1624 * codec for client's Debug command.
1625 */
1626template <>
1628 : public CodecSimpleCommand<Codec<borrowable::message::client::Debug>,
1629 borrowable::message::client::Debug> {
1630 public:
1633
1635
1636 constexpr static uint8_t cmd_byte() noexcept {
1637 return static_cast<uint8_t>(CommandByte::Debug);
1638 }
1639
1640 /**
1641 * capabilities the codec depends on.
1642 */
1644 return {};
1645 }
1646};
1647
1648/**
1649 * codec for client's InitSchema command.
1650 */
1651template <bool Borrowed>
1652class Codec<borrowable::message::client::InitSchema<Borrowed>>
1653 : public impl::EncodeBase<
1654 Codec<borrowable::message::client::InitSchema<Borrowed>>> {
1655 template <class Accumulator>
1656 constexpr auto accumulate_fields(Accumulator &&accu) const {
1657 namespace bw = borrowable::wire;
1658
1659 return accu.step(bw::FixedInt<1>(cmd_byte()))
1660 .step(bw::String<Borrowed>(v_.schema()))
1661 .result();
1662 }
1663
1664 public:
1667
1668 friend __base;
1669
1671 : __base(caps), v_{std::move(v)} {}
1672
1673 constexpr static uint8_t cmd_byte() noexcept {
1674 return static_cast<uint8_t>(CommandByte::InitSchema);
1675 }
1676
1677 /**
1678 * capabilities the codec depends on.
1679 */
1681 return {};
1682 }
1683
1687
1688 namespace bw = borrowable::wire;
1689
1690 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
1691 if (!accu.result()) return stdx::unexpected(accu.result().error());
1692
1693 if (cmd_byte_res->value() != cmd_byte()) {
1695 }
1696
1697 auto schema_res = accu.template step<bw::String<Borrowed>>();
1698 if (!accu.result()) return stdx::unexpected(accu.result().error());
1699
1700 return std::make_pair(accu.result().value(),
1701 value_type(schema_res->value()));
1702 }
1703
1704 private:
1706};
1707
1708/**
1709 * codec for client's Query command.
1710 */
1711template <bool Borrowed>
1712class Codec<borrowable::message::client::Query<Borrowed>>
1713 : public impl::EncodeBase<
1714 Codec<borrowable::message::client::Query<Borrowed>>> {
1715 template <class Accumulator>
1716 auto accumulate_fields(Accumulator &&accu) const {
1717 namespace bw = borrowable::wire;
1718
1719 accu.step(bw::FixedInt<1>(cmd_byte()));
1720
1721 auto caps = this->caps();
1722
1723 if (caps.test(capabilities::pos::query_attributes)) {
1724 uint64_t param_count = v_.values().size();
1725 accu.step(bw::VarInt(param_count)); // param_count
1726 accu.step(bw::VarInt(1)); // param_set_count: always 1
1727
1728 if (param_count > 0) {
1729 // mark all that are NULL in the nullbits
1730 //
1731 // - one bit per parameter to send
1732 // - if a parameter is NULL, the bit is set, and later no value is
1733 // added.
1734
1735 uint8_t null_bit_byte{};
1736 int bit_pos{};
1737
1738 for (auto const &param : v_.values()) {
1739 if (!param.value) null_bit_byte |= 1 << bit_pos;
1740
1741 if (++bit_pos > 7) {
1742 accu.step(bw::FixedInt<1>(null_bit_byte));
1743
1744 bit_pos = 0;
1745 null_bit_byte = 0;
1746 }
1747 }
1748
1749 if (bit_pos != 0) accu.step(bw::FixedInt<1>(null_bit_byte));
1750
1751 accu.step(bw::FixedInt<1>(1)); // new_param_bind_flag: always 1
1752
1753 for (const auto &param : v_.values()) {
1754 accu.step(bw::FixedInt<2>(param.type_and_flags))
1755 .step(bw::VarString<Borrowed>(param.name));
1756 }
1757
1758 for (const auto &param : v_.values()) {
1759 if (!param.value) continue;
1760
1761 auto type = param.type_and_flags & 0xff;
1762 switch (type) {
1763 case field_type::Bit:
1764 case field_type::Blob:
1767 case field_type::Set:
1768 case field_type::String:
1769 case field_type::Enum:
1774 case field_type::Json:
1777 accu.template step<bw::VarInt>(param.value->size());
1778 break;
1779 case field_type::Date:
1782 case field_type::Time:
1783 assert(param.value->size() <= 255);
1784
1785 accu.template step<bw::FixedInt<1>>(param.value->size());
1786
1787 break;
1789 case field_type::Double:
1790 assert(param.value->size() == 8);
1791
1792 break;
1793 case field_type::Long:
1794 case field_type::Int24:
1795 case field_type::Float:
1796 assert(param.value->size() == 4);
1797
1798 break;
1799 case field_type::Short:
1800 case field_type::Year:
1801 assert(param.value->size() == 2);
1802
1803 break;
1804 case field_type::Tiny:
1805 assert(param.value->size() == 1);
1806
1807 break;
1808 default:
1809 assert(true || "unknown field-type");
1810 break;
1811 }
1812 accu.template step<bw::String<Borrowed>>(*param.value);
1813 }
1814 }
1815 }
1816
1817 accu.step(bw::String<Borrowed>(v_.statement()));
1818 return accu.result();
1819 }
1820
1821 template <class Accu>
1823 Accu &accu, uint8_t type) {
1824 namespace bw = borrowable::wire;
1825
1826 switch (type) {
1827 case field_type::Bit:
1828 case field_type::Blob:
1831 case field_type::Set:
1832 case field_type::String:
1833 case field_type::Enum:
1838 case field_type::Json:
1840 case field_type::Geometry: {
1841 auto string_field_size_res = accu.template step<bw::VarInt>();
1842 if (!accu.result()) {
1843 return stdx::unexpected(accu.result().error());
1844 }
1845
1846 return string_field_size_res->value();
1847 }
1848 case field_type::Date:
1851 case field_type::Time: {
1852 auto time_field_size_res = accu.template step<bw::FixedInt<1>>();
1853 if (!accu.result()) {
1854 return stdx::unexpected(accu.result().error());
1855 }
1856
1857 return time_field_size_res->value();
1858 }
1860 case field_type::Double:
1861 return 8;
1862 case field_type::Long:
1863 case field_type::Int24:
1864 case field_type::Float:
1865 return 4;
1866 case field_type::Short:
1867 case field_type::Year:
1868 return 2;
1869 case field_type::Tiny:
1870 return 1;
1871 }
1872
1874 }
1875
1876 public:
1879
1880 friend __base;
1881
1883 : __base(caps), v_{std::move(v)} {}
1884
1885 constexpr static uint8_t cmd_byte() noexcept {
1886 return static_cast<uint8_t>(CommandByte::Query);
1887 }
1888
1889 /**
1890 * capabilities the codec depends on.
1891 */
1894 }
1895
1899
1900 namespace bw = borrowable::wire;
1901
1902 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
1903 if (!accu.result()) return stdx::unexpected(accu.result().error());
1904
1905 if (cmd_byte_res->value() != cmd_byte()) {
1907 }
1908
1909 std::vector<typename value_type::Param> params;
1910 if (caps.test(capabilities::pos::query_attributes)) {
1911 //
1912 auto param_count_res = accu.template step<bw::VarInt>();
1913 if (!param_count_res) return stdx::unexpected(param_count_res.error());
1914
1915 // currently always 1.
1916 auto param_set_count_res = accu.template step<bw::VarInt>();
1917 if (!param_set_count_res)
1918 return stdx::unexpected(param_set_count_res.error());
1919
1920 if (param_set_count_res->value() != 1) {
1922 }
1923
1924 const auto param_count = param_count_res->value();
1925 if (param_count > 0) {
1926 // bit-map
1927 const auto nullbits_res = accu.template step<bw::String<Borrowed>>(
1928 bytes_per_bits(param_count));
1929 if (!accu.result()) return stdx::unexpected(accu.result().error());
1930
1931 const auto nullbits = nullbits_res->value();
1932
1933 // always 1
1934 auto new_params_bound_res = accu.template step<bw::FixedInt<1>>();
1935 if (!accu.result()) return stdx::unexpected(accu.result().error());
1936
1937 auto new_params_bound = new_params_bound_res->value();
1938 if (new_params_bound != 1) {
1939 // Always 1, malformed packet error of not 1
1941 }
1942
1943 // redundant, but protocol-docs says:
1944 //
1945 // 'if new-params-bind-flag == 1'
1946 //
1947 // therefore keep it.
1948 if (new_params_bound == 1) {
1949 for (long n{}; n < param_count; ++n) {
1950 auto param_type_res = accu.template step<bw::FixedInt<2>>();
1951 if (!accu.result()) {
1952 return stdx::unexpected(accu.result().error());
1953 }
1954 auto param_name_res = accu.template step<bw::VarString<Borrowed>>();
1955 if (!accu.result()) {
1956 return stdx::unexpected(accu.result().error());
1957 }
1958
1959 params.emplace_back(param_type_res->value(),
1960 param_name_res->value(),
1961 std::optional<std::string>());
1962 }
1963 }
1964
1965 for (long n{}, nullbit_pos{}, nullbyte_pos{}; n < param_count;
1966 ++n, ++nullbit_pos) {
1967 if (nullbit_pos > 7) {
1968 ++nullbyte_pos;
1969 nullbit_pos = 0;
1970 }
1971
1972 if (!(nullbits[nullbyte_pos] & (1 << nullbit_pos))) {
1973 auto &param = params[n];
1974
1975 auto field_size_res =
1976 decode_field_size(accu, param.type_and_flags & 0xff);
1977 if (!field_size_res) {
1978 return stdx::unexpected(field_size_res.error());
1979 }
1980
1981 auto param_value_res = accu.template step<bw::String<Borrowed>>(
1982 field_size_res.value());
1983 if (!accu.result()) {
1984 return stdx::unexpected(accu.result().error());
1985 }
1986
1987 param.value = param_value_res->value();
1988 }
1989 }
1990 }
1991 }
1992
1993 auto statement_res = accu.template step<bw::String<Borrowed>>();
1994
1995 if (!accu.result()) return stdx::unexpected(accu.result().error());
1996
1997 return std::make_pair(
1998 accu.result().value(),
1999 value_type(statement_res->value(), std::move(params)));
2000 }
2001
2002 private:
2004};
2005
2006/**
2007 * codec for client::SendFile message.
2008 *
2009 * sent by client as response to server::SendFileRequest
2010 *
2011 * format:
2012 *
2013 * - String payload
2014 */
2015template <bool Borrowed>
2016class Codec<borrowable::message::client::SendFile<Borrowed>>
2017 : public impl::EncodeBase<
2018 Codec<borrowable::message::client::SendFile<Borrowed>>> {
2019 template <class Accumulator>
2020 constexpr auto accumulate_fields(Accumulator &&accu) const {
2021 namespace bw = borrowable::wire;
2022
2023 return accu.step(bw::String<Borrowed>(v_.payload())).result();
2024 }
2025
2026 public:
2029
2030 friend __base;
2031
2033 : __base(caps), v_{std::move(v)} {}
2034
2035 /**
2036 * capabilities the codec depends on.
2037 */
2039 return {};
2040 }
2041
2045
2046 namespace bw = borrowable::wire;
2047
2048 auto payload_res = accu.template step<bw::String<Borrowed>>();
2049 if (!accu.result()) return stdx::unexpected(accu.result().error());
2050
2051 return std::make_pair(accu.result().value(),
2052 value_type(payload_res->value()));
2053 }
2054
2055 private:
2057};
2058
2059/**
2060 * codec for client's ListFields command.
2061 */
2062template <bool Borrowed>
2063class Codec<borrowable::message::client::ListFields<Borrowed>>
2064 : public impl::EncodeBase<
2065 Codec<borrowable::message::client::ListFields<Borrowed>>> {
2066 template <class Accumulator>
2067 constexpr auto accumulate_fields(Accumulator &&accu) const {
2068 namespace bw = borrowable::wire;
2069
2070 return accu.step(bw::FixedInt<1>(cmd_byte()))
2071 .step(bw::NulTermString<Borrowed>(v_.table_name()))
2072 .step(bw::String<Borrowed>(v_.wildcard()))
2073 .result();
2074 }
2075
2076 public:
2079
2080 friend __base;
2081
2083 : __base(caps), v_{std::move(v)} {}
2084
2085 constexpr static uint8_t cmd_byte() noexcept {
2086 return static_cast<uint8_t>(CommandByte::ListFields);
2087 }
2088
2089 /**
2090 * capabilities the codec depends on.
2091 */
2093 return {};
2094 }
2095
2099
2100 namespace bw = borrowable::wire;
2101
2102 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
2103 if (!accu.result()) return stdx::unexpected(accu.result().error());
2104
2105 if (cmd_byte_res->value() != cmd_byte()) {
2107 }
2108
2109 auto table_name_res = accu.template step<bw::NulTermString<Borrowed>>();
2110 auto wildcard_res = accu.template step<bw::String<Borrowed>>();
2111 if (!accu.result()) return stdx::unexpected(accu.result().error());
2112
2113 return std::make_pair(
2114 accu.result().value(),
2115 value_type(table_name_res->value(), wildcard_res->value()));
2116 }
2117
2118 private:
2120};
2121
2122/**
2123 * codec for client's Reload command.
2124 */
2125template <>
2127 : public impl::EncodeBase<Codec<borrowable::message::client::Reload>> {
2128 template <class Accumulator>
2129 constexpr auto accumulate_fields(Accumulator &&accu) const {
2130 namespace bw = borrowable::wire;
2131
2132 return accu.step(bw::FixedInt<1>(cmd_byte()))
2133 .step(bw::FixedInt<1>(v_.cmds().to_ulong()))
2134 .result();
2135 }
2136
2137 public:
2140
2141 friend __base;
2142
2144 : __base(caps), v_{std::move(v)} {}
2145
2146 constexpr static uint8_t cmd_byte() noexcept {
2147 return static_cast<uint8_t>(CommandByte::Refresh);
2148 }
2149
2150 /**
2151 * capabilities the codec depends on.
2152 */
2154 return {};
2155 }
2156
2160
2161 namespace bw = borrowable::wire;
2162
2163 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
2164 if (!accu.result()) return stdx::unexpected(accu.result().error());
2165
2166 if (cmd_byte_res->value() != cmd_byte()) {
2168 }
2169
2170 auto cmds_res = accu.template step<bw::FixedInt<1>>();
2171 if (!accu.result()) return stdx::unexpected(accu.result().error());
2172
2173 return std::make_pair(accu.result().value(), value_type(cmds_res->value()));
2174 }
2175
2176 private:
2178};
2179
2180/**
2181 * codec for client's Kill command.
2182 *
2183 * format:
2184 *
2185 * - FixedInt<1> == 0x0c, ProcessKill
2186 * - FixedInt<4> id
2187 */
2188template <>
2190 : public impl::EncodeBase<Codec<borrowable::message::client::Kill>> {
2191 template <class Accumulator>
2192 constexpr auto accumulate_fields(Accumulator &&accu) const {
2193 namespace bw = borrowable::wire;
2194
2195 return accu.step(bw::FixedInt<1>(cmd_byte()))
2196 .step(bw::FixedInt<4>(v_.connection_id()))
2197 .result();
2198 }
2199
2200 public:
2203
2204 friend __base;
2205
2207 : __base(caps), v_{std::move(v)} {}
2208
2209 constexpr static uint8_t cmd_byte() noexcept {
2210 return static_cast<uint8_t>(CommandByte::ProcessKill);
2211 }
2212
2213 /**
2214 * capabilities the codec depends on.
2215 */
2217 return {};
2218 }
2219
2223
2224 namespace bw = borrowable::wire;
2225
2226 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
2227 if (!accu.result()) return stdx::unexpected(accu.result().error());
2228
2229 if (cmd_byte_res->value() != cmd_byte()) {
2231 }
2232
2233 auto connection_id_res = accu.template step<bw::FixedInt<4>>();
2234 if (!accu.result()) return stdx::unexpected(accu.result().error());
2235
2236 return std::make_pair(accu.result().value(),
2237 value_type(connection_id_res->value()));
2238 }
2239
2240 private:
2242};
2243
2244/**
2245 * codec for client's Prepared Statement command.
2246 */
2247template <bool Borrowed>
2248class Codec<borrowable::message::client::StmtPrepare<Borrowed>>
2249 : public impl::EncodeBase<
2250 Codec<borrowable::message::client::StmtPrepare<Borrowed>>> {
2251 template <class Accumulator>
2252 constexpr auto accumulate_fields(Accumulator &&accu) const {
2253 namespace bw = borrowable::wire;
2254
2255 return accu.step(bw::FixedInt<1>(cmd_byte()))
2256 .step(bw::String<Borrowed>(v_.statement()))
2257 .result();
2258 }
2259
2260 public:
2263
2264 friend __base;
2265
2267 : __base(caps), v_{std::move(v)} {}
2268
2269 constexpr static uint8_t cmd_byte() noexcept {
2270 return static_cast<uint8_t>(CommandByte::StmtPrepare);
2271 }
2272
2273 /**
2274 * capabilities the codec depends on.
2275 */
2277 return {};
2278 }
2279
2283
2284 namespace bw = borrowable::wire;
2285
2286 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
2287 if (!accu.result()) return stdx::unexpected(accu.result().error());
2288
2289 if (cmd_byte_res->value() != cmd_byte()) {
2291 }
2292
2293 auto statement_res = accu.template step<bw::String<Borrowed>>();
2294 if (!accu.result()) return stdx::unexpected(accu.result().error());
2295
2296 return std::make_pair(accu.result().value(),
2297 value_type(statement_res->value()));
2298 }
2299
2300 private:
2302};
2303
2304/**
2305 * codec for client's Execute Statement command.
2306 */
2307template <bool Borrowed>
2308class Codec<borrowable::message::client::StmtExecute<Borrowed>>
2309 : public impl::EncodeBase<
2310 Codec<borrowable::message::client::StmtExecute<Borrowed>>> {
2311 template <class Accumulator>
2312 auto accumulate_fields(Accumulator &&accu) const {
2313 namespace bw = borrowable::wire;
2314
2315 auto caps = this->caps();
2316
2317 accu.step(bw::FixedInt<1>(cmd_byte()))
2318 .step(bw::FixedInt<4>(v_.statement_id()))
2319 .step(bw::FixedInt<1>(v_.flags().to_ullong()))
2320 .step(bw::FixedInt<4>(v_.iteration_count()));
2321
2322 // num-params from the StmtPrepareOk
2323 auto num_params = v_.values().size();
2324
2325 const bool supports_query_attributes =
2327
2328 if (supports_query_attributes &&
2329 v_.flags().test(cursor::pos::param_count_available)) {
2330 accu.step(bw::VarInt(num_params));
2331 }
2332
2333 if (num_params == 0) return accu.result();
2334
2335 // mark all that are NULL in the nullbits
2336 //
2337 // - one bit per parameter to send
2338 // - if a parameter is NULL, the bit is set, and later no value is added.
2339 uint8_t null_bit_byte{};
2340 int bit_pos{};
2341
2342 for (auto const &param : v_.values()) {
2343 if (!param.has_value()) null_bit_byte |= 1 << bit_pos;
2344
2345 if (++bit_pos > 7) {
2346 accu.step(bw::FixedInt<1>(null_bit_byte));
2347
2348 bit_pos = 0;
2349 null_bit_byte = 0;
2350 }
2351 }
2352
2353 if (bit_pos != 0) accu.step(bw::FixedInt<1>(null_bit_byte));
2354
2355 accu.step(bw::FixedInt<1>(v_.new_params_bound()));
2356
2357 if (v_.new_params_bound()) {
2358 for (const auto &param_def : v_.types()) {
2359 accu.step(bw::FixedInt<2>(param_def.type_and_flags));
2360
2361 if (supports_query_attributes) {
2362 accu.step(borrowed::wire::VarString(param_def.name));
2363 }
2364 }
2365 }
2366
2367 for (auto [n, v] : stdx::views::enumerate(v_.values())) {
2368 // add all the values that aren't NULL
2369 if (!v.has_value()) continue;
2370
2371 // write length of the type is a variable length
2372 switch (v_.types()[n].type_and_flags & 0xff) {
2373 case field_type::Bit:
2374 case field_type::Blob:
2377 case field_type::Set:
2378 case field_type::String:
2379 case field_type::Enum:
2386 accu.step(bw::VarInt(v->size()));
2387 break;
2388 case field_type::Date:
2391 case field_type::Time:
2392 accu.step(bw::FixedInt<1>(v->size()));
2393 break;
2395 case field_type::Double:
2396 case field_type::Long:
2397 case field_type::Int24:
2398 case field_type::Float:
2399 case field_type::Short:
2400 case field_type::Year:
2401 case field_type::Tiny:
2402 // fixed size
2403 break;
2404 default:
2405 assert(false || "Unknown Type");
2406 }
2407 accu.step(borrowed::wire::String(v.value()));
2408 }
2409
2410 return accu.result();
2411 }
2412
2413 public:
2416
2417 friend __base;
2418
2420 : __base(caps), v_{std::move(val)} {}
2421
2422 constexpr static uint8_t cmd_byte() noexcept {
2423 return static_cast<uint8_t>(CommandByte::StmtExecute);
2424 }
2425
2426 /**
2427 * capabilities the codec depends on.
2428 */
2431 }
2432
2433 /**
2434 * decode a buffer into a message::client::StmtExecute.
2435 *
2436 * @param buffer a buffer
2437 * @param caps protocol capabilities
2438 * @param metadata_lookup callable that expects a 'uint32_t statement_id'
2439 * that returns a result that's convertible to
2440 * 'stdx::expected<std::vector<ParamDef>, std::error_code>' representing the
2441 * parameter-definitions of the prepared statement
2442 *
2443 * decoding a StmtExecute message requires the parameter-definitions of the
2444 * prepared statement. The metadata_lookup function may be called to get
2445 * the parameter-definitions for the statement-id.
2446 *
2447 * The function may return a parameter-definitions directly
2448 *
2449 * \code
2450 * StmtExecute::decode(
2451 * buffers,
2452 * capabilities::protocol_41,
2453 * [](uint32_t stmt_id) { return std::vector<ParamDef>{}; });
2454 * \endcode
2455 *
2456 * ... or a stdx::expected<std::vector<ParamDef>, std::error_code> if it wants
2457 * to signal that a statement-id wasn't found
2458 *
2459 * \code
2460 * StmtExecute::decode(
2461 * buffers,
2462 * capabilities::protocol_41,
2463 * [](uint32_t stmt_id) ->
2464 * stdx::expected<std::vector<ParamDef>, std::error_code> {
2465 * bool found{true};
2466 *
2467 * if (found) {
2468 * return {};
2469 * } else {
2470 * return stdx::unexpected(make_error_code(
2471 * codec_errc::statement_id_not_found));
2472 * }
2473 * });
2474 * \endcode
2475 */
2476 template <class Func>
2479 Func &&metadata_lookup) {
2481
2482 namespace bw = borrowable::wire;
2483
2484 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
2485 if (!accu.result()) return stdx::unexpected(accu.result().error());
2486
2487 if (cmd_byte_res->value() != cmd_byte()) {
2489 }
2490
2491 auto statement_id_res = accu.template step<bw::FixedInt<4>>();
2492 auto flags_res = accu.template step<bw::FixedInt<1>>();
2493 auto iteration_count_res = accu.template step<bw::FixedInt<4>>();
2494
2495 if (!accu.result()) return stdx::unexpected(accu.result().error());
2496
2498
2499 const bool supports_query_attributes =
2501
2503 metadata_res = metadata_lookup(statement_id_res->value());
2504 if (!metadata_res) {
2505 return stdx::unexpected(
2507 }
2508
2509 size_t param_count = metadata_res->size();
2510
2511 if (supports_query_attributes &&
2512 (flags_res->value() & param_count_available) != 0) {
2513 auto param_count_res = accu.template step<bw::VarInt>();
2514 if (!accu.result()) {
2515 return stdx::unexpected(accu.result().error());
2516 }
2517
2518 if (static_cast<uint64_t>(param_count_res->value()) < param_count) {
2519 // can the param-count shrink?
2521 }
2522
2523 param_count = param_count_res->value();
2524 }
2525
2526 if (param_count == 0) {
2527 return std::make_pair(
2528 accu.result().value(),
2529 value_type(statement_id_res->value(), flags_res->value(),
2530 iteration_count_res->value(), false, {}, {}));
2531 }
2532
2533 auto nullbits_res =
2534 accu.template step<bw::String<Borrowed>>(bytes_per_bits(param_count));
2535 if (!accu.result()) return stdx::unexpected(accu.result().error());
2536
2537 auto new_params_bound_res = accu.template step<bw::FixedInt<1>>();
2538 if (!accu.result()) return stdx::unexpected(accu.result().error());
2539
2540 std::vector<typename value_type::ParamDef> types;
2541
2542 auto new_params_bound = new_params_bound_res->value();
2543 if (new_params_bound == 0) {
2544 // no new params, use the last known params.
2545 types = *metadata_res;
2546 } else if (new_params_bound == 1) {
2547 // check that there is at least enough data for the types (a FixedInt<2>)
2548 // before reserving memory.
2549 if (param_count >= buffer.size() / 2) {
2551 }
2552
2553 types.reserve(param_count);
2554
2555 for (size_t n{}; n < param_count; ++n) {
2556 auto type_res = accu.template step<bw::FixedInt<2>>();
2557 if (!accu.result()) return stdx::unexpected(accu.result().error());
2558
2559 if (supports_query_attributes) {
2560 auto name_res = accu.template step<bw::VarString<Borrowed>>();
2561 if (!accu.result()) {
2562 return stdx::unexpected(accu.result().error());
2563 }
2564 types.emplace_back(type_res->value(), name_res->value());
2565 } else {
2566 types.emplace_back(type_res->value(), "");
2567 }
2568 }
2569 } else {
2571 }
2572
2573 if (param_count != types.size()) {
2574 // param-count and available types doesn't match.
2576 }
2577
2578 std::vector<std::optional<typename value_type::string_type>> values;
2579 values.reserve(param_count);
2580
2581 const auto nullbits = nullbits_res->value();
2582 for (size_t n{}, bit_pos{}, byte_pos{}; n < param_count; ++n, ++bit_pos) {
2583 if (bit_pos > 7) {
2584 bit_pos = 0;
2585 ++byte_pos;
2586 }
2587
2588 // if the data was sent via COM_STMT_SEND_LONG_DATA, there will be no data
2589 // for
2590 const auto param_already_sent =
2591 n < metadata_res->size() ? (*metadata_res)[n].param_already_sent
2592 : false;
2593
2594 if (param_already_sent) {
2595 values.emplace_back(""); // empty
2596 } else if (!(nullbits[byte_pos] & (1 << bit_pos))) {
2598 stdx::unexpected(make_error_code(std::errc::invalid_argument)));
2599 switch (types[n].type_and_flags & 0xff) {
2600 case field_type::Bit:
2601 case field_type::Blob:
2604 case field_type::Set:
2605 case field_type::String:
2606 case field_type::Enum:
2612 case field_type::Geometry: {
2613 auto string_field_size_res = accu.template step<bw::VarInt>();
2614 if (!accu.result()) {
2615 return stdx::unexpected(accu.result().error());
2616 }
2617
2618 field_size_res = string_field_size_res->value();
2619 } break;
2620 case field_type::Date:
2623 case field_type::Time: {
2624 auto time_field_size_res = accu.template step<bw::FixedInt<1>>();
2625 if (!accu.result()) {
2626 return stdx::unexpected(accu.result().error());
2627 }
2628
2629 field_size_res = time_field_size_res->value();
2630 } break;
2632 case field_type::Double:
2633 field_size_res = 8;
2634 break;
2635 case field_type::Long:
2636 case field_type::Int24:
2637 case field_type::Float:
2638 field_size_res = 4;
2639 break;
2640 case field_type::Short:
2641 case field_type::Year:
2642 field_size_res = 2;
2643 break;
2644 case field_type::Tiny:
2645 field_size_res = 1;
2646 break;
2647 }
2648
2649 if (!field_size_res) {
2650 return stdx::unexpected(
2652 }
2653
2654 auto value_res =
2655 accu.template step<bw::String<Borrowed>>(field_size_res.value());
2656 if (!accu.result()) {
2657 return stdx::unexpected(accu.result().error());
2658 }
2659
2660 values.push_back(value_res->value());
2661 } else {
2662 // NULL
2663 values.emplace_back(std::nullopt);
2664 }
2665 }
2666
2667 if (!accu.result()) return stdx::unexpected(accu.result().error());
2668
2669 return std::make_pair(
2670 accu.result().value(),
2671 value_type(statement_id_res->value(), flags_res->value(),
2672 iteration_count_res->value(), new_params_bound_res->value(),
2673 types, values));
2674 }
2675
2676 private:
2678};
2679
2680/**
2681 * codec for client's append data Statement command.
2682 */
2683template <bool Borrowed>
2685 : public impl::EncodeBase<
2686 Codec<borrowable::message::client::StmtParamAppendData<Borrowed>>> {
2687 template <class Accumulator>
2688 constexpr auto accumulate_fields(Accumulator &&accu) const {
2689 namespace bw = borrowable::wire;
2690
2691 return accu.step(bw::FixedInt<1>(cmd_byte()))
2692 .step(bw::FixedInt<4>(v_.statement_id()))
2693 .step(bw::FixedInt<2>(v_.param_id()))
2694 .step(bw::String<Borrowed>(v_.data()))
2695 .result();
2696 }
2697
2698 public:
2701
2702 friend __base;
2703
2705 : __base(caps), v_{std::move(v)} {}
2706
2707 constexpr static uint8_t cmd_byte() noexcept {
2708 return static_cast<uint8_t>(CommandByte::StmtSendLongData);
2709 }
2710
2711 /**
2712 * capabilities the codec depends on.
2713 */
2715 return {};
2716 }
2717
2721
2722 namespace bw = borrowable::wire;
2723
2724 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
2725 if (!accu.result()) return stdx::unexpected(accu.result().error());
2726
2727 if (cmd_byte_res->value() != cmd_byte()) {
2729 }
2730
2731 auto statement_id_res = accu.template step<bw::FixedInt<4>>();
2732 auto param_id_res = accu.template step<bw::FixedInt<2>>();
2733 auto data_res = accu.template step<bw::String<Borrowed>>();
2734 if (!accu.result()) return stdx::unexpected(accu.result().error());
2735
2736 return std::make_pair(accu.result().value(),
2737 value_type(statement_id_res->value(),
2738 param_id_res->value(), data_res->value()));
2739 }
2740
2741 private:
2743};
2744
2745/**
2746 * codec for client's Close Statement command.
2747 */
2748template <>
2750 : public impl::EncodeBase<Codec<borrowable::message::client::StmtClose>> {
2751 template <class Accumulator>
2752 constexpr auto accumulate_fields(Accumulator &&accu) const {
2753 namespace bw = borrowable::wire;
2754
2755 return accu.step(bw::FixedInt<1>(cmd_byte()))
2756 .step(bw::FixedInt<4>(v_.statement_id()))
2757 .result();
2758 }
2759
2760 public:
2763
2764 friend __base;
2765
2767 : __base(caps), v_{std::move(v)} {}
2768
2769 constexpr static uint8_t cmd_byte() noexcept {
2770 return static_cast<uint8_t>(CommandByte::StmtClose);
2771 }
2772
2773 /**
2774 * capabilities the codec depends on.
2775 */
2777 return {};
2778 }
2779
2783
2784 namespace bw = borrowable::wire;
2785
2786 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
2787 if (!accu.result()) return stdx::unexpected(accu.result().error());
2788
2789 if (cmd_byte_res->value() != cmd_byte()) {
2791 }
2792
2793 auto statement_id_res = accu.template step<bw::FixedInt<4>>();
2794 if (!accu.result()) return stdx::unexpected(accu.result().error());
2795
2796 return std::make_pair(accu.result().value(),
2797 value_type(statement_id_res->value()));
2798 }
2799
2800 private:
2802};
2803
2804/**
2805 * codec for client's Reset Statement command.
2806 */
2807template <>
2809 : public impl::EncodeBase<Codec<borrowable::message::client::StmtReset>> {
2810 template <class Accumulator>
2811 constexpr auto accumulate_fields(Accumulator &&accu) const {
2812 namespace bw = borrowable::wire;
2813
2814 return accu.step(bw::FixedInt<1>(cmd_byte()))
2815 .step(bw::FixedInt<4>(v_.statement_id()))
2816 .result();
2817 }
2818
2819 public:
2822
2823 friend __base;
2824
2826 : __base(caps), v_{std::move(v)} {}
2827
2828 constexpr static uint8_t cmd_byte() noexcept {
2829 return static_cast<uint8_t>(CommandByte::StmtReset);
2830 }
2831
2832 /**
2833 * capabilities the codec depends on.
2834 */
2836 return {};
2837 }
2838
2842
2843 namespace bw = borrowable::wire;
2844
2845 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
2846 if (!accu.result()) return stdx::unexpected(accu.result().error());
2847
2848 if (cmd_byte_res->value() != cmd_byte()) {
2850 }
2851
2852 auto statement_id_res = accu.template step<bw::FixedInt<4>>();
2853 if (!accu.result()) return stdx::unexpected(accu.result().error());
2854
2855 return std::make_pair(accu.result().value(),
2856 value_type(statement_id_res->value()));
2857 }
2858
2859 private:
2861};
2862
2863/**
2864 * codec for client's SetOption command.
2865 */
2866template <>
2868 : public impl::EncodeBase<Codec<borrowable::message::client::SetOption>> {
2869 template <class Accumulator>
2870 constexpr auto accumulate_fields(Accumulator &&accu) const {
2871 namespace bw = borrowable::wire;
2872
2873 return accu.step(bw::FixedInt<1>(cmd_byte()))
2874 .step(bw::FixedInt<2>(v_.option()))
2875 .result();
2876 }
2877
2878 public:
2881
2882 friend __base;
2883
2885 : __base(caps), v_{std::move(v)} {}
2886
2887 constexpr static uint8_t cmd_byte() noexcept {
2888 return static_cast<uint8_t>(CommandByte::SetOption);
2889 }
2890
2891 /**
2892 * capabilities the codec depends on.
2893 */
2895 return {};
2896 }
2897
2901
2902 namespace bw = borrowable::wire;
2903
2904 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
2905 if (!accu.result()) return stdx::unexpected(accu.result().error());
2906
2907 if (cmd_byte_res->value() != cmd_byte()) {
2909 }
2910
2911 auto option_res = accu.template step<bw::FixedInt<2>>();
2912 if (!accu.result()) return stdx::unexpected(accu.result().error());
2913
2914 return std::make_pair(accu.result().value(),
2915 value_type(option_res->value()));
2916 }
2917
2918 private:
2920};
2921
2922/**
2923 * codec for client's Fetch Cursor command.
2924 */
2925template <>
2927 : public impl::EncodeBase<Codec<borrowable::message::client::StmtFetch>> {
2928 template <class Accumulator>
2929 constexpr auto accumulate_fields(Accumulator &&accu) const {
2930 namespace bw = borrowable::wire;
2931
2932 return accu.step(bw::FixedInt<1>(cmd_byte()))
2933 .step(bw::FixedInt<4>(v_.statement_id()))
2934 .step(bw::FixedInt<4>(v_.row_count()))
2935 .result();
2936 }
2937
2938 public:
2941
2942 friend __base;
2943
2945 : __base(caps), v_{std::move(v)} {}
2946
2947 constexpr static uint8_t cmd_byte() noexcept {
2948 return static_cast<uint8_t>(CommandByte::StmtFetch);
2949 }
2950
2951 /**
2952 * capabilities the codec depends on.
2953 */
2955 return {};
2956 }
2957
2961
2962 namespace bw = borrowable::wire;
2963
2964 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
2965 if (!accu.result()) return stdx::unexpected(accu.result().error());
2966
2967 if (cmd_byte_res->value() != cmd_byte()) {
2969 }
2970
2971 auto statement_id_res = accu.template step<bw::FixedInt<4>>();
2972 auto row_count_res = accu.template step<bw::FixedInt<4>>();
2973 if (!accu.result()) return stdx::unexpected(accu.result().error());
2974
2975 return std::make_pair(
2976 accu.result().value(),
2977 value_type(statement_id_res->value(), row_count_res->value()));
2978 }
2979
2980 private:
2982};
2983
2984/**
2985 * codec for client side greeting message.
2986 *
2987 *
2988 * in 3.21 ... 4.0:
2989 *
2990 * FixedInt<2> capabilities [protocol_41 not set]
2991 * FixedInt<3> max-allowed-packet
2992 * NulTermString username
2993 * NulTermString auth-method-data
2994 *
2995 * [if not connect_with_schema, there may be no trailing Nul-byte]
2996 *
2997 * if connect_with_schema {
2998 * String schema
2999 * }
3000 *
3001 * the auth-method is "old_password" if "protocol_version == 10 &&
3002 * (capabilities & long_password)", it is "older_password" otherwise
3003 *
3004 * FixedInt<2> capabilities_lo [protocol_41 set]
3005 * FixedInt<2> capabilities_hi
3006 * FixedInt<4> max_allowed-packet
3007 * ...
3008 *
3009 * The capabilities that are part of the message are the client's capabilities
3010 * (which may announce more than what the server supports). The codec
3011 * uses the capabilities that are shared between client and server to decide
3012 * which parts and how they are understood, though.
3013 *
3014 * checked capabilities:
3015 * - protocol_41
3016 * - ssl
3017 * - client_auth_method_data_varint
3018 * - secure_connection
3019 * - connect_with_schema
3020 * - plugin_auth
3021 * - connect_attributes
3022 */
3023template <bool Borrowed>
3024class Codec<borrowable::message::client::Greeting<Borrowed>>
3025 : public impl::EncodeBase<
3026 Codec<borrowable::message::client::Greeting<Borrowed>>> {
3027 template <class Accumulator>
3028 constexpr auto accumulate_fields(Accumulator &&accu) const {
3029 namespace bw = borrowable::wire;
3030
3031 const auto shared_caps = v_.capabilities() & this->caps();
3032
3034 accu.step(bw::FixedInt<4>(v_.capabilities().to_ulong()))
3035 .step(bw::FixedInt<4>(v_.max_packet_size()))
3036 .step(bw::FixedInt<1>(v_.collation()))
3037 .step(bw::String<Borrowed>(std::string(23, '\0')));
3038 if (!(shared_caps[classic_protocol::capabilities::pos::ssl] &&
3039 v_.username().empty())) {
3040 // the username is empty and SSL is set, this is a short SSL-greeting
3041 // packet
3042 accu.step(bw::NulTermString<Borrowed>(v_.username()));
3043
3044 if (shared_caps[classic_protocol::capabilities::pos::
3046 accu.step(bw::VarString<Borrowed>(v_.auth_method_data()));
3047 } else if (shared_caps[classic_protocol::capabilities::pos::
3049 accu.step(bw::FixedInt<1>(v_.auth_method_data().size()))
3050 .step(bw::String<Borrowed>(v_.auth_method_data()));
3051 } else {
3052 accu.step(bw::NulTermString<Borrowed>(v_.auth_method_data()));
3053 }
3054
3055 if (shared_caps
3057 accu.step(bw::NulTermString<Borrowed>(v_.schema()));
3058 }
3059
3060 if (!shared_caps
3062 // special handling for off-spec client/server implementations.
3063 //
3064 // 1. older clients may set ::plugin_auth, but
3065 // ::connection_attributes which means nothing follows the
3066 // "auth-method-name" field
3067 // 2. auth-method-name is empty, it MAY be skipped.
3069 !v_.auth_method_name().empty()) {
3070 accu.step(bw::NulTermString<Borrowed>(v_.auth_method_name()));
3071 }
3072 } else {
3074 accu.step(bw::NulTermString<Borrowed>(v_.auth_method_name()));
3075 }
3076
3077 accu.step(bw::VarString<Borrowed>(v_.attributes()));
3078 }
3079 }
3080 } else {
3081 accu.step(bw::FixedInt<2>(v_.capabilities().to_ulong()))
3082 .step(bw::FixedInt<3>(v_.max_packet_size()))
3083 .step(bw::NulTermString<Borrowed>(v_.username()));
3084 if (shared_caps
3086 accu.step(bw::NulTermString<Borrowed>(v_.auth_method_data()))
3087 .step(bw::String<Borrowed>(v_.schema()));
3088 } else {
3089 accu.step(bw::String<Borrowed>(v_.auth_method_data()));
3090 }
3091 }
3092
3093 return accu.result();
3094 }
3095
3096 public:
3099
3100 friend __base;
3101
3103 : __base(caps), v_{std::move(v)} {}
3104
3105 /**
3106 * capabilities the codec depends on.
3107 */
3112 }
3113
3117
3118 namespace bw = borrowable::wire;
3119
3120 auto capabilities_lo_res = accu.template step<bw::FixedInt<2>>();
3121 if (!capabilities_lo_res)
3122 return stdx::unexpected(capabilities_lo_res.error());
3123
3124 auto client_capabilities = classic_protocol::capabilities::value_type(
3125 capabilities_lo_res->value());
3126
3127 // decoding depends on the capabilities that both client and server have
3128 // in common
3129 auto shared_capabilities = caps & client_capabilities;
3130
3131 if (shared_capabilities[classic_protocol::capabilities::pos::protocol_41]) {
3132 // if protocol_41 is set in the capabilities, we expected 2 more bytes
3133 // of capabilities
3134 auto capabilities_hi_res = accu.template step<bw::FixedInt<2>>();
3135 if (!capabilities_hi_res)
3136 return stdx::unexpected(capabilities_hi_res.error());
3137
3138 client_capabilities |= classic_protocol::capabilities::value_type(
3139 capabilities_hi_res->value() << 16);
3140
3141 shared_capabilities = caps & client_capabilities;
3142
3143 auto max_packet_size_res = accu.template step<bw::FixedInt<4>>();
3144 auto collation_res = accu.template step<bw::FixedInt<1>>();
3145
3146 accu.template step<bw::String<Borrowed>>(23); // skip 23 bytes
3147
3148 auto last_accu_res = accu.result();
3149
3150 auto username_res = accu.template step<bw::NulTermString<Borrowed>>();
3151 if (!accu.result()) {
3152 // if there isn't enough data for the nul-term-string, but we had the
3153 // 23-bytes ...
3154 if (last_accu_res &&
3155 shared_capabilities[classic_protocol::capabilities::pos::ssl]) {
3156 return std::make_pair(
3157 last_accu_res.value(),
3158 value_type(client_capabilities, max_packet_size_res->value(),
3159 collation_res->value(), {}, {}, {}, {}, {}));
3160 }
3161
3162 return stdx::unexpected(accu.result().error());
3163 }
3164
3165 // auth-method-data is either
3166 //
3167 // - varint length
3168 // - fixed-int-1 length
3169 // - null-term-string
3170 stdx::expected<bw::String<Borrowed>, std::error_code>
3171 auth_method_data_res;
3172 if (shared_capabilities[classic_protocol::capabilities::pos::
3174 auto res = accu.template step<bw::VarString<Borrowed>>();
3175 if (!res) return stdx::unexpected(res.error());
3176
3177 auth_method_data_res = bw::String<Borrowed>(res->value());
3178 } else if (shared_capabilities
3180 auto auth_method_data_len_res = accu.template step<bw::FixedInt<1>>();
3181 if (!auth_method_data_len_res)
3182 return stdx::unexpected(auth_method_data_len_res.error());
3183 auto auth_method_data_len = auth_method_data_len_res->value();
3184
3185 auto res =
3186 accu.template step<bw::String<Borrowed>>(auth_method_data_len);
3187 if (!res) return stdx::unexpected(res.error());
3188
3189 auth_method_data_res = bw::String<Borrowed>(res->value());
3190 } else {
3191 auto res = accu.template step<bw::NulTermString<Borrowed>>();
3192 if (!res) return stdx::unexpected(res.error());
3193
3194 auth_method_data_res = bw::String<Borrowed>(res->value());
3195 }
3196
3197 stdx::expected<bw::NulTermString<Borrowed>, std::error_code> schema_res;
3198 if (shared_capabilities
3200 schema_res = accu.template step<bw::NulTermString<Borrowed>>();
3201 }
3202 if (!schema_res) return stdx::unexpected(schema_res.error());
3203
3205 auth_method_res;
3206 if (shared_capabilities
3208 if (net::buffer_size(buffer) == accu.result().value()) {
3209 // even with plugin_auth set, the server is fine, if no
3210 // auth_method_name is sent.
3211 auth_method_res = bw::NulTermString<Borrowed>{};
3212 } else {
3213 auth_method_res = accu.template step<bw::NulTermString<Borrowed>>();
3214 }
3215 }
3216 if (!auth_method_res) return stdx::unexpected(auth_method_res.error());
3217
3218 stdx::expected<bw::VarString<Borrowed>, std::error_code> attributes_res;
3219 if (shared_capabilities
3221 attributes_res = accu.template step<bw::VarString<Borrowed>>();
3222 }
3223
3224 if (!accu.result()) return stdx::unexpected(accu.result().error());
3225
3226 return std::make_pair(
3227 accu.result().value(),
3228 value_type(client_capabilities, max_packet_size_res->value(),
3229 collation_res->value(), username_res->value(),
3230 auth_method_data_res->value(), schema_res->value(),
3231 auth_method_res->value(), attributes_res->value()));
3232
3233 } else {
3234 auto max_packet_size_res = accu.template step<bw::FixedInt<3>>();
3235
3236 auto username_res = accu.template step<bw::NulTermString<Borrowed>>();
3237
3238 stdx::expected<bw::String<Borrowed>, std::error_code>
3239 auth_method_data_res;
3240 stdx::expected<bw::String<Borrowed>, std::error_code> schema_res;
3241
3242 if (shared_capabilities
3244 auto res = accu.template step<bw::NulTermString<Borrowed>>();
3245 if (!res) return stdx::unexpected(res.error());
3246
3247 // auth_method_data is a wire::String, move it over
3248 auth_method_data_res = bw::String<Borrowed>(res->value());
3249
3250 schema_res = accu.template step<bw::String<Borrowed>>();
3251 } else {
3252 auth_method_data_res = accu.template step<bw::String<Borrowed>>();
3253 }
3254
3255 if (!accu.result()) return stdx::unexpected(accu.result().error());
3256
3257 // idea: benchmark in-place constructor where all parameters are passed
3258 // down to the lowest level.
3259 //
3260 // It should involve less copy-construction.
3261 //
3262 // - stdx::in_place is for in-place construction of stdx::expected's
3263 // value
3264 // - std::piecewise_construct for the parts of the std::pair that is
3265 // returned as value of stdx::expected
3266 //
3267 // return {stdx::in_place, std::piecewise_construct,
3268 // std::forward_as_tuple(accu.result().value()),
3269 // std::forward_as_tuple(capabilities,
3270 // max_packet_size_res->value(),
3271 // 0x00, username_res->value(),
3272 // auth_method_data_res->value(),
3273 // schema_res->value(), {},
3274 // {})};
3275 return std::make_pair(
3276 accu.result().value(),
3277 value_type(client_capabilities, max_packet_size_res->value(), 0x00,
3278 username_res->value(), auth_method_data_res->value(),
3279 schema_res->value(), {}, {}));
3280 }
3281 }
3282
3283 private:
3285};
3286
3287/**
3288 * codec for client::AuthMethodData message.
3289 *
3290 * format:
3291 *
3292 * - String auth_method_data
3293 *
3294 * sent after server::AuthMethodData or server::AuthMethodContinue
3295 */
3296template <bool Borrowed>
3297class Codec<borrowable::message::client::AuthMethodData<Borrowed>>
3298 : public impl::EncodeBase<
3299 Codec<borrowable::message::client::AuthMethodData<Borrowed>>> {
3300 template <class Accumulator>
3301 constexpr auto accumulate_fields(Accumulator &&accu) const {
3302 namespace bw = borrowable::wire;
3303
3304 return accu.step(bw::String<Borrowed>(v_.auth_method_data())).result();
3305 }
3306
3307 public:
3310
3311 friend __base;
3312
3314 : __base(caps), v_{std::move(v)} {}
3315
3316 /**
3317 * capabilities the codec depends on.
3318 */
3320 return {};
3321 }
3322
3326
3327 namespace bw = borrowable::wire;
3328
3329 auto auth_method_data_res = accu.template step<bw::String<Borrowed>>();
3330
3331 if (!accu.result()) return stdx::unexpected(accu.result().error());
3332
3333 return std::make_pair(accu.result().value(),
3334 value_type(auth_method_data_res->value()));
3335 }
3336
3337 private:
3339};
3340
3341/**
3342 * codec for client side change-user message.
3343 *
3344 * checked capabilities:
3345 * - protocol_41
3346 * - secure_connection
3347 * - plugin_auth
3348 * - connect_attributes
3349 */
3350template <bool Borrowed>
3351class Codec<borrowable::message::client::ChangeUser<Borrowed>>
3352 : public impl::EncodeBase<
3353 Codec<borrowable::message::client::ChangeUser<Borrowed>>> {
3354 template <class Accumulator>
3355 constexpr auto accumulate_fields(Accumulator &&accu) const {
3356 namespace bw = borrowable::wire;
3357
3358 accu.step(bw::FixedInt<1>(cmd_byte()))
3359 .step(bw::NulTermString<Borrowed>(v_.username()));
3360
3362 accu.step(bw::FixedInt<1>(v_.auth_method_data().size()))
3363 .step(bw::String<Borrowed>(v_.auth_method_data()));
3364 } else {
3365 accu.step(bw::NulTermString<Borrowed>(v_.auth_method_data()));
3366 }
3367 accu.step(bw::NulTermString<Borrowed>(v_.schema()));
3368
3369 // 4.1 and later have a collation
3370 //
3371 // this could be checked via the protocol_41 capability, but that's not
3372 // what the server does
3373 if (v_.collation() != 0x00 ||
3376 accu.step(bw::FixedInt<2>(v_.collation()));
3378 accu.step(bw::NulTermString<Borrowed>(v_.auth_method_name()));
3379 }
3380
3381 if (this->caps()
3383 accu.step(bw::VarString<Borrowed>(v_.attributes()));
3384 }
3385 }
3386
3387 return accu.result();
3388 }
3389
3390 public:
3393
3394 friend __base;
3395
3397 : __base(caps), v_{std::move(v)} {}
3398
3399 constexpr static uint8_t cmd_byte() noexcept {
3400 return static_cast<uint8_t>(CommandByte::ChangeUser);
3401 }
3402
3403 /**
3404 * capabilities the codec depends on.
3405 */
3409 }
3410
3414
3415 namespace bw = borrowable::wire;
3416
3417 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
3418 if (!accu.result()) return stdx::unexpected(accu.result().error());
3419
3420 if (cmd_byte_res->value() != cmd_byte()) {
3422 }
3423 auto username_res = accu.template step<bw::NulTermString<Borrowed>>();
3424
3425 // auth-method-data is either
3426 //
3427 // - fixed-int-1 length
3428 // - null-term-string
3429 stdx::expected<bw::String<Borrowed>, std::error_code> auth_method_data_res;
3431 auto auth_method_data_len_res = accu.template step<bw::FixedInt<1>>();
3432 if (!auth_method_data_len_res)
3433 return stdx::unexpected(auth_method_data_len_res.error());
3434 auto auth_method_data_len = auth_method_data_len_res->value();
3435
3436 auto res = accu.template step<bw::String<Borrowed>>(auth_method_data_len);
3437 if (!res) return stdx::unexpected(res.error());
3438
3439 auth_method_data_res = bw::String<Borrowed>(res->value());
3440 } else {
3441 auto res = accu.template step<bw::NulTermString<Borrowed>>();
3442 if (!res) return stdx::unexpected(res.error());
3443
3444 auth_method_data_res = bw::String<Borrowed>(res->value());
3445 }
3446
3447 auto schema_res = accu.template step<bw::NulTermString<Borrowed>>();
3448
3449 if (!accu.result()) return stdx::unexpected(accu.result().error());
3450
3451 // 3.23.x-4.0 don't send more.
3452 if (buffer_size(buffer) <= accu.result().value()) {
3453 return std::make_pair(
3454 accu.result().value(),
3455 value_type(username_res->value(), auth_method_data_res->value(),
3456 schema_res->value(), 0x00, {}, {}));
3457 }
3458
3459 // added in 4.1
3460 auto collation_res = accu.template step<bw::FixedInt<2>>();
3461
3463 auth_method_name_res;
3465 auth_method_name_res = accu.template step<bw::NulTermString<Borrowed>>();
3466 }
3467
3468 stdx::expected<bw::VarString<Borrowed>, std::error_code> attributes_res;
3470 attributes_res = accu.template step<bw::VarString<Borrowed>>();
3471 }
3472
3473 if (!accu.result()) return stdx::unexpected(accu.result().error());
3474
3475 return std::make_pair(
3476 accu.result().value(),
3477 value_type(username_res->value(), auth_method_data_res->value(),
3478 schema_res->value(), collation_res->value(),
3479 auth_method_name_res->value(), attributes_res->value()));
3480 }
3481
3482 private:
3484};
3485
3486/**
3487 * codec for client's Clone command.
3488 *
3489 * response: server::Ok or server::Error
3490 */
3491template <>
3493 : public CodecSimpleCommand<Codec<borrowable::message::client::Clone>,
3494 borrowable::message::client::Clone> {
3495 public:
3498
3500
3501 constexpr static uint8_t cmd_byte() noexcept {
3502 return static_cast<uint8_t>(CommandByte::Clone);
3503 }
3504
3505 /**
3506 * capabilities the codec depends on.
3507 */
3509 return {};
3510 }
3511};
3512
3513/**
3514 * codec for client side dump-binlog message.
3515 */
3516template <bool Borrowed>
3517class Codec<borrowable::message::client::BinlogDump<Borrowed>>
3518 : public impl::EncodeBase<
3519 Codec<borrowable::message::client::BinlogDump<Borrowed>>> {
3520 public:
3522
3523 private:
3524 template <class Accumulator>
3525 constexpr auto accumulate_fields(Accumulator &&accu) const {
3526 namespace bw = borrowable::wire;
3527
3528 return accu.step(bw::FixedInt<1>(cmd_byte()))
3529 .step(bw::FixedInt<4>(v_.position()))
3530 .step(bw::FixedInt<2>(v_.flags().underlying_value()))
3531 .step(bw::FixedInt<4>(v_.server_id()))
3532 .step(bw::String<Borrowed>(v_.filename()))
3533 .result();
3534 }
3535
3536 public:
3538
3539 friend __base;
3540
3542 : __base(caps), v_{std::move(v)} {}
3543
3544 constexpr static uint8_t cmd_byte() noexcept {
3545 return static_cast<uint8_t>(CommandByte::BinlogDump);
3546 }
3547
3548 /**
3549 * capabilities the codec depends on.
3550 */
3552 return {};
3553 }
3554
3558
3559 namespace bw = borrowable::wire;
3560
3561 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
3562 if (!accu.result()) return stdx::unexpected(accu.result().error());
3563
3564 if (cmd_byte_res->value() != cmd_byte()) {
3566 }
3567 auto position_res = accu.template step<bw::FixedInt<4>>();
3568 auto flags_res = accu.template step<bw::FixedInt<2>>();
3569 auto server_id_res = accu.template step<bw::FixedInt<4>>();
3570
3571 auto filename_res = accu.template step<bw::String<Borrowed>>();
3572
3573 if (!accu.result()) return stdx::unexpected(accu.result().error());
3574
3576 flags.underlying_value(flags_res->value());
3577
3578 return std::make_pair(
3579 accu.result().value(),
3580 value_type(flags, server_id_res->value(), filename_res->value(),
3581 position_res->value()));
3582 }
3583
3584 private:
3586};
3587
3588/**
3589 * codec for client side register-replica message.
3590 */
3591template <bool Borrowed>
3592class Codec<borrowable::message::client::RegisterReplica<Borrowed>>
3593 : public impl::EncodeBase<
3594 Codec<borrowable::message::client::RegisterReplica<Borrowed>>> {
3595 public:
3597
3598 private:
3599 template <class Accumulator>
3600 constexpr auto accumulate_fields(Accumulator &&accu) const {
3601 namespace bw = borrowable::wire;
3602
3603 return accu.step(bw::FixedInt<1>(cmd_byte()))
3604 .step(bw::FixedInt<4>(v_.server_id()))
3605 .step(bw::FixedInt<1>(v_.hostname().size()))
3606 .step(bw::String<Borrowed>(v_.hostname()))
3607 .step(bw::FixedInt<1>(v_.username().size()))
3608 .step(bw::String<Borrowed>(v_.username()))
3609 .step(bw::FixedInt<1>(v_.password().size()))
3610 .step(bw::String<Borrowed>(v_.password()))
3611 .step(bw::FixedInt<2>(v_.port()))
3612 .step(bw::FixedInt<4>(v_.replication_rank()))
3613 .step(bw::FixedInt<4>(v_.master_id()))
3614 .result();
3615 }
3616
3617 public:
3619
3620 friend __base;
3621
3623 : __base(caps), v_{std::move(v)} {}
3624
3625 constexpr static uint8_t cmd_byte() noexcept {
3626 return static_cast<uint8_t>(CommandByte::RegisterReplica);
3627 }
3628
3629 /**
3630 * capabilities the codec depends on.
3631 */
3633 return {};
3634 }
3635
3639
3640 namespace bw = borrowable::wire;
3641
3642 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
3643 if (!accu.result()) return stdx::unexpected(accu.result().error());
3644
3645 if (cmd_byte_res->value() != cmd_byte()) {
3647 }
3648 auto server_id_res = accu.template step<bw::FixedInt<4>>();
3649 auto hostname_len_res = accu.template step<bw::FixedInt<1>>();
3650 if (!accu.result()) return stdx::unexpected(accu.result().error());
3651
3652 auto hostname_res =
3653 accu.template step<bw::String<Borrowed>>(hostname_len_res->value());
3654
3655 auto username_len_res = accu.template step<bw::FixedInt<1>>();
3656 if (!accu.result()) return stdx::unexpected(accu.result().error());
3657
3658 auto username_res =
3659 accu.template step<bw::String<Borrowed>>(username_len_res->value());
3660
3661 auto password_len_res = accu.template step<bw::FixedInt<1>>();
3662 if (!accu.result()) return stdx::unexpected(accu.result().error());
3663
3664 auto password_res =
3665 accu.template step<bw::String<Borrowed>>(password_len_res->value());
3666
3667 auto port_res = accu.template step<bw::FixedInt<2>>();
3668 auto replication_rank_res = accu.template step<bw::FixedInt<4>>();
3669 auto master_id_res = accu.template step<bw::FixedInt<4>>();
3670
3671 if (!accu.result()) return stdx::unexpected(accu.result().error());
3672
3673 return std::make_pair(
3674 accu.result().value(),
3675 value_type(server_id_res->value(), hostname_res->value(),
3676 username_res->value(), password_res->value(),
3677 port_res->value(), replication_rank_res->value(),
3678 master_id_res->value()));
3679 }
3680
3681 private:
3683};
3684
3685/**
3686 * codec for client side dump-binlog-with-gtid message.
3687 */
3688template <bool Borrowed>
3689class Codec<borrowable::message::client::BinlogDumpGtid<Borrowed>>
3690 : public impl::EncodeBase<
3691 Codec<borrowable::message::client::BinlogDumpGtid<Borrowed>>> {
3692 public:
3694
3695 private:
3696 template <class Accumulator>
3697 constexpr auto accumulate_fields(Accumulator &&accu) const {
3698 namespace bw = borrowable::wire;
3699
3700 accu.step(bw::FixedInt<1>(cmd_byte()))
3701 .step(bw::FixedInt<2>(v_.flags().underlying_value()))
3702 .step(bw::FixedInt<4>(v_.server_id()))
3703 .step(bw::FixedInt<4>(v_.filename().size()))
3704 .step(bw::String<Borrowed>(v_.filename()))
3705 .step(bw::FixedInt<8>(v_.position()));
3706
3707 if (v_.flags() & value_type::Flags::through_gtid) {
3708 accu.step(bw::FixedInt<4>(v_.sids().size()))
3709 .step(bw::String<Borrowed>(v_.sids()));
3710 }
3711
3712 return accu.result();
3713 }
3714
3715 public:
3717
3718 friend base_;
3719
3721 : base_(caps), v_{std::move(val)} {}
3722
3723 constexpr static uint8_t cmd_byte() noexcept {
3724 return static_cast<uint8_t>(CommandByte::BinlogDumpGtid);
3725 }
3726
3727 /**
3728 * capabilities the codec depends on.
3729 */
3731 return {};
3732 }
3733
3737
3738 namespace bw = borrowable::wire;
3739
3740 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
3741 if (!accu.result()) return stdx::unexpected(accu.result().error());
3742
3743 if (cmd_byte_res->value() != cmd_byte()) {
3745 }
3746 auto flags_res = accu.template step<bw::FixedInt<2>>();
3747 auto server_id_res = accu.template step<bw::FixedInt<4>>();
3748 auto filename_len_res = accu.template step<bw::FixedInt<4>>();
3749 if (!accu.result()) return stdx::unexpected(accu.result().error());
3750
3751 auto filename_res =
3752 accu.template step<bw::String<Borrowed>>(filename_len_res->value());
3753 auto position_res = accu.template step<bw::FixedInt<8>>();
3754
3756 flags.underlying_value(flags_res->value());
3757
3758 if (!(flags & value_type::Flags::through_gtid)) {
3759 if (!accu.result()) return stdx::unexpected(accu.result().error());
3760
3761 return std::make_pair(
3762 accu.result().value(),
3763 value_type(flags, server_id_res->value(), filename_res->value(),
3764 position_res->value(), {}));
3765 }
3766
3767 auto sids_len_res = accu.template step<bw::FixedInt<4>>();
3768 if (!accu.result()) return stdx::unexpected(accu.result().error());
3769
3770 auto sids_res =
3771 accu.template step<bw::String<Borrowed>>(sids_len_res->value());
3772
3773 if (!accu.result()) return stdx::unexpected(accu.result().error());
3774
3775 return std::make_pair(
3776 accu.result().value(),
3777 value_type(flags, server_id_res->value(), filename_res->value(),
3778 position_res->value(), sids_res->value()));
3779 }
3780
3781 private:
3783};
3784
3785} // namespace classic_protocol
3786
3787#endif
CRTP base for client-side commands that are encoded as a single byte.
Definition: classic_protocol_codec_message.h:1453
constexpr CodecSimpleCommand(capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:1466
friend __base
Definition: classic_protocol_codec_message.h:1464
static constexpr size_t max_size() noexcept
Definition: classic_protocol_codec_message.h:1468
static stdx::expected< std::pair< size_t, ValueType >, std::error_code > decode(const net::const_buffer &buffer, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:1470
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:1455
const value_type v_
Definition: classic_protocol_codec_message.h:3338
static stdx::expected< std::pair< size_t, value_type >, std::error_code > decode(const net::const_buffer &buffer, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:3323
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:3319
friend __base
Definition: classic_protocol_codec_message.h:3311
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:3301
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:3313
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:3723
const value_type v_
Definition: classic_protocol_codec_message.h:3782
static stdx::expected< std::pair< size_t, value_type >, std::error_code > decode(const net::const_buffer &buffer, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:3734
constexpr Codec(value_type val, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:3720
friend base_
Definition: classic_protocol_codec_message.h:3718
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:3730
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:3697
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:3541
friend __base
Definition: classic_protocol_codec_message.h:3539
const value_type v_
Definition: classic_protocol_codec_message.h:3585
static stdx::expected< std::pair< size_t, value_type >, std::error_code > decode(const net::const_buffer &buffer, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:3555
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:3525
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:3544
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:3551
const value_type v_
Definition: classic_protocol_codec_message.h:3483
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:3406
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:3399
static stdx::expected< std::pair< size_t, value_type >, std::error_code > decode(const net::const_buffer &buffer, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:3411
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:3396
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:3355
friend __base
Definition: classic_protocol_codec_message.h:3394
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:3501
constexpr Codec(value_type, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:3499
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:3508
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:1636
constexpr Codec(value_type, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:1634
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:1643
friend __base
Definition: classic_protocol_codec_message.h:3100
static stdx::expected< std::pair< size_t, value_type >, std::error_code > decode(const net::const_buffer &buffer, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:3114
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:3102
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:3028
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:3108
const value_type v_
Definition: classic_protocol_codec_message.h:3284
static stdx::expected< std::pair< size_t, value_type >, std::error_code > decode(const net::const_buffer &buffer, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:1684
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:1656
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:1680
const value_type v_
Definition: classic_protocol_codec_message.h:1705
friend __base
Definition: classic_protocol_codec_message.h:1668
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:1670
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:1673
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:2216
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:2192
value_type v_
Definition: classic_protocol_codec_message.h:2241
friend __base
Definition: classic_protocol_codec_message.h:2204
static stdx::expected< std::pair< size_t, value_type >, std::error_code > decode(const net::const_buffer &buffer, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:2220
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:2209
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:2206
const value_type v_
Definition: classic_protocol_codec_message.h:2119
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:2082
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:2085
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:2092
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:2067
friend __base
Definition: classic_protocol_codec_message.h:2080
static stdx::expected< std::pair< size_t, value_type >, std::error_code > decode(const net::const_buffer &buffer, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:2096
constexpr Codec(value_type, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:1584
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:1593
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:1586
const value_type v_
Definition: classic_protocol_codec_message.h:2003
friend __base
Definition: classic_protocol_codec_message.h:1880
auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:1716
static stdx::expected< std::pair< size_t, value_type >, std::error_code > decode(const net::const_buffer &buffer, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:1896
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:1885
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:1892
static stdx::expected< size_t, std::error_code > decode_field_size(Accu &accu, uint8_t type)
Definition: classic_protocol_codec_message.h:1822
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:1882
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:1535
constexpr Codec(value_type, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:1533
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:1542
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:3600
const value_type v_
Definition: classic_protocol_codec_message.h:3682
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:3625
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:3622
friend __base
Definition: classic_protocol_codec_message.h:3620
static stdx::expected< std::pair< size_t, value_type >, std::error_code > decode(const net::const_buffer &buffer, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:3636
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:3632
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:2153
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:2129
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:2146
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:2143
friend __base
Definition: classic_protocol_codec_message.h:2141
static stdx::expected< std::pair< size_t, value_type >, std::error_code > decode(const net::const_buffer &buffer, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:2157
const value_type v_
Definition: classic_protocol_codec_message.h:2177
constexpr Codec(value_type, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:1559
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:1561
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:1568
static stdx::expected< std::pair< size_t, value_type >, std::error_code > decode(const net::const_buffer &buffer, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:2042
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:2020
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:2038
friend __base
Definition: classic_protocol_codec_message.h:2030
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:2032
const value_type v_
Definition: classic_protocol_codec_message.h:2056
const value_type v_
Definition: classic_protocol_codec_message.h:2919
static stdx::expected< std::pair< size_t, value_type >, std::error_code > decode(const net::const_buffer &buffer, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:2898
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:2884
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:2894
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:2870
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:2887
friend __base
Definition: classic_protocol_codec_message.h:2882
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:1618
constexpr Codec(value_type, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:1609
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:1611
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:2776
friend __base
Definition: classic_protocol_codec_message.h:2764
const value_type v_
Definition: classic_protocol_codec_message.h:2801
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:2769
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:2752
static stdx::expected< std::pair< size_t, value_type >, std::error_code > decode(const net::const_buffer &buffer, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:2780
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:2766
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:2429
friend __base
Definition: classic_protocol_codec_message.h:2417
const value_type v_
Definition: classic_protocol_codec_message.h:2677
static stdx::expected< std::pair< size_t, value_type >, std::error_code > decode(const net::const_buffer &buffer, capabilities::value_type caps, Func &&metadata_lookup)
decode a buffer into a message::client::StmtExecute.
Definition: classic_protocol_codec_message.h:2477
auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:2312
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:2422
constexpr Codec(value_type val, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:2419
static stdx::expected< std::pair< size_t, value_type >, std::error_code > decode(const net::const_buffer &buffer, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:2958
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:2947
const value_type v_
Definition: classic_protocol_codec_message.h:2981
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:2929
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:2944
friend __base
Definition: classic_protocol_codec_message.h:2942
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:2954
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:2704
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:2707
const value_type v_
Definition: classic_protocol_codec_message.h:2742
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:2714
static stdx::expected< std::pair< size_t, value_type >, std::error_code > decode(const net::const_buffer &buffer, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:2718
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:2688
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:2269
static stdx::expected< std::pair< size_t, value_type >, std::error_code > decode(const net::const_buffer &buffer, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:2280
const value_type v_
Definition: classic_protocol_codec_message.h:2301
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:2266
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:2276
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:2252
friend __base
Definition: classic_protocol_codec_message.h:2264
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:2828
static stdx::expected< std::pair< size_t, value_type >, std::error_code > decode(const net::const_buffer &buffer, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:2839
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:2811
friend __base
Definition: classic_protocol_codec_message.h:2823
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:2835
const value_type v_
Definition: classic_protocol_codec_message.h:2860
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:2825
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:332
const value_type v_
Definition: classic_protocol_codec_message.h:365
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:318
borrowable::message::server::AuthMethodData< Borrowed > value_type
Definition: classic_protocol_codec_message.h:327
static constexpr uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:335
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:340
static stdx::expected< std::pair< size_t, value_type >, std::error_code > decode(const net::const_buffer &buffer, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:344
friend __base
Definition: classic_protocol_codec_message.h:330
borrowable::message::server::AuthMethodSwitch< Borrowed > value_type
Definition: classic_protocol_codec_message.h:261
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:266
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:247
static stdx::expected< std::pair< size_t, value_type >, std::error_code > decode(const net::const_buffer &buffer, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:278
static constexpr uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:269
const value_type v_
Definition: classic_protocol_codec_message.h:307
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:274
borrowable::message::server::ColumnCount value_type
Definition: classic_protocol_codec_message.h:785
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:790
friend __base
Definition: classic_protocol_codec_message.h:788
const value_type v_
Definition: classic_protocol_codec_message.h:811
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:778
static constexpr size_t max_size() noexcept
Definition: classic_protocol_codec_message.h:793
static stdx::expected< std::pair< size_t, value_type >, std::error_code > decode(const net::const_buffer &buffer, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:797
auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:825
const value_type v_
Definition: classic_protocol_codec_message.h:979
friend __base
Definition: classic_protocol_codec_message.h:869
Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:871
static stdx::expected< std::pair< size_t, value_type >, std::error_code > decode(const net::const_buffer &buffer, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:878
static size_t max_size() noexcept
Definition: classic_protocol_codec_message.h:874
borrowable::message::server::ColumnMeta< Borrowed > value_type
Definition: classic_protocol_codec_message.h:866
borrowable::message::server::Eof< Borrowed > value_type
Definition: classic_protocol_codec_message.h:560
const value_type v_
Definition: classic_protocol_codec_message.h:667
friend __base
Definition: classic_protocol_codec_message.h:563
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:573
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:565
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:518
static constexpr uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:568
static stdx::expected< std::pair< size_t, value_type >, std::error_code > decode(const net::const_buffer &buffer, capabilities::value_type caps)
decode a server::Eof message from a buffer-sequence.
Definition: classic_protocol_codec_message.h:598
friend __base
Definition: classic_protocol_codec_message.h:716
static constexpr uint8_t cmd_byte()
Definition: classic_protocol_codec_message.h:721
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:718
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:726
static stdx::expected< std::pair< size_t, value_type >, std::error_code > decode(const net::const_buffer &buffer, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:734
borrowable::message::server::Error< Borrowed > value_type
Definition: classic_protocol_codec_message.h:713
const value_type v_
Definition: classic_protocol_codec_message.h:768
static constexpr size_t max_size() noexcept
Definition: classic_protocol_codec_message.h:730
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:699
const value_type v_
Definition: classic_protocol_codec_message.h:236
friend __base
Definition: classic_protocol_codec_message.h:132
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:134
static stdx::expected< std::pair< size_t, value_type >, std::error_code > decode(const net::const_buffer &buffer, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:137
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:86
borrowable::message::server::Greeting< Borrowed > value_type
Definition: classic_protocol_codec_message.h:129
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:420
const value_type v_
Definition: classic_protocol_codec_message.h:492
borrowable::message::server::Ok< Borrowed > value_type
Definition: classic_protocol_codec_message.h:407
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:376
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:412
static stdx::expected< std::pair< size_t, value_type >, std::error_code > decode(const net::const_buffer &buffer, capabilities::value_type caps)
decode a server::Ok message from a buffer-sequence.
Definition: classic_protocol_codec_message.h:440
friend __base
Definition: classic_protocol_codec_message.h:410
static constexpr uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:415
static size_t max_size() noexcept
Definition: classic_protocol_codec_message.h:1173
Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:1170
const value_type v_
Definition: classic_protocol_codec_message.h:1206
auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:1150
static stdx::expected< std::pair< size_t, value_type >, std::error_code > decode(const net::const_buffer &buffer, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:1177
borrowable::message::server::Row< Borrowed > value_type
Definition: classic_protocol_codec_message.h:1165
friend __base
Definition: classic_protocol_codec_message.h:1168
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:1018
const value_type v_
Definition: classic_protocol_codec_message.h:1043
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:1010
friend __base
Definition: classic_protocol_codec_message.h:1008
borrowable::message::server::SendFileRequest< Borrowed > value_type
Definition: classic_protocol_codec_message.h:1005
static stdx::expected< std::pair< size_t, value_type >, std::error_code > decode(const net::const_buffer &buffer, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:1022
static constexpr uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:1013
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:996
const value_type v_
Definition: classic_protocol_codec_message.h:1445
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:1427
borrowable::message::server::Statistics< Borrowed > value_type
Definition: classic_protocol_codec_message.h:1422
friend __base
Definition: classic_protocol_codec_message.h:1425
static stdx::expected< std::pair< size_t, value_type >, std::error_code > decode(const net::const_buffer &buffer, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:1430
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:1415
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:1095
static stdx::expected< std::pair< size_t, value_type >, std::error_code > decode(const net::const_buffer &buffer, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:1104
friend __base
Definition: classic_protocol_codec_message.h:1090
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:1092
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:1100
borrowable::message::server::StmtPrepareOk value_type
Definition: classic_protocol_codec_message.h:1087
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:1069
const value_type v_
Definition: classic_protocol_codec_message.h:1139
const value_type v_
Definition: classic_protocol_codec_message.h:1404
Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:1298
borrowable::message::server::StmtRow< Borrowed > value_type
Definition: classic_protocol_codec_message.h:1293
static stdx::expected< std::pair< size_t, value_type >, std::error_code > decode(const net::const_buffer &buffer, capabilities::value_type caps, std::vector< field_type::value_type > types)
Definition: classic_protocol_codec_message.h:1305
static size_t max_size() noexcept
Definition: classic_protocol_codec_message.h:1301
auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:1228
friend __base
Definition: classic_protocol_codec_message.h:1296
Codec for a type.
Definition: classic_protocol_codec_base.h:72
Definition: classic_protocol_message.h:1273
Definition: classic_protocol_message.h:1335
Definition: classic_protocol_message.h:1307
Definition: classic_protocol_message.h:888
Definition: classic_protocol_message.h:1304
Definition: classic_protocol_message.h:1268
Definition: classic_protocol_message.h:684
Definition: classic_protocol_message.h:863
Definition: classic_protocol_message.h:976
Definition: classic_protocol_message.h:826
Definition: classic_protocol_message.h:1263
Definition: classic_protocol_message.h:786
Definition: classic_protocol_message.h:1258
Definition: classic_protocol_message.h:1367
Definition: classic_protocol_message.h:954
Definition: classic_protocol_message.h:941
Definition: classic_protocol_message.h:996
set options on the current connection.
Definition: classic_protocol_message.h:1238
Definition: classic_protocol_message.h:948
close a prepared statement.
Definition: classic_protocol_message.h:1168
execute a prepared statement.
Definition: classic_protocol_message.h:1090
fetch rows from an executed statement.
Definition: classic_protocol_message.h:1212
append data to a parameter of a prepared statement.
Definition: classic_protocol_message.h:1049
Definition: classic_protocol_message.h:1021
reset a prepared statement.
Definition: classic_protocol_message.h:1190
Definition: classic_protocol_wire.h:38
Definition: classic_protocol_wire.h:65
Generator of decoded Types of a buffer.
Definition: classic_protocol_codec_base.h:150
result_type result() const
get result of the step().
Definition: classic_protocol_codec_base.h:216
CRTP base for the Codec's encode part.
Definition: classic_protocol_codec_base.h:371
constexpr capabilities::value_type caps() const noexcept
Definition: classic_protocol_codec_base.h:386
Definition: buffer.h:135
size_t size() const noexcept
Definition: buffer.h:120
Definition: expected.h:286
constexpr const error_type & error() const &
Definition: expected.h:755
constexpr value_type & value() &
Definition: expected.h:642
a type-safe flags type.
Definition: flags.h:115
Definition: expected.h:112
constexpr DWORD buf_size
Definition: create_def.cc:229
static int flags[50]
Definition: hp_test1.cc:40
borrowable::binary::Null Null
Definition: classic_protocol_binary.h:337
borrowable::wire::VarInt VarInt
Definition: classic_protocol_wire.h:148
Definition: classic_protocol_constants.h:36
constexpr value_type text_result_with_session_tracking
Definition: classic_protocol_constants.h:62
constexpr value_type long_flag
Definition: classic_protocol_constants.h:40
constexpr value_type transactions
Definition: classic_protocol_constants.h:51
constexpr value_type plugin_auth
Definition: classic_protocol_constants.h:57
constexpr value_type session_track
Definition: classic_protocol_constants.h:61
constexpr value_type optional_resultset_metadata
Definition: classic_protocol_constants.h:63
constexpr value_type query_attributes
Definition: classic_protocol_constants.h:65
constexpr value_type connect_attributes
Definition: classic_protocol_constants.h:58
constexpr value_type client_auth_method_data_varint
Definition: classic_protocol_constants.h:59
constexpr value_type ssl
Definition: classic_protocol_constants.h:49
constexpr value_type connect_with_schema
Definition: classic_protocol_constants.h:41
constexpr value_type secure_connection
Definition: classic_protocol_constants.h:53
constexpr value_type protocol_41
Definition: classic_protocol_constants.h:47
constexpr value_type client_auth_method_data_varint
Definition: classic_protocol_constants.h:130
constexpr value_type connect_attributes
Definition: classic_protocol_constants.h:128
constexpr value_type plugin_auth
Definition: classic_protocol_constants.h:126
constexpr value_type ssl
Definition: classic_protocol_constants.h:110
constexpr value_type protocol_41
Definition: classic_protocol_constants.h:104
constexpr value_type transactions
Definition: classic_protocol_constants.h:113
constexpr value_type optional_resultset_metadata
Definition: classic_protocol_constants.h:142
constexpr value_type text_result_with_session_tracking
Definition: classic_protocol_constants.h:137
constexpr value_type secure_connection
Definition: classic_protocol_constants.h:116
constexpr value_type query_attributes
Definition: classic_protocol_constants.h:145
std::bitset< 32 > value_type
Definition: classic_protocol_constants.h:73
constexpr value_type connect_with_schema
Definition: classic_protocol_constants.h:86
constexpr value_type session_track
Definition: classic_protocol_constants.h:135
constexpr value_type param_count_available
Definition: classic_protocol_constants.h:216
constexpr value_type Short
Definition: classic_protocol_constants.h:233
constexpr value_type DateTime
Definition: classic_protocol_constants.h:243
constexpr value_type LongLong
Definition: classic_protocol_constants.h:239
constexpr value_type Varchar
Definition: classic_protocol_constants.h:246
constexpr value_type NewDecimal
Definition: classic_protocol_constants.h:253
constexpr value_type Time
Definition: classic_protocol_constants.h:242
constexpr value_type Decimal
Definition: classic_protocol_constants.h:231
constexpr value_type VarString
Definition: classic_protocol_constants.h:260
constexpr value_type MediumBlob
Definition: classic_protocol_constants.h:257
constexpr value_type String
Definition: classic_protocol_constants.h:261
constexpr value_type Set
Definition: classic_protocol_constants.h:255
constexpr value_type Geometry
Definition: classic_protocol_constants.h:262
constexpr value_type Bit
Definition: classic_protocol_constants.h:247
constexpr value_type Tiny
Definition: classic_protocol_constants.h:232
constexpr value_type TinyBlob
Definition: classic_protocol_constants.h:256
constexpr value_type Json
Definition: classic_protocol_constants.h:252
constexpr value_type Int24
Definition: classic_protocol_constants.h:240
constexpr value_type Enum
Definition: classic_protocol_constants.h:254
constexpr value_type Long
Definition: classic_protocol_constants.h:234
constexpr value_type Double
Definition: classic_protocol_constants.h:236
constexpr value_type Year
Definition: classic_protocol_constants.h:244
constexpr value_type Timestamp
Definition: classic_protocol_constants.h:238
constexpr value_type LongBlob
Definition: classic_protocol_constants.h:258
constexpr value_type Blob
Definition: classic_protocol_constants.h:259
constexpr value_type Date
Definition: classic_protocol_constants.h:241
constexpr value_type Float
Definition: classic_protocol_constants.h:235
borrowable::message::client::StmtFetch StmtFetch
Definition: classic_protocol_message.h:1446
borrowable::message::client::StmtReset StmtReset
Definition: classic_protocol_message.h:1441
borrowable::message::client::Reload Reload
Definition: classic_protocol_message.h:1436
borrowable::message::client::SetOption SetOption
Definition: classic_protocol_message.h:1445
borrowable::message::client::Kill Kill
Definition: classic_protocol_message.h:1434
borrowable::message::client::StmtClose StmtClose
Definition: classic_protocol_message.h:1442
borrowable::message::server::AuthMethodSwitch< false > AuthMethodSwitch
Definition: classic_protocol_message.h:1416
borrowable::message::server::Error< false > Error
Definition: classic_protocol_message.h:1411
borrowable::message::server::StmtPrepareOk StmtPrepareOk
Definition: classic_protocol_message.h:1421
borrowable::message::server::Greeting< false > Greeting
Definition: classic_protocol_message.h:1413
borrowable::message::server::Row< false > Row
Definition: classic_protocol_message.h:1419
borrowable::message::server::Eof< false > Eof
Definition: classic_protocol_message.h:1412
borrowable::message::server::ColumnCount ColumnCount
Definition: classic_protocol_message.h:1414
borrowable::message::server::Ok< false > Ok
Definition: classic_protocol_message.h:1410
borrowable::message::server::AuthMethodData< false > AuthMethodData
Definition: classic_protocol_message.h:1417
borrowable::message::server::Statistics< false > Statistics
Definition: classic_protocol_message.h:1422
borrowable::message::server::StmtRow< false > StmtRow
Definition: classic_protocol_message.h:1420
borrowable::message::server::SendFileRequest< false > SendFileRequest
Definition: classic_protocol_message.h:1418
borrowable::message::server::ColumnMeta< false > ColumnMeta
Definition: classic_protocol_message.h:1415
constexpr value_type session_state_changed
Definition: classic_protocol_constants.h:165
constexpr value_type session_state_changed
Definition: classic_protocol_constants.h:207
Definition: classic_protocol_binary.h:39
std::error_code make_error_code(codec_errc e) noexcept
Definition: classic_protocol_codec_error.h:86
CommandByte
Definition: classic_protocol_codec_message.h:1487
constexpr size_t bytes_per_bits(size_t bits)
Definition: classic_protocol_codec_base.h:55
ValueType max(X &&first)
Definition: gtid.h:103
mutable_buffer buffer(void *p, size_t n) noexcept
Definition: buffer.h:418
size_t buffer_size(const ConstBufferSequence &buffers) noexcept
Definition: buffer.h:313
Definition: gcs_xcom_synode.h:64
constexpr auto enumerate(T &&iterable)
Definition: ranges.h:143
unexpected(E) -> unexpected< E >
required string type
Definition: replication_group_member_actions.proto:34
int n
Definition: xcom_base.cc:509