MySQL 9.0.0
Source Code Documentation
classic_protocol_codec_message.h
Go to the documentation of this file.
1/*
2 Copyright (c) 2019, 2024, 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 (this->caps().test(capabilities::pos::session_track)) {
392 accu.step(bw::VarString<Borrowed>(v_.message()));
393 if (v_.status_flags().test(status::pos::session_state_changed)) {
394 accu.step(bw::VarString<Borrowed>(v_.session_changes()));
395 }
396 } else {
397 accu.step(bw::String<Borrowed>(v_.message()));
398 }
399
400 return accu.result();
401 }
402
403 public:
404 using value_type = borrowable::message::server::Ok<Borrowed>;
406
407 friend __base;
408
410 : __base(caps), v_{std::move(v)} {}
411
412 static constexpr uint8_t cmd_byte() noexcept { return 0x00; }
413
414 /**
415 * capabilities the codec depends on.
416 */
420 }
421
422 /**
423 * decode a server::Ok message from a buffer-sequence.
424 *
425 * precondition:
426 * - input starts with cmd_byte()
427 *
428 * @param buffer input buffser sequence
429 * @param caps protocol capabilities
430 *
431 * @retval std::pair<size_t, message::server::Ok> on success, with bytes
432 * processed
433 * @retval codec_errc::invalid_input if preconditions aren't met
434 * @retval codec_errc::not_enough_input not enough data to parse the whole
435 * message
436 */
440
441 namespace bw = borrowable::wire;
442
443 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
444 if (!accu.result()) return stdx::unexpected(accu.result().error());
445
446 if (cmd_byte_res->value() != cmd_byte()) {
448 }
449
450 auto affected_rows_res = accu.template step<bw::VarInt>();
451 auto last_insert_id_res = accu.template step<bw::VarInt>();
452
453 stdx::expected<bw::FixedInt<2>, std::error_code> status_flags_res(0);
454 stdx::expected<bw::FixedInt<2>, std::error_code> warning_count_res(0);
457 status_flags_res = accu.template step<bw::FixedInt<2>>();
459 warning_count_res = accu.template step<bw::FixedInt<2>>();
460 }
461 }
462
463 stdx::expected<bw::String<Borrowed>, std::error_code> message_res;
465 session_changes_res;
467 // if there is more data.
468 const auto var_message_res =
469 accu.template try_step<bw::VarString<Borrowed>>();
470 if (var_message_res) {
471 // set the message from the var-string
472 message_res = var_message_res.value();
473 }
474
475 if (status_flags_res->value() &
477 session_changes_res = accu.template step<bw::VarString<Borrowed>>();
478 }
479 } else {
480 message_res = accu.template step<bw::String<Borrowed>>();
481 }
482
483 if (!accu.result()) return stdx::unexpected(accu.result().error());
484
485 return std::make_pair(
486 accu.result().value(),
487 value_type(affected_rows_res->value(), last_insert_id_res->value(),
488 status_flags_res->value(), warning_count_res->value(),
489 message_res->value(), session_changes_res->value()));
490 }
491
492 private:
494};
495
496/**
497 * codec for server-side Eof message.
498 *
499 * Eof message is encoded differently dependending on protocol capabiltiies,
500 * but always starts with:
501 *
502 * - 0xef
503 *
504 * If capabilities has text_result_with_session_tracking, it is followed by
505 * - [rest of Ok packet]
506 *
507 * otherwise, if capabilities has protocol_41
508 * - FixedInt<2> warning-count
509 * - FixedInt<2> status flags
510 *
511 * otherwise
512 * - nothing
513 */
514template <bool Borrowed>
515class Codec<borrowable::message::server::Eof<Borrowed>>
516 : public impl::EncodeBase<
517 Codec<borrowable::message::server::Eof<Borrowed>>> {
518 template <class Accumulator>
519 constexpr auto accumulate_fields(Accumulator &&accu) const {
520 namespace bw = borrowable::wire;
521
522 accu.step(bw::FixedInt<1>(cmd_byte()));
523
524 auto shared_caps = this->caps();
525
526 if (shared_caps.test(
528 accu.step(bw::VarInt(v_.affected_rows()))
529 .step(bw::VarInt(v_.last_insert_id()));
530
531 if (shared_caps[capabilities::pos::protocol_41] ||
532 shared_caps[capabilities::pos::transactions]) {
533 accu.step(bw::FixedInt<2>(v_.status_flags().to_ulong()));
534 if (shared_caps[capabilities::pos::protocol_41]) {
535 accu.step(bw::FixedInt<2>(v_.warning_count()));
536 }
537 }
538
539 if (shared_caps[capabilities::pos::session_track]) {
540 if (!v_.message().empty() ||
541 v_.status_flags()[status::pos::session_state_changed]) {
542 // only write message and session-changes if both of them aren't
543 // empty.
544 accu.step(bw::VarString<Borrowed>(v_.message()));
545 if (v_.status_flags()[status::pos::session_state_changed]) {
546 accu.step(bw::VarString<Borrowed>(v_.session_changes()));
547 }
548 }
549 } else {
550 accu.step(bw::String<Borrowed>(v_.message()));
551 }
552 } else if (shared_caps[capabilities::pos::protocol_41]) {
553 accu.step(bw::FixedInt<2>(v_.warning_count()))
554 .step(bw::FixedInt<2>(v_.status_flags().to_ulong()));
555 }
556
557 return accu.result();
558 }
559
560 public:
561 using value_type = borrowable::message::server::Eof<Borrowed>;
563
564 friend __base;
565
567 : __base(caps), v_{std::move(v)} {}
568
569 static constexpr uint8_t cmd_byte() noexcept { return 0xfe; }
570
571 /**
572 * capabilities the codec depends on.
573 */
578 }
579
580 /**
581 * decode a server::Eof message from a buffer-sequence.
582 *
583 * capabilities checked:
584 * - protocol_41
585 * - text_resultset_with_session_tracking
586 *
587 * precondition:
588 * - input starts with cmd_byte()
589 *
590 * @param buffer input buffser sequence
591 * @param caps protocol capabilities
592 *
593 * @retval std::pair<size_t, message::server::Eof> on success, with bytes
594 * processed
595 * @retval codec_errc::invalid_input if preconditions aren't met
596 * @retval codec_errc::not_enough_input not enough data to parse the whole
597 * message
598 */
602
603 namespace bw = borrowable::wire;
604
605 const auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
606 if (!accu.result()) return stdx::unexpected(accu.result().error());
607
608 if (cmd_byte_res->value() != cmd_byte()) {
610 }
611
613 const auto affected_rows_res = accu.template step<bw::VarInt>();
614 const auto last_insert_id_res = accu.template step<bw::VarInt>();
615
616 stdx::expected<bw::FixedInt<2>, std::error_code> status_flags_res(0);
617 stdx::expected<bw::FixedInt<2>, std::error_code> warning_count_res(0);
620 status_flags_res = accu.template step<bw::FixedInt<2>>();
622 warning_count_res = accu.template step<bw::FixedInt<2>>();
623 }
624 }
625
626 stdx::expected<bw::String<Borrowed>, std::error_code> message_res;
628 session_state_info_res;
630 // when session-track is supported, the 'message' part is a VarString.
631 // But only if there is actually session-data and the message has data.
632 const auto var_message_res =
633 accu.template try_step<bw::VarString<Borrowed>>();
634 if (var_message_res) {
635 // set the message from the var-string
636 message_res = var_message_res.value();
637 }
638
639 if (status_flags_res->value() &
641 session_state_info_res =
642 accu.template step<bw::VarString<Borrowed>>();
643 }
644 } else {
645 message_res = accu.template step<bw::String<Borrowed>>();
646 }
647
648 if (!accu.result()) return stdx::unexpected(accu.result().error());
649
650 return std::make_pair(
651 accu.result().value(),
652 value_type(affected_rows_res->value(), last_insert_id_res->value(),
653 status_flags_res->value(), warning_count_res->value(),
654 message_res->value(), session_state_info_res->value()));
655 } else if (caps[capabilities::pos::protocol_41]) {
656 const auto warning_count_res = accu.template step<bw::FixedInt<2>>();
657 const auto status_flags_res = accu.template step<bw::FixedInt<2>>();
658
659 return std::make_pair(
660 accu.result().value(),
661 value_type(status_flags_res->value(), warning_count_res->value()));
662 } else {
663 return std::make_pair(accu.result().value(), value_type());
664 }
665 }
666
667 private:
669};
670
671/**
672 * codec for Error message.
673 *
674 * note: Format overview:
675 *
676 * 3.21: protocol_version <= 9 [not supported]
677 *
678 * FixedInt<1> 0xff
679 * String message
680 *
681 * 3.21: protocol_version > 9
682 *
683 * FixedInt<1> 0xff
684 * FixedInt<2> error_code
685 * String message
686 *
687 * 4.1 and later:
688 *
689 * FixedInt<1> 0xff
690 * FixedInt<2> error_code
691 * '#'
692 * String<5> sql_state
693 * String message
694 */
695template <bool Borrowed>
696class Codec<borrowable::message::server::Error<Borrowed>>
697 : public impl::EncodeBase<
698 Codec<borrowable::message::server::Error<Borrowed>>> {
699 template <class Accumulator>
700 constexpr auto accumulate_fields(Accumulator &&accu) const {
701 namespace bw = borrowable::wire;
702
703 accu.step(bw::FixedInt<1>(cmd_byte()))
704 .step(bw::FixedInt<2>(v_.error_code()));
705 if (this->caps()[capabilities::pos::protocol_41]) {
706 accu.step(bw::FixedInt<1>('#'))
707 .step(bw::String<Borrowed>(v_.sql_state()));
708 }
709
710 return accu.step(bw::String<Borrowed>(v_.message())).result();
711 }
712
713 public:
714 using value_type = borrowable::message::server::Error<Borrowed>;
716
717 friend __base;
718
720 : __base(caps), v_{std::move(v)} {}
721
722 static constexpr uint8_t cmd_byte() { return 0xff; }
723
724 /**
725 * capabilities the codec depends on.
726 */
729 }
730
731 static constexpr size_t max_size() noexcept {
732 return std::numeric_limits<size_t>::max();
733 }
734
738
739 namespace bw = borrowable::wire;
740
741 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
742 if (!accu.result()) return stdx::unexpected(accu.result().error());
743
744 if (cmd_byte_res->value() != cmd_byte()) {
746 }
747
748 // decode all fields, check result later before they are used.
749 auto error_code_res = accu.template step<bw::FixedInt<2>>();
750 stdx::expected<bw::String<Borrowed>, std::error_code> sql_state_res;
752 auto sql_state_hash_res = accu.template step<bw::FixedInt<1>>();
753 if (!sql_state_hash_res) {
754 return stdx::unexpected(sql_state_hash_res.error());
755 }
756 sql_state_res = accu.template step<bw::String<Borrowed>>(5);
757 }
758 auto message_res = accu.template step<bw::String<Borrowed>>();
759
760 if (!accu.result()) return stdx::unexpected(accu.result().error());
761
762 return std::make_pair(
763 accu.result().value(),
764 value_type(error_code_res->value(), message_res->value(),
765 sql_state_res->value()));
766 }
767
768 private:
770};
771
772/**
773 * codec for ColumnCount message.
774 */
775template <>
777 : public impl::EncodeBase<Codec<borrowable::message::server::ColumnCount>> {
778 template <class Accumulator>
779 constexpr auto accumulate_fields(Accumulator &&accu) const {
780 namespace bw = borrowable::wire;
781
782 return accu.step(bw::VarInt(v_.count())).result();
783 }
784
785 public:
788
789 friend __base;
790
792 : __base(caps), v_{std::move(v)} {}
793
794 static constexpr size_t max_size() noexcept {
795 return std::numeric_limits<size_t>::max();
796 }
797
801
802 namespace bw = borrowable::wire;
803
804 auto count_res = accu.template step<bw::VarInt>();
805 if (!accu.result()) return stdx::unexpected(accu.result().error());
806
807 return std::make_pair(accu.result().value(),
808 value_type(count_res->value()));
809 }
810
811 private:
813};
814
815/**
816 * Codec of ColumnMeta.
817 *
818 * capabilities checked:
819 * - protocol_41
820 */
821template <bool Borrowed>
822class Codec<borrowable::message::server::ColumnMeta<Borrowed>>
823 : public impl::EncodeBase<
824 Codec<borrowable::message::server::ColumnMeta<Borrowed>>> {
825 template <class Accumulator>
826 auto accumulate_fields(Accumulator &&accu) const {
827 namespace bw = borrowable::wire;
828
829 if (!this->caps()[capabilities::pos::protocol_41]) {
830 accu.step(bw::VarString<Borrowed>(v_.table()))
831 .step(bw::VarString<Borrowed>(v_.name()))
832 .step(bw::VarInt(3))
833 .step(bw::FixedInt<3>(v_.column_length()))
834 .step(bw::VarInt(1))
835 .step(bw::FixedInt<1>(v_.type()));
836
837 if (this->caps()[capabilities::pos::long_flag]) {
838 accu.step(bw::VarInt(3))
839 .step(bw::FixedInt<2>(v_.flags().to_ulong()))
840 .step(bw::FixedInt<1>(v_.decimals()));
841 } else {
842 accu.step(bw::VarInt(2))
843 .step(bw::FixedInt<1>(v_.flags().to_ulong()))
844 .step(bw::FixedInt<1>(v_.decimals()));
845 }
846
847 return accu.result();
848 } else {
849 return accu.step(bw::VarString<Borrowed>(v_.catalog()))
850 .step(bw::VarString<Borrowed>(v_.schema()))
851 .step(bw::VarString<Borrowed>(v_.table()))
852 .step(bw::VarString<Borrowed>(v_.orig_table()))
853 .step(bw::VarString<Borrowed>(v_.name()))
854 .step(bw::VarString<Borrowed>(v_.orig_name()))
855 .step(bw::VarInt(12))
856 .step(bw::FixedInt<2>(v_.collation()))
857 .step(bw::FixedInt<4>(v_.column_length()))
858 .step(bw::FixedInt<1>(v_.type()))
859 .step(bw::FixedInt<2>(v_.flags().to_ulong()))
860 .step(bw::FixedInt<1>(v_.decimals()))
861 .step(bw::FixedInt<2>(0))
862 .result();
863 }
864 }
865
866 public:
867 using value_type = borrowable::message::server::ColumnMeta<Borrowed>;
869
870 friend __base;
871
873 : __base(caps), v_{std::move(v)} {}
874
875 static size_t max_size() noexcept {
876 return std::numeric_limits<size_t>::max();
877 }
878
882
883 namespace bw = borrowable::wire;
884
886 // 3.2x protocol used up to 4.0.x
887
888 // bit-size of the 'flags' field
889 const uint8_t flags_size = caps[capabilities::pos::long_flag] ? 2 : 1;
890
891 const auto table_res = accu.template step<bw::VarString<Borrowed>>();
892 const auto name_res = accu.template step<bw::VarString<Borrowed>>();
893
894 const auto column_length_len_res = accu.template step<bw::VarInt>();
895 if (!accu.result()) return stdx::unexpected(accu.result().error());
896
897 if (column_length_len_res->value() != 3) {
899 }
900
901 const auto column_length_res = accu.template step<bw::FixedInt<3>>();
902 const auto type_len_res = accu.template step<bw::VarInt>();
903 if (!accu.result()) return stdx::unexpected(accu.result().error());
904
905 if (type_len_res->value() != 1) {
907 }
908
909 const auto type_res = accu.template step<bw::FixedInt<1>>();
910 const auto flags_and_decimals_len_res = accu.template step<bw::VarInt>();
911 if (!accu.result()) return stdx::unexpected(accu.result().error());
912
913 if (flags_and_decimals_len_res->value() != flags_size + 1) {
915 }
916
917 stdx::expected<bw::FixedInt<3>, std::error_code> flags_and_decimals_res(
918 0);
919 if (flags_size == 2) {
920 flags_and_decimals_res = accu.template step<bw::FixedInt<3>>();
921 } else {
922 const auto small_flags_and_decimals_res =
923 accu.template step<bw::FixedInt<2>>();
924 if (small_flags_and_decimals_res) {
925 flags_and_decimals_res =
926 bw::FixedInt<3>(small_flags_and_decimals_res->value());
927 }
928 }
929
930 if (!accu.result()) return stdx::unexpected(accu.result().error());
931
932 const uint16_t flags =
933 flags_and_decimals_res->value() & ((1 << (flags_size * 8)) - 1);
934 const uint8_t decimals =
935 flags_and_decimals_res->value() >> (flags_size * 8);
936
937 return std::make_pair(
938 accu.result().value(),
939 value_type({}, {}, table_res->value(), {}, name_res->value(), {}, {},
940 column_length_res->value(), type_res->value(), flags,
941 decimals));
942 } else {
943 const auto catalog_res = accu.template step<bw::VarString<Borrowed>>();
944 const auto schema_res = accu.template step<bw::VarString<Borrowed>>();
945 const auto table_res = accu.template step<bw::VarString<Borrowed>>();
946 const auto orig_table_res = accu.template step<bw::VarString<Borrowed>>();
947 const auto name_res = accu.template step<bw::VarString<Borrowed>>();
948 const auto orig_name_res = accu.template step<bw::VarString<Borrowed>>();
949
950 /* next is a collection of fields which is wrapped inside a varstring of
951 * 12-bytes size */
952 const auto other_len_res = accu.template step<bw::VarInt>();
953
954 if (other_len_res->value() != 12) {
956 }
957
958 const auto collation_res = accu.template step<bw::FixedInt<2>>();
959 const auto column_length_res = accu.template step<bw::FixedInt<4>>();
960 const auto type_res = accu.template step<bw::FixedInt<1>>();
961 const auto flags_res = accu.template step<bw::FixedInt<2>>();
962 const auto decimals_res = accu.template step<bw::FixedInt<1>>();
963
964 accu.template step<void>(2); // fillers
965
966 if (!accu.result()) return stdx::unexpected(accu.result().error());
967
968 return std::make_pair(
969 accu.result().value(),
970 value_type(catalog_res->value(), schema_res->value(),
971 table_res->value(), orig_table_res->value(),
972 name_res->value(), orig_name_res->value(),
973 collation_res->value(), column_length_res->value(),
974 type_res->value(), flags_res->value(),
975 decimals_res->value()));
976 }
977 }
978
979 private:
981};
982
983/**
984 * codec for server's SendFileRequest response.
985 *
986 * sent as response after client::Query
987 *
988 * layout:
989 *
990 * 0xfb<filename>
991 */
992template <bool Borrowed>
993class Codec<borrowable::message::server::SendFileRequest<Borrowed>>
994 : public impl::EncodeBase<
995 Codec<borrowable::message::server::SendFileRequest<Borrowed>>> {
996 template <class Accumulator>
997 constexpr auto accumulate_fields(Accumulator &&accu) const {
998 namespace bw = borrowable::wire;
999
1000 return accu.step(bw::FixedInt<1>(cmd_byte()))
1001 .step(bw::String<Borrowed>(v_.filename()))
1002 .result();
1003 }
1004
1005 public:
1006 using value_type = borrowable::message::server::SendFileRequest<Borrowed>;
1008
1009 friend __base;
1010
1012 : __base(caps), v_{std::move(v)} {}
1013
1014 static constexpr uint8_t cmd_byte() noexcept { return 0xfb; }
1015
1016 /**
1017 * capabilities the codec depends on.
1018 */
1020 return {};
1021 }
1022
1026
1027 namespace bw = borrowable::wire;
1028
1029 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
1030 if (!accu.result()) return stdx::unexpected(accu.result().error());
1031
1032 if (cmd_byte_res->value() != cmd_byte()) {
1034 }
1035
1036 auto filename_res = accu.template step<bw::String<Borrowed>>();
1037 if (!accu.result()) return stdx::unexpected(accu.result().error());
1038
1039 return std::make_pair(accu.result().value(),
1040 value_type(filename_res->value()));
1041 }
1042
1043 private:
1045};
1046
1047/**
1048 * codec for server::StmtPrepareOk message.
1049 *
1050 * format:
1051 *
1052 * - FixedInt<1> == 0x00 [ok]
1053 * - FixedInt<4> stmt-id
1054 * - FixedInt<2> column-count
1055 * - FixedInt<2> param-count
1056 * - FixedInt<1> == 0x00 [filler]
1057 * - FixedInt<2> warning-count
1058 *
1059 * If caps contains optional_resultset_metadata:
1060 *
1061 * - FixedInt<1> with_metadata
1062 *
1063 * sent as response after a client::StmtPrepare
1064 */
1065template <>
1067 : public impl::EncodeBase<
1068 Codec<borrowable::message::server::StmtPrepareOk>> {
1069 template <class Accumulator>
1070 constexpr auto accumulate_fields(Accumulator &&accu) const {
1071 namespace bw = borrowable::wire;
1072
1073 accu.step(bw::FixedInt<1>(cmd_byte()))
1074 .step(bw::FixedInt<4>(v_.statement_id()))
1075 .step(bw::FixedInt<2>(v_.column_count()))
1076 .step(bw::FixedInt<2>(v_.param_count()))
1077 .step(bw::FixedInt<1>(0))
1078 .step(bw::FixedInt<2>(v_.warning_count()));
1079
1081 accu.step(bw::FixedInt<1>(v_.with_metadata()));
1082 }
1083
1084 return accu.result();
1085 }
1086
1087 public:
1090
1091 friend __base;
1092
1094 : __base(caps), v_{std::move(v)} {}
1095
1096 constexpr static uint8_t cmd_byte() noexcept { return 0x00; }
1097
1098 /**
1099 * capabilities the codec depends on.
1100 */
1103 }
1104
1108
1109 namespace bw = borrowable::wire;
1110
1111 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
1112 if (!cmd_byte_res) return stdx::unexpected(cmd_byte_res.error());
1113 auto stmt_id_res = accu.template step<bw::FixedInt<4>>();
1114 auto column_count_res = accu.template step<bw::FixedInt<2>>();
1115 auto param_count_res = accu.template step<bw::FixedInt<2>>();
1116 auto filler_res = accu.template step<bw::FixedInt<1>>();
1117 if (!filler_res) return stdx::unexpected(filler_res.error());
1118 auto warning_count_res = accu.template step<bw::FixedInt<2>>();
1119
1120 // by default, metadata isn't optional
1121 int8_t with_metadata{1};
1123 auto with_metadata_res = accu.template step<bw::FixedInt<1>>();
1124
1125 if (with_metadata_res) {
1126 with_metadata = with_metadata_res->value();
1127 }
1128 }
1129
1130 if (!accu.result()) return stdx::unexpected(accu.result().error());
1131
1132 return std::make_pair(
1133 accu.result().value(),
1134 value_type(stmt_id_res->value(), column_count_res->value(),
1135 param_count_res->value(), warning_count_res->value(),
1136 with_metadata));
1137 }
1138
1139 private:
1141};
1142
1143/**
1144 * codec for a Row from the server.
1145 */
1146template <bool Borrowed>
1147class Codec<borrowable::message::server::Row<Borrowed>>
1148 : public impl::EncodeBase<
1149 Codec<borrowable::message::server::Row<Borrowed>>> {
1150 template <class Accumulator>
1151 auto accumulate_fields(Accumulator &&accu) const {
1152 namespace bw = borrowable::wire;
1153
1154 for (const auto &field : v_) {
1155 if (field) {
1156 accu.step(bw::VarString<Borrowed>(*field));
1157 } else {
1158 accu.step(bw::Null());
1159 }
1160 }
1161
1162 return accu.result();
1163 }
1164
1165 public:
1166 using value_type = borrowable::message::server::Row<Borrowed>;
1168
1169 friend __base;
1170
1172 : __base(caps), v_{std::move(v)} {}
1173
1174 static size_t max_size() noexcept {
1175 return std::numeric_limits<size_t>::max();
1176 }
1177
1181
1182 namespace bw = borrowable::wire;
1183
1184 std::vector<typename value_type::value_type> fields;
1185
1186 const size_t buf_size = buffer_size(buffer);
1187
1188 while (accu.result() && (accu.result().value() < buf_size)) {
1189 // field may other be a Null or a VarString
1190 auto null_res = accu.template try_step<bw::Null>();
1191 if (null_res) {
1192 fields.emplace_back(std::nullopt);
1193 } else {
1194 auto field_res = accu.template step<bw::VarString<Borrowed>>();
1195 if (!field_res) return stdx::unexpected(field_res.error());
1196
1197 fields.emplace_back(field_res->value());
1198 }
1199 }
1200
1201 if (!accu.result()) return stdx::unexpected(accu.result().error());
1202
1203 return std::make_pair(accu.result().value(), value_type(fields));
1204 }
1205
1206 private:
1208};
1209
1210/**
1211 * codec for a StmtRow from the server.
1212 *
1213 * StmtRow is the Row of a StmtExecute's resultset.
1214 *
1215 * - 0x00
1216 * - NULL bitmap
1217 * - non-NULL-values in binary encoding
1218 *
1219 * both encode and decode require type information to know:
1220 *
1221 * - size the NULL bitmap
1222 * - length of each field
1223 */
1224template <bool Borrowed>
1225class Codec<borrowable::message::server::StmtRow<Borrowed>>
1226 : public impl::EncodeBase<
1227 Codec<borrowable::message::server::StmtRow<Borrowed>>> {
1228 template <class Accumulator>
1229 auto accumulate_fields(Accumulator &&accu) const {
1230 namespace bw = borrowable::wire;
1231
1232 accu.step(bw::FixedInt<1>(0));
1233
1234 // null-bitmap starts with a 2-bit offset
1235 size_t bit_pos{2};
1236 uint8_t null_bit_byte{};
1237
1238 for (auto const &field : v_) {
1239 if (!field) null_bit_byte |= (1 << bit_pos);
1240
1241 if (++bit_pos > 7) {
1242 accu.step(bw::FixedInt<1>(null_bit_byte));
1243
1244 bit_pos = 0;
1245 null_bit_byte = 0;
1246 }
1247 }
1248
1249 if (bit_pos != 0) accu.step(bw::FixedInt<1>(null_bit_byte));
1250
1251 for (auto [n, field] : stdx::views::enumerate(v_)) {
1252 if (!field) continue;
1253
1254 switch (v_.types()[n]) {
1255 case field_type::Bit:
1256 case field_type::Blob:
1259 case field_type::Set:
1260 case field_type::String:
1261 case field_type::Enum:
1268 accu.step(bw::VarInt(field->size()));
1269 break;
1270 case field_type::Date:
1273 case field_type::Time:
1274 accu.step(bw::FixedInt<1>(field->size()));
1275 break;
1277 case field_type::Double:
1278 case field_type::Long:
1279 case field_type::Int24:
1280 case field_type::Float:
1281 case field_type::Short:
1282 case field_type::Year:
1283 case field_type::Tiny:
1284 // fixed size
1285 break;
1286 }
1287 accu.step(borrowed::wire::String(*field));
1288 }
1289
1290 return accu.result();
1291 }
1292
1293 public:
1294 using value_type = borrowable::message::server::StmtRow<Borrowed>;
1296
1297 friend __base;
1298
1300 : __base(caps), v_{std::move(v)} {}
1301
1302 static size_t max_size() noexcept {
1303 return std::numeric_limits<size_t>::max();
1304 }
1305
1308 std::vector<field_type::value_type> types) {
1309 namespace bw = borrowable::wire;
1310
1312
1313 const auto row_byte_res = accu.template step<bw::FixedInt<1>>();
1314 if (!accu.result()) return stdx::unexpected(accu.result().error());
1315
1316 // first byte is 0x00
1317 if (row_byte_res->value() != 0x00) {
1319 }
1320
1321 const auto nullbits_res =
1322 accu.template step<bw::String<Borrowed>>(bytes_per_bits(types.size()));
1323 if (!accu.result()) return stdx::unexpected(accu.result().error());
1324
1325 const auto nullbits = nullbits_res->value();
1326
1327 std::vector<typename value_type::value_type> values;
1328
1329 for (size_t n{}, bit_pos{2}, byte_pos{}; n < types.size(); ++n, ++bit_pos) {
1330 if (bit_pos > 7) {
1331 bit_pos = 0;
1332 ++byte_pos;
1333 }
1334
1335 if (!(nullbits[byte_pos] & (1 << bit_pos))) {
1337 stdx::unexpected(make_error_code(std::errc::invalid_argument)));
1338 switch (types[n]) {
1339 case field_type::Bit:
1340 case field_type::Blob:
1343 case field_type::Set:
1344 case field_type::String:
1345 case field_type::Enum:
1351 case field_type::Geometry: {
1352 auto string_field_size_res = accu.template step<bw::VarInt>();
1353 if (!accu.result()) return stdx::unexpected(accu.result().error());
1354
1355 field_size_res = string_field_size_res->value();
1356 } break;
1357 case field_type::Date:
1360 case field_type::Time: {
1361 auto time_field_size_res = accu.template step<bw::FixedInt<1>>();
1362 if (!accu.result()) return stdx::unexpected(accu.result().error());
1363
1364 field_size_res = time_field_size_res->value();
1365 } break;
1367 case field_type::Double:
1368 field_size_res = 8;
1369 break;
1370 case field_type::Long:
1371 case field_type::Int24:
1372 case field_type::Float:
1373 field_size_res = 4;
1374 break;
1375 case field_type::Short:
1376 case field_type::Year:
1377 field_size_res = 2;
1378 break;
1379 case field_type::Tiny:
1380 field_size_res = 1;
1381 break;
1382 }
1383
1384 if (!field_size_res) {
1385 return stdx::unexpected(
1387 }
1388
1389 const auto value_res =
1390 accu.template step<bw::String<Borrowed>>(field_size_res.value());
1391 if (!accu.result()) return stdx::unexpected(accu.result().error());
1392
1393 values.push_back(value_res->value());
1394 } else {
1395 values.emplace_back(std::nullopt);
1396 }
1397 }
1398
1399 if (!accu.result()) return stdx::unexpected(accu.result().error());
1400
1401 return std::make_pair(accu.result().value(), value_type(types, values));
1402 }
1403
1404 private:
1406};
1407
1408/**
1409 * codec for server::Statistics message.
1410 */
1411template <bool Borrowed>
1412class Codec<borrowable::message::server::Statistics<Borrowed>>
1413 : public impl::EncodeBase<
1414 Codec<borrowable::message::server::Statistics<Borrowed>>> {
1415 template <class Accumulator>
1416 constexpr auto accumulate_fields(Accumulator &&accu) const {
1417 namespace bw = borrowable::wire;
1418
1419 return accu.step(bw::String<Borrowed>(v_.stats())).result();
1420 }
1421
1422 public:
1423 using value_type = borrowable::message::server::Statistics<Borrowed>;
1425
1426 friend __base;
1427
1429 : __base(caps), v_{std::move(v)} {}
1430
1434
1435 namespace bw = borrowable::wire;
1436
1437 auto stats_res = accu.template step<bw::String<Borrowed>>();
1438
1439 if (!accu.result()) return stdx::unexpected(accu.result().error());
1440
1441 return std::make_pair(accu.result().value(),
1442 value_type(stats_res->value()));
1443 }
1444
1445 private:
1447};
1448
1449/**
1450 * CRTP base for client-side commands that are encoded as a single byte.
1451 */
1452template <class Base, class ValueType>
1454 : public impl::EncodeBase<CodecSimpleCommand<Base, ValueType>> {
1455 template <class Accumulator>
1456 constexpr auto accumulate_fields(Accumulator &&accu) const {
1457 namespace bw = borrowable::wire;
1458
1459 return accu.step(bw::FixedInt<1>(Base::cmd_byte())).result();
1460 }
1461
1462 public:
1464
1465 friend __base;
1466
1468
1469 static constexpr size_t max_size() noexcept { return 1; }
1470
1474
1475 namespace bw = borrowable::wire;
1476
1477 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
1478 if (!accu.result()) return stdx::unexpected(accu.result().error());
1479
1480 if (cmd_byte_res->value() != Base::cmd_byte()) {
1482 }
1483
1484 return std::make_pair(accu.result().value(), ValueType());
1485 }
1486};
1487
1488enum class CommandByte {
1489 Quit = 0x01,
1490 InitSchema,
1491 Query,
1492 ListFields,
1493 CreateDb,
1494 DropDb,
1495 Refresh,
1496 Shutdown,
1497 Statistics,
1499 Connect,
1501 Debug,
1502 Ping,
1503 Time,
1505 ChangeUser,
1506 BinlogDump,
1507 TableDump,
1508 ConnectOut,
1513 StmtClose,
1514 StmtReset,
1515 SetOption,
1516 StmtFetch,
1517 Deamon,
1520 Clone
1521};
1522
1523/**
1524 * codec for client's Quit command.
1525 */
1526template <>
1528 : public CodecSimpleCommand<Codec<borrowable::message::client::Quit>,
1529 borrowable::message::client::Quit> {
1530 public:
1533
1535
1536 constexpr static uint8_t cmd_byte() noexcept {
1537 return static_cast<uint8_t>(CommandByte::Quit);
1538 }
1539
1540 /**
1541 * capabilities the codec depends on.
1542 */
1544 return {};
1545 }
1546};
1547
1548/**
1549 * codec for client's ResetConnection command.
1550 */
1551template <>
1553 : public CodecSimpleCommand<
1554 Codec<borrowable::message::client::ResetConnection>,
1555 borrowable::message::client::ResetConnection> {
1556 public:
1559
1561
1562 constexpr static uint8_t cmd_byte() noexcept {
1563 return static_cast<uint8_t>(CommandByte::ResetConnection);
1564 }
1565
1566 /**
1567 * capabilities the codec depends on.
1568 */
1570 return {};
1571 }
1572};
1573
1574/**
1575 * codec for client's Ping command.
1576 */
1577template <>
1579 : public CodecSimpleCommand<Codec<borrowable::message::client::Ping>,
1580 borrowable::message::client::Ping> {
1581 public:
1584
1586
1587 constexpr static uint8_t cmd_byte() noexcept {
1588 return static_cast<uint8_t>(CommandByte::Ping);
1589 }
1590
1591 /**
1592 * capabilities the codec depends on.
1593 */
1595 return {};
1596 }
1597};
1598
1599/**
1600 * codec for client's Statistics command.
1601 */
1602template <>
1604 : public CodecSimpleCommand<Codec<borrowable::message::client::Statistics>,
1605 borrowable::message::client::Statistics> {
1606 public:
1609
1611
1612 constexpr static uint8_t cmd_byte() noexcept {
1613 return static_cast<uint8_t>(CommandByte::Statistics);
1614 }
1615
1616 /**
1617 * capabilities the codec depends on.
1618 */
1620 return {};
1621 }
1622};
1623
1624/**
1625 * codec for client's Debug command.
1626 */
1627template <>
1629 : public CodecSimpleCommand<Codec<borrowable::message::client::Debug>,
1630 borrowable::message::client::Debug> {
1631 public:
1634
1636
1637 constexpr static uint8_t cmd_byte() noexcept {
1638 return static_cast<uint8_t>(CommandByte::Debug);
1639 }
1640
1641 /**
1642 * capabilities the codec depends on.
1643 */
1645 return {};
1646 }
1647};
1648
1649/**
1650 * codec for client's InitSchema command.
1651 */
1652template <bool Borrowed>
1653class Codec<borrowable::message::client::InitSchema<Borrowed>>
1654 : public impl::EncodeBase<
1655 Codec<borrowable::message::client::InitSchema<Borrowed>>> {
1656 template <class Accumulator>
1657 constexpr auto accumulate_fields(Accumulator &&accu) const {
1658 namespace bw = borrowable::wire;
1659
1660 return accu.step(bw::FixedInt<1>(cmd_byte()))
1661 .step(bw::String<Borrowed>(v_.schema()))
1662 .result();
1663 }
1664
1665 public:
1668
1669 friend __base;
1670
1672 : __base(caps), v_{std::move(v)} {}
1673
1674 constexpr static uint8_t cmd_byte() noexcept {
1675 return static_cast<uint8_t>(CommandByte::InitSchema);
1676 }
1677
1678 /**
1679 * capabilities the codec depends on.
1680 */
1682 return {};
1683 }
1684
1688
1689 namespace bw = borrowable::wire;
1690
1691 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
1692 if (!accu.result()) return stdx::unexpected(accu.result().error());
1693
1694 if (cmd_byte_res->value() != cmd_byte()) {
1696 }
1697
1698 auto schema_res = accu.template step<bw::String<Borrowed>>();
1699 if (!accu.result()) return stdx::unexpected(accu.result().error());
1700
1701 return std::make_pair(accu.result().value(),
1702 value_type(schema_res->value()));
1703 }
1704
1705 private:
1707};
1708
1709/**
1710 * codec for client's Query command.
1711 */
1712template <bool Borrowed>
1713class Codec<borrowable::message::client::Query<Borrowed>>
1714 : public impl::EncodeBase<
1715 Codec<borrowable::message::client::Query<Borrowed>>> {
1716 template <class Accumulator>
1717 auto accumulate_fields(Accumulator &&accu) const {
1718 namespace bw = borrowable::wire;
1719
1720 accu.step(bw::FixedInt<1>(cmd_byte()));
1721
1722 auto caps = this->caps();
1723
1724 if (caps.test(capabilities::pos::query_attributes)) {
1725 uint64_t param_count = v_.values().size();
1726 accu.step(bw::VarInt(param_count)); // param_count
1727 accu.step(bw::VarInt(1)); // param_set_count: always 1
1728
1729 if (param_count > 0) {
1730 // mark all that are NULL in the nullbits
1731 //
1732 // - one bit per parameter to send
1733 // - if a parameter is NULL, the bit is set, and later no value is
1734 // added.
1735
1736 uint8_t null_bit_byte{};
1737 int bit_pos{};
1738
1739 for (auto const &param : v_.values()) {
1740 if (!param.value) null_bit_byte |= 1 << bit_pos;
1741
1742 if (++bit_pos > 7) {
1743 accu.step(bw::FixedInt<1>(null_bit_byte));
1744
1745 bit_pos = 0;
1746 null_bit_byte = 0;
1747 }
1748 }
1749
1750 if (bit_pos != 0) accu.step(bw::FixedInt<1>(null_bit_byte));
1751
1752 accu.step(bw::FixedInt<1>(1)); // new_param_bind_flag: always 1
1753
1754 for (const auto &param : v_.values()) {
1755 accu.step(bw::FixedInt<2>(param.type_and_flags))
1756 .step(bw::VarString<Borrowed>(param.name));
1757 }
1758
1759 for (const auto &param : v_.values()) {
1760 if (!param.value) continue;
1761
1762 auto type = param.type_and_flags & 0xff;
1763 switch (type) {
1764 case field_type::Bit:
1765 case field_type::Blob:
1768 case field_type::Set:
1769 case field_type::String:
1770 case field_type::Enum:
1775 case field_type::Json:
1778 accu.template step<bw::VarInt>(param.value->size());
1779 break;
1780 case field_type::Date:
1783 case field_type::Time:
1784 assert(param.value->size() <= 255);
1785
1786 accu.template step<bw::FixedInt<1>>(param.value->size());
1787
1788 break;
1790 case field_type::Double:
1791 assert(param.value->size() == 8);
1792
1793 break;
1794 case field_type::Long:
1795 case field_type::Int24:
1796 case field_type::Float:
1797 assert(param.value->size() == 4);
1798
1799 break;
1800 case field_type::Short:
1801 case field_type::Year:
1802 assert(param.value->size() == 2);
1803
1804 break;
1805 case field_type::Tiny:
1806 assert(param.value->size() == 1);
1807
1808 break;
1809 default:
1810 assert(true || "unknown field-type");
1811 break;
1812 }
1813 accu.template step<bw::String<Borrowed>>(*param.value);
1814 }
1815 }
1816 }
1817
1818 accu.step(bw::String<Borrowed>(v_.statement()));
1819 return accu.result();
1820 }
1821
1822 template <class Accu>
1824 Accu &accu, uint8_t type) {
1825 namespace bw = borrowable::wire;
1826
1827 switch (type) {
1828 case field_type::Bit:
1829 case field_type::Blob:
1832 case field_type::Set:
1833 case field_type::String:
1834 case field_type::Enum:
1839 case field_type::Json:
1841 case field_type::Geometry: {
1842 auto string_field_size_res = accu.template step<bw::VarInt>();
1843 if (!accu.result()) {
1844 return stdx::unexpected(accu.result().error());
1845 }
1846
1847 return string_field_size_res->value();
1848 }
1849 case field_type::Date:
1852 case field_type::Time: {
1853 auto time_field_size_res = accu.template step<bw::FixedInt<1>>();
1854 if (!accu.result()) {
1855 return stdx::unexpected(accu.result().error());
1856 }
1857
1858 return time_field_size_res->value();
1859 }
1861 case field_type::Double:
1862 return 8;
1863 case field_type::Long:
1864 case field_type::Int24:
1865 case field_type::Float:
1866 return 4;
1867 case field_type::Short:
1868 case field_type::Year:
1869 return 2;
1870 case field_type::Tiny:
1871 return 1;
1872 }
1873
1875 }
1876
1877 public:
1880
1881 friend __base;
1882
1884 : __base(caps), v_{std::move(v)} {}
1885
1886 constexpr static uint8_t cmd_byte() noexcept {
1887 return static_cast<uint8_t>(CommandByte::Query);
1888 }
1889
1890 /**
1891 * capabilities the codec depends on.
1892 */
1895 }
1896
1900
1901 namespace bw = borrowable::wire;
1902
1903 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
1904 if (!accu.result()) return stdx::unexpected(accu.result().error());
1905
1906 if (cmd_byte_res->value() != cmd_byte()) {
1908 }
1909
1910 std::vector<typename value_type::Param> params;
1911 if (caps.test(capabilities::pos::query_attributes)) {
1912 //
1913 auto param_count_res = accu.template step<bw::VarInt>();
1914 if (!param_count_res) return stdx::unexpected(param_count_res.error());
1915
1916 // currently always 1.
1917 auto param_set_count_res = accu.template step<bw::VarInt>();
1918 if (!param_set_count_res)
1919 return stdx::unexpected(param_set_count_res.error());
1920
1921 if (param_set_count_res->value() != 1) {
1923 }
1924
1925 const auto param_count = param_count_res->value();
1926 if (param_count > 0) {
1927 // bit-map
1928 const auto nullbits_res = accu.template step<bw::String<Borrowed>>(
1929 bytes_per_bits(param_count));
1930 if (!accu.result()) return stdx::unexpected(accu.result().error());
1931
1932 const auto nullbits = nullbits_res->value();
1933
1934 // always 1
1935 auto new_params_bound_res = accu.template step<bw::FixedInt<1>>();
1936 if (!accu.result()) return stdx::unexpected(accu.result().error());
1937
1938 auto new_params_bound = new_params_bound_res->value();
1939 if (new_params_bound != 1) {
1940 // Always 1, malformed packet error of not 1
1942 }
1943
1944 // redundant, but protocol-docs says:
1945 //
1946 // 'if new-params-bind-flag == 1'
1947 //
1948 // therefore keep it.
1949 if (new_params_bound == 1) {
1950 for (long n{}; n < param_count; ++n) {
1951 auto param_type_res = accu.template step<bw::FixedInt<2>>();
1952 if (!accu.result()) {
1953 return stdx::unexpected(accu.result().error());
1954 }
1955 auto param_name_res = accu.template step<bw::VarString<Borrowed>>();
1956 if (!accu.result()) {
1957 return stdx::unexpected(accu.result().error());
1958 }
1959
1960 params.emplace_back(param_type_res->value(),
1961 param_name_res->value(),
1962 std::optional<std::string>());
1963 }
1964 }
1965
1966 for (long n{}, nullbit_pos{}, nullbyte_pos{}; n < param_count;
1967 ++n, ++nullbit_pos) {
1968 if (nullbit_pos > 7) {
1969 ++nullbyte_pos;
1970 nullbit_pos = 0;
1971 }
1972
1973 if (!(nullbits[nullbyte_pos] & (1 << nullbit_pos))) {
1974 auto &param = params[n];
1975
1976 auto field_size_res =
1977 decode_field_size(accu, param.type_and_flags & 0xff);
1978 if (!field_size_res) {
1979 return stdx::unexpected(field_size_res.error());
1980 }
1981
1982 auto param_value_res = accu.template step<bw::String<Borrowed>>(
1983 field_size_res.value());
1984 if (!accu.result()) {
1985 return stdx::unexpected(accu.result().error());
1986 }
1987
1988 param.value = param_value_res->value();
1989 }
1990 }
1991 }
1992 }
1993
1994 auto statement_res = accu.template step<bw::String<Borrowed>>();
1995
1996 if (!accu.result()) return stdx::unexpected(accu.result().error());
1997
1998 return std::make_pair(
1999 accu.result().value(),
2000 value_type(statement_res->value(), std::move(params)));
2001 }
2002
2003 private:
2005};
2006
2007/**
2008 * codec for client::SendFile message.
2009 *
2010 * sent by client as response to server::SendFileRequest
2011 *
2012 * format:
2013 *
2014 * - String payload
2015 */
2016template <bool Borrowed>
2017class Codec<borrowable::message::client::SendFile<Borrowed>>
2018 : public impl::EncodeBase<
2019 Codec<borrowable::message::client::SendFile<Borrowed>>> {
2020 template <class Accumulator>
2021 constexpr auto accumulate_fields(Accumulator &&accu) const {
2022 namespace bw = borrowable::wire;
2023
2024 return accu.step(bw::String<Borrowed>(v_.payload())).result();
2025 }
2026
2027 public:
2030
2031 friend __base;
2032
2034 : __base(caps), v_{std::move(v)} {}
2035
2036 /**
2037 * capabilities the codec depends on.
2038 */
2040 return {};
2041 }
2042
2046
2047 namespace bw = borrowable::wire;
2048
2049 auto payload_res = accu.template step<bw::String<Borrowed>>();
2050 if (!accu.result()) return stdx::unexpected(accu.result().error());
2051
2052 return std::make_pair(accu.result().value(),
2053 value_type(payload_res->value()));
2054 }
2055
2056 private:
2058};
2059
2060/**
2061 * codec for client's ListFields command.
2062 */
2063template <bool Borrowed>
2064class Codec<borrowable::message::client::ListFields<Borrowed>>
2065 : public impl::EncodeBase<
2066 Codec<borrowable::message::client::ListFields<Borrowed>>> {
2067 template <class Accumulator>
2068 constexpr auto accumulate_fields(Accumulator &&accu) const {
2069 namespace bw = borrowable::wire;
2070
2071 return accu.step(bw::FixedInt<1>(cmd_byte()))
2072 .step(bw::NulTermString<Borrowed>(v_.table_name()))
2073 .step(bw::String<Borrowed>(v_.wildcard()))
2074 .result();
2075 }
2076
2077 public:
2080
2081 friend __base;
2082
2084 : __base(caps), v_{std::move(v)} {}
2085
2086 constexpr static uint8_t cmd_byte() noexcept {
2087 return static_cast<uint8_t>(CommandByte::ListFields);
2088 }
2089
2090 /**
2091 * capabilities the codec depends on.
2092 */
2094 return {};
2095 }
2096
2100
2101 namespace bw = borrowable::wire;
2102
2103 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
2104 if (!accu.result()) return stdx::unexpected(accu.result().error());
2105
2106 if (cmd_byte_res->value() != cmd_byte()) {
2108 }
2109
2110 auto table_name_res = accu.template step<bw::NulTermString<Borrowed>>();
2111 auto wildcard_res = accu.template step<bw::String<Borrowed>>();
2112 if (!accu.result()) return stdx::unexpected(accu.result().error());
2113
2114 return std::make_pair(
2115 accu.result().value(),
2116 value_type(table_name_res->value(), wildcard_res->value()));
2117 }
2118
2119 private:
2121};
2122
2123/**
2124 * codec for client's Reload command.
2125 */
2126template <>
2128 : public impl::EncodeBase<Codec<borrowable::message::client::Reload>> {
2129 template <class Accumulator>
2130 constexpr auto accumulate_fields(Accumulator &&accu) const {
2131 namespace bw = borrowable::wire;
2132
2133 return accu.step(bw::FixedInt<1>(cmd_byte()))
2134 .step(bw::FixedInt<1>(v_.cmds().to_ulong()))
2135 .result();
2136 }
2137
2138 public:
2141
2142 friend __base;
2143
2145 : __base(caps), v_{std::move(v)} {}
2146
2147 constexpr static uint8_t cmd_byte() noexcept {
2148 return static_cast<uint8_t>(CommandByte::Refresh);
2149 }
2150
2151 /**
2152 * capabilities the codec depends on.
2153 */
2155 return {};
2156 }
2157
2161
2162 namespace bw = borrowable::wire;
2163
2164 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
2165 if (!accu.result()) return stdx::unexpected(accu.result().error());
2166
2167 if (cmd_byte_res->value() != cmd_byte()) {
2169 }
2170
2171 auto cmds_res = accu.template step<bw::FixedInt<1>>();
2172 if (!accu.result()) return stdx::unexpected(accu.result().error());
2173
2174 return std::make_pair(accu.result().value(), value_type(cmds_res->value()));
2175 }
2176
2177 private:
2179};
2180
2181/**
2182 * codec for client's Kill command.
2183 *
2184 * format:
2185 *
2186 * - FixedInt<1> == 0x0c, ProcessKill
2187 * - FixedInt<4> id
2188 */
2189template <>
2191 : public impl::EncodeBase<Codec<borrowable::message::client::Kill>> {
2192 template <class Accumulator>
2193 constexpr auto accumulate_fields(Accumulator &&accu) const {
2194 namespace bw = borrowable::wire;
2195
2196 return accu.step(bw::FixedInt<1>(cmd_byte()))
2197 .step(bw::FixedInt<4>(v_.connection_id()))
2198 .result();
2199 }
2200
2201 public:
2204
2205 friend __base;
2206
2208 : __base(caps), v_{std::move(v)} {}
2209
2210 constexpr static uint8_t cmd_byte() noexcept {
2211 return static_cast<uint8_t>(CommandByte::ProcessKill);
2212 }
2213
2214 /**
2215 * capabilities the codec depends on.
2216 */
2218 return {};
2219 }
2220
2224
2225 namespace bw = borrowable::wire;
2226
2227 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
2228 if (!accu.result()) return stdx::unexpected(accu.result().error());
2229
2230 if (cmd_byte_res->value() != cmd_byte()) {
2232 }
2233
2234 auto connection_id_res = accu.template step<bw::FixedInt<4>>();
2235 if (!accu.result()) return stdx::unexpected(accu.result().error());
2236
2237 return std::make_pair(accu.result().value(),
2238 value_type(connection_id_res->value()));
2239 }
2240
2241 private:
2243};
2244
2245/**
2246 * codec for client's Prepared Statement command.
2247 */
2248template <bool Borrowed>
2249class Codec<borrowable::message::client::StmtPrepare<Borrowed>>
2250 : public impl::EncodeBase<
2251 Codec<borrowable::message::client::StmtPrepare<Borrowed>>> {
2252 template <class Accumulator>
2253 constexpr auto accumulate_fields(Accumulator &&accu) const {
2254 namespace bw = borrowable::wire;
2255
2256 return accu.step(bw::FixedInt<1>(cmd_byte()))
2257 .step(bw::String<Borrowed>(v_.statement()))
2258 .result();
2259 }
2260
2261 public:
2264
2265 friend __base;
2266
2268 : __base(caps), v_{std::move(v)} {}
2269
2270 constexpr static uint8_t cmd_byte() noexcept {
2271 return static_cast<uint8_t>(CommandByte::StmtPrepare);
2272 }
2273
2274 /**
2275 * capabilities the codec depends on.
2276 */
2278 return {};
2279 }
2280
2284
2285 namespace bw = borrowable::wire;
2286
2287 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
2288 if (!accu.result()) return stdx::unexpected(accu.result().error());
2289
2290 if (cmd_byte_res->value() != cmd_byte()) {
2292 }
2293
2294 auto statement_res = accu.template step<bw::String<Borrowed>>();
2295 if (!accu.result()) return stdx::unexpected(accu.result().error());
2296
2297 return std::make_pair(accu.result().value(),
2298 value_type(statement_res->value()));
2299 }
2300
2301 private:
2303};
2304
2305/**
2306 * codec for client's Execute Statement command.
2307 */
2308template <bool Borrowed>
2309class Codec<borrowable::message::client::StmtExecute<Borrowed>>
2310 : public impl::EncodeBase<
2311 Codec<borrowable::message::client::StmtExecute<Borrowed>>> {
2312 template <class Accumulator>
2313 auto accumulate_fields(Accumulator &&accu) const {
2314 namespace bw = borrowable::wire;
2315
2316 auto caps = this->caps();
2317
2318 accu.step(bw::FixedInt<1>(cmd_byte()))
2319 .step(bw::FixedInt<4>(v_.statement_id()))
2320 .step(bw::FixedInt<1>(v_.flags().to_ullong()))
2321 .step(bw::FixedInt<4>(v_.iteration_count()));
2322
2323 // num-params from the StmtPrepareOk
2324 auto num_params = v_.values().size();
2325
2326 const bool supports_query_attributes =
2328
2329 if (supports_query_attributes &&
2330 v_.flags().test(cursor::pos::param_count_available)) {
2331 accu.step(bw::VarInt(num_params));
2332 }
2333
2334 if (num_params == 0) return accu.result();
2335
2336 // mark all that are NULL in the nullbits
2337 //
2338 // - one bit per parameter to send
2339 // - if a parameter is NULL, the bit is set, and later no value is added.
2340 uint8_t null_bit_byte{};
2341 int bit_pos{};
2342
2343 for (auto const &param : v_.values()) {
2344 if (!param.has_value()) null_bit_byte |= 1 << bit_pos;
2345
2346 if (++bit_pos > 7) {
2347 accu.step(bw::FixedInt<1>(null_bit_byte));
2348
2349 bit_pos = 0;
2350 null_bit_byte = 0;
2351 }
2352 }
2353
2354 if (bit_pos != 0) accu.step(bw::FixedInt<1>(null_bit_byte));
2355
2356 accu.step(bw::FixedInt<1>(v_.new_params_bound()));
2357
2358 if (v_.new_params_bound()) {
2359 for (const auto &param_def : v_.types()) {
2360 accu.step(bw::FixedInt<2>(param_def.type_and_flags));
2361
2362 if (supports_query_attributes) {
2363 accu.step(borrowed::wire::VarString(param_def.name));
2364 }
2365 }
2366 }
2367
2368 for (auto [n, v] : stdx::views::enumerate(v_.values())) {
2369 // add all the values that aren't NULL
2370 if (!v.has_value()) continue;
2371
2372 // write length of the type is a variable length
2373 switch (v_.types()[n].type_and_flags & 0xff) {
2374 case field_type::Bit:
2375 case field_type::Blob:
2378 case field_type::Set:
2379 case field_type::String:
2380 case field_type::Enum:
2387 accu.step(bw::VarInt(v->size()));
2388 break;
2389 case field_type::Date:
2392 case field_type::Time:
2393 accu.step(bw::FixedInt<1>(v->size()));
2394 break;
2396 case field_type::Double:
2397 case field_type::Long:
2398 case field_type::Int24:
2399 case field_type::Float:
2400 case field_type::Short:
2401 case field_type::Year:
2402 case field_type::Tiny:
2403 // fixed size
2404 break;
2405 default:
2406 assert(false || "Unknown Type");
2407 }
2408 accu.step(borrowed::wire::String(v.value()));
2409 }
2410
2411 return accu.result();
2412 }
2413
2414 public:
2417
2418 friend __base;
2419
2421 : __base(caps), v_{std::move(val)} {}
2422
2423 constexpr static uint8_t cmd_byte() noexcept {
2424 return static_cast<uint8_t>(CommandByte::StmtExecute);
2425 }
2426
2427 /**
2428 * capabilities the codec depends on.
2429 */
2432 }
2433
2434 /**
2435 * decode a buffer into a message::client::StmtExecute.
2436 *
2437 * @param buffer a buffer
2438 * @param caps protocol capabilities
2439 * @param metadata_lookup callable that expects a 'uint32_t statement_id'
2440 * that returns a result that's convertible to
2441 * 'stdx::expected<std::vector<ParamDef>, std::error_code>' representing the
2442 * parameter-definitions of the prepared statement
2443 *
2444 * decoding a StmtExecute message requires the parameter-definitions of the
2445 * prepared statement. The metadata_lookup function may be called to get
2446 * the parameter-definitions for the statement-id.
2447 *
2448 * The function may return a parameter-definitions directly
2449 *
2450 * \code
2451 * StmtExecute::decode(
2452 * buffers,
2453 * capabilities::protocol_41,
2454 * [](uint32_t stmt_id) { return std::vector<ParamDef>{}; });
2455 * \endcode
2456 *
2457 * ... or a stdx::expected<std::vector<ParamDef>, std::error_code> if it wants
2458 * to signal that a statement-id wasn't found
2459 *
2460 * \code
2461 * StmtExecute::decode(
2462 * buffers,
2463 * capabilities::protocol_41,
2464 * [](uint32_t stmt_id) ->
2465 * stdx::expected<std::vector<ParamDef>, std::error_code> {
2466 * bool found{true};
2467 *
2468 * if (found) {
2469 * return {};
2470 * } else {
2471 * return stdx::unexpected(make_error_code(
2472 * codec_errc::statement_id_not_found));
2473 * }
2474 * });
2475 * \endcode
2476 */
2477 template <class Func>
2480 Func &&metadata_lookup) {
2482
2483 namespace bw = borrowable::wire;
2484
2485 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
2486 if (!accu.result()) return stdx::unexpected(accu.result().error());
2487
2488 if (cmd_byte_res->value() != cmd_byte()) {
2490 }
2491
2492 auto statement_id_res = accu.template step<bw::FixedInt<4>>();
2493 auto flags_res = accu.template step<bw::FixedInt<1>>();
2494 auto iteration_count_res = accu.template step<bw::FixedInt<4>>();
2495
2496 if (!accu.result()) return stdx::unexpected(accu.result().error());
2497
2499
2500 const bool supports_query_attributes =
2502
2504 metadata_res = metadata_lookup(statement_id_res->value());
2505 if (!metadata_res) {
2506 return stdx::unexpected(
2508 }
2509
2510 size_t param_count = metadata_res->size();
2511
2512 if (supports_query_attributes &&
2513 (flags_res->value() & param_count_available) != 0) {
2514 auto param_count_res = accu.template step<bw::VarInt>();
2515 if (!accu.result()) {
2516 return stdx::unexpected(accu.result().error());
2517 }
2518
2519 if (static_cast<uint64_t>(param_count_res->value()) < param_count) {
2520 // can the param-count shrink?
2522 }
2523
2524 param_count = param_count_res->value();
2525 }
2526
2527 if (param_count == 0) {
2528 return std::make_pair(
2529 accu.result().value(),
2530 value_type(statement_id_res->value(), flags_res->value(),
2531 iteration_count_res->value(), false, {}, {}));
2532 }
2533
2534 auto nullbits_res =
2535 accu.template step<bw::String<Borrowed>>(bytes_per_bits(param_count));
2536 if (!accu.result()) return stdx::unexpected(accu.result().error());
2537
2538 auto new_params_bound_res = accu.template step<bw::FixedInt<1>>();
2539 if (!accu.result()) return stdx::unexpected(accu.result().error());
2540
2541 std::vector<typename value_type::ParamDef> types;
2542
2543 auto new_params_bound = new_params_bound_res->value();
2544 if (new_params_bound == 0) {
2545 // no new params, use the last known params.
2546 types = *metadata_res;
2547 } else if (new_params_bound == 1) {
2548 // check that there is at least enough data for the types (a FixedInt<2>)
2549 // before reserving memory.
2550 if (param_count >= buffer.size() / 2) {
2552 }
2553
2554 types.reserve(param_count);
2555
2556 for (size_t n{}; n < param_count; ++n) {
2557 auto type_res = accu.template step<bw::FixedInt<2>>();
2558 if (!accu.result()) return stdx::unexpected(accu.result().error());
2559
2560 if (supports_query_attributes) {
2561 auto name_res = accu.template step<bw::VarString<Borrowed>>();
2562 if (!accu.result()) {
2563 return stdx::unexpected(accu.result().error());
2564 }
2565 types.emplace_back(type_res->value(), name_res->value());
2566 } else {
2567 types.emplace_back(type_res->value(), "");
2568 }
2569 }
2570 } else {
2572 }
2573
2574 if (param_count != types.size()) {
2575 // param-count and available types doesn't match.
2577 }
2578
2579 std::vector<std::optional<typename value_type::string_type>> values;
2580 values.reserve(param_count);
2581
2582 const auto nullbits = nullbits_res->value();
2583 for (size_t n{}, bit_pos{}, byte_pos{}; n < param_count; ++n, ++bit_pos) {
2584 if (bit_pos > 7) {
2585 bit_pos = 0;
2586 ++byte_pos;
2587 }
2588
2589 // if the data was sent via COM_STMT_SEND_LONG_DATA, there will be no data
2590 // for
2591 const auto param_already_sent =
2592 n < metadata_res->size() ? (*metadata_res)[n].param_already_sent
2593 : false;
2594
2595 if (param_already_sent) {
2596 values.emplace_back(""); // empty
2597 } else if (!(nullbits[byte_pos] & (1 << bit_pos))) {
2599 stdx::unexpected(make_error_code(std::errc::invalid_argument)));
2600 switch (types[n].type_and_flags & 0xff) {
2601 case field_type::Bit:
2602 case field_type::Blob:
2605 case field_type::Set:
2606 case field_type::String:
2607 case field_type::Enum:
2613 case field_type::Geometry: {
2614 auto string_field_size_res = accu.template step<bw::VarInt>();
2615 if (!accu.result()) {
2616 return stdx::unexpected(accu.result().error());
2617 }
2618
2619 field_size_res = string_field_size_res->value();
2620 } break;
2621 case field_type::Date:
2624 case field_type::Time: {
2625 auto time_field_size_res = accu.template step<bw::FixedInt<1>>();
2626 if (!accu.result()) {
2627 return stdx::unexpected(accu.result().error());
2628 }
2629
2630 field_size_res = time_field_size_res->value();
2631 } break;
2633 case field_type::Double:
2634 field_size_res = 8;
2635 break;
2636 case field_type::Long:
2637 case field_type::Int24:
2638 case field_type::Float:
2639 field_size_res = 4;
2640 break;
2641 case field_type::Short:
2642 case field_type::Year:
2643 field_size_res = 2;
2644 break;
2645 case field_type::Tiny:
2646 field_size_res = 1;
2647 break;
2648 }
2649
2650 if (!field_size_res) {
2651 return stdx::unexpected(
2653 }
2654
2655 auto value_res =
2656 accu.template step<bw::String<Borrowed>>(field_size_res.value());
2657 if (!accu.result()) {
2658 return stdx::unexpected(accu.result().error());
2659 }
2660
2661 values.push_back(value_res->value());
2662 } else {
2663 // NULL
2664 values.emplace_back(std::nullopt);
2665 }
2666 }
2667
2668 if (!accu.result()) return stdx::unexpected(accu.result().error());
2669
2670 return std::make_pair(
2671 accu.result().value(),
2672 value_type(statement_id_res->value(), flags_res->value(),
2673 iteration_count_res->value(), new_params_bound_res->value(),
2674 types, values));
2675 }
2676
2677 private:
2679};
2680
2681/**
2682 * codec for client's append data Statement command.
2683 */
2684template <bool Borrowed>
2686 : public impl::EncodeBase<
2687 Codec<borrowable::message::client::StmtParamAppendData<Borrowed>>> {
2688 template <class Accumulator>
2689 constexpr auto accumulate_fields(Accumulator &&accu) const {
2690 namespace bw = borrowable::wire;
2691
2692 return accu.step(bw::FixedInt<1>(cmd_byte()))
2693 .step(bw::FixedInt<4>(v_.statement_id()))
2694 .step(bw::FixedInt<2>(v_.param_id()))
2695 .step(bw::String<Borrowed>(v_.data()))
2696 .result();
2697 }
2698
2699 public:
2702
2703 friend __base;
2704
2706 : __base(caps), v_{std::move(v)} {}
2707
2708 constexpr static uint8_t cmd_byte() noexcept {
2709 return static_cast<uint8_t>(CommandByte::StmtSendLongData);
2710 }
2711
2712 /**
2713 * capabilities the codec depends on.
2714 */
2716 return {};
2717 }
2718
2722
2723 namespace bw = borrowable::wire;
2724
2725 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
2726 if (!accu.result()) return stdx::unexpected(accu.result().error());
2727
2728 if (cmd_byte_res->value() != cmd_byte()) {
2730 }
2731
2732 auto statement_id_res = accu.template step<bw::FixedInt<4>>();
2733 auto param_id_res = accu.template step<bw::FixedInt<2>>();
2734 auto data_res = accu.template step<bw::String<Borrowed>>();
2735 if (!accu.result()) return stdx::unexpected(accu.result().error());
2736
2737 return std::make_pair(accu.result().value(),
2738 value_type(statement_id_res->value(),
2739 param_id_res->value(), data_res->value()));
2740 }
2741
2742 private:
2744};
2745
2746/**
2747 * codec for client's Close Statement command.
2748 */
2749template <>
2751 : public impl::EncodeBase<Codec<borrowable::message::client::StmtClose>> {
2752 template <class Accumulator>
2753 constexpr auto accumulate_fields(Accumulator &&accu) const {
2754 namespace bw = borrowable::wire;
2755
2756 return accu.step(bw::FixedInt<1>(cmd_byte()))
2757 .step(bw::FixedInt<4>(v_.statement_id()))
2758 .result();
2759 }
2760
2761 public:
2764
2765 friend __base;
2766
2768 : __base(caps), v_{std::move(v)} {}
2769
2770 constexpr static uint8_t cmd_byte() noexcept {
2771 return static_cast<uint8_t>(CommandByte::StmtClose);
2772 }
2773
2774 /**
2775 * capabilities the codec depends on.
2776 */
2778 return {};
2779 }
2780
2784
2785 namespace bw = borrowable::wire;
2786
2787 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
2788 if (!accu.result()) return stdx::unexpected(accu.result().error());
2789
2790 if (cmd_byte_res->value() != cmd_byte()) {
2792 }
2793
2794 auto statement_id_res = accu.template step<bw::FixedInt<4>>();
2795 if (!accu.result()) return stdx::unexpected(accu.result().error());
2796
2797 return std::make_pair(accu.result().value(),
2798 value_type(statement_id_res->value()));
2799 }
2800
2801 private:
2803};
2804
2805/**
2806 * codec for client's Reset Statement command.
2807 */
2808template <>
2810 : public impl::EncodeBase<Codec<borrowable::message::client::StmtReset>> {
2811 template <class Accumulator>
2812 constexpr auto accumulate_fields(Accumulator &&accu) const {
2813 namespace bw = borrowable::wire;
2814
2815 return accu.step(bw::FixedInt<1>(cmd_byte()))
2816 .step(bw::FixedInt<4>(v_.statement_id()))
2817 .result();
2818 }
2819
2820 public:
2823
2824 friend __base;
2825
2827 : __base(caps), v_{std::move(v)} {}
2828
2829 constexpr static uint8_t cmd_byte() noexcept {
2830 return static_cast<uint8_t>(CommandByte::StmtReset);
2831 }
2832
2833 /**
2834 * capabilities the codec depends on.
2835 */
2837 return {};
2838 }
2839
2843
2844 namespace bw = borrowable::wire;
2845
2846 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
2847 if (!accu.result()) return stdx::unexpected(accu.result().error());
2848
2849 if (cmd_byte_res->value() != cmd_byte()) {
2851 }
2852
2853 auto statement_id_res = accu.template step<bw::FixedInt<4>>();
2854 if (!accu.result()) return stdx::unexpected(accu.result().error());
2855
2856 return std::make_pair(accu.result().value(),
2857 value_type(statement_id_res->value()));
2858 }
2859
2860 private:
2862};
2863
2864/**
2865 * codec for client's SetOption command.
2866 */
2867template <>
2869 : public impl::EncodeBase<Codec<borrowable::message::client::SetOption>> {
2870 template <class Accumulator>
2871 constexpr auto accumulate_fields(Accumulator &&accu) const {
2872 namespace bw = borrowable::wire;
2873
2874 return accu.step(bw::FixedInt<1>(cmd_byte()))
2875 .step(bw::FixedInt<2>(v_.option()))
2876 .result();
2877 }
2878
2879 public:
2882
2883 friend __base;
2884
2886 : __base(caps), v_{std::move(v)} {}
2887
2888 constexpr static uint8_t cmd_byte() noexcept {
2889 return static_cast<uint8_t>(CommandByte::SetOption);
2890 }
2891
2892 /**
2893 * capabilities the codec depends on.
2894 */
2896 return {};
2897 }
2898
2902
2903 namespace bw = borrowable::wire;
2904
2905 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
2906 if (!accu.result()) return stdx::unexpected(accu.result().error());
2907
2908 if (cmd_byte_res->value() != cmd_byte()) {
2910 }
2911
2912 auto option_res = accu.template step<bw::FixedInt<2>>();
2913 if (!accu.result()) return stdx::unexpected(accu.result().error());
2914
2915 return std::make_pair(accu.result().value(),
2916 value_type(option_res->value()));
2917 }
2918
2919 private:
2921};
2922
2923/**
2924 * codec for client's Fetch Cursor command.
2925 */
2926template <>
2928 : public impl::EncodeBase<Codec<borrowable::message::client::StmtFetch>> {
2929 template <class Accumulator>
2930 constexpr auto accumulate_fields(Accumulator &&accu) const {
2931 namespace bw = borrowable::wire;
2932
2933 return accu.step(bw::FixedInt<1>(cmd_byte()))
2934 .step(bw::FixedInt<4>(v_.statement_id()))
2935 .step(bw::FixedInt<4>(v_.row_count()))
2936 .result();
2937 }
2938
2939 public:
2942
2943 friend __base;
2944
2946 : __base(caps), v_{std::move(v)} {}
2947
2948 constexpr static uint8_t cmd_byte() noexcept {
2949 return static_cast<uint8_t>(CommandByte::StmtFetch);
2950 }
2951
2952 /**
2953 * capabilities the codec depends on.
2954 */
2956 return {};
2957 }
2958
2962
2963 namespace bw = borrowable::wire;
2964
2965 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
2966 if (!accu.result()) return stdx::unexpected(accu.result().error());
2967
2968 if (cmd_byte_res->value() != cmd_byte()) {
2970 }
2971
2972 auto statement_id_res = accu.template step<bw::FixedInt<4>>();
2973 auto row_count_res = accu.template step<bw::FixedInt<4>>();
2974 if (!accu.result()) return stdx::unexpected(accu.result().error());
2975
2976 return std::make_pair(
2977 accu.result().value(),
2978 value_type(statement_id_res->value(), row_count_res->value()));
2979 }
2980
2981 private:
2983};
2984
2985/**
2986 * codec for client side greeting message.
2987 *
2988 *
2989 * in 3.21 ... 4.0:
2990 *
2991 * FixedInt<2> capabilities [protocol_41 not set]
2992 * FixedInt<3> max-allowed-packet
2993 * NulTermString username
2994 * NulTermString auth-method-data
2995 *
2996 * [if not connect_with_schema, there may be no trailing Nul-byte]
2997 *
2998 * if connect_with_schema {
2999 * String schema
3000 * }
3001 *
3002 * the auth-method is "old_password" if "protocol_version == 10 &&
3003 * (capabilities & long_password)", it is "older_password" otherwise
3004 *
3005 * FixedInt<2> capabilities_lo [protocol_41 set]
3006 * FixedInt<2> capabilities_hi
3007 * FixedInt<4> max_allowed-packet
3008 * ...
3009 *
3010 * The capabilities that are part of the message are the client's capabilities
3011 * (which may announce more than what the server supports). The codec
3012 * uses the capabilities that are shared between client and server to decide
3013 * which parts and how they are understood, though.
3014 *
3015 * checked capabilities:
3016 * - protocol_41
3017 * - ssl
3018 * - client_auth_method_data_varint
3019 * - secure_connection
3020 * - connect_with_schema
3021 * - plugin_auth
3022 * - connect_attributes
3023 */
3024template <bool Borrowed>
3025class Codec<borrowable::message::client::Greeting<Borrowed>>
3026 : public impl::EncodeBase<
3027 Codec<borrowable::message::client::Greeting<Borrowed>>> {
3028 template <class Accumulator>
3029 constexpr auto accumulate_fields(Accumulator &&accu) const {
3030 namespace bw = borrowable::wire;
3031
3032 const auto shared_caps = v_.capabilities() & this->caps();
3033
3035 accu.step(bw::FixedInt<4>(v_.capabilities().to_ulong()))
3036 .step(bw::FixedInt<4>(v_.max_packet_size()))
3037 .step(bw::FixedInt<1>(v_.collation()))
3038 .step(bw::String<Borrowed>(std::string(23, '\0')));
3039 if (!(shared_caps[classic_protocol::capabilities::pos::ssl] &&
3040 v_.username().empty())) {
3041 // the username is empty and SSL is set, this is a short SSL-greeting
3042 // packet
3043 accu.step(bw::NulTermString<Borrowed>(v_.username()));
3044
3045 if (shared_caps[classic_protocol::capabilities::pos::
3047 accu.step(bw::VarString<Borrowed>(v_.auth_method_data()));
3048 } else if (shared_caps[classic_protocol::capabilities::pos::
3050 accu.step(bw::FixedInt<1>(v_.auth_method_data().size()))
3051 .step(bw::String<Borrowed>(v_.auth_method_data()));
3052 } else {
3053 accu.step(bw::NulTermString<Borrowed>(v_.auth_method_data()));
3054 }
3055
3056 if (shared_caps
3058 accu.step(bw::NulTermString<Borrowed>(v_.schema()));
3059 }
3060
3061 if (!shared_caps
3063 // special handling for off-spec client/server implementations.
3064 //
3065 // 1. older clients may set ::plugin_auth, but
3066 // ::connection_attributes which means nothing follows the
3067 // "auth-method-name" field
3068 // 2. auth-method-name is empty, it MAY be skipped.
3070 !v_.auth_method_name().empty()) {
3071 accu.step(bw::NulTermString<Borrowed>(v_.auth_method_name()));
3072 }
3073 } else {
3075 accu.step(bw::NulTermString<Borrowed>(v_.auth_method_name()));
3076 }
3077
3078 accu.step(bw::VarString<Borrowed>(v_.attributes()));
3079 }
3080 }
3081 } else {
3082 accu.step(bw::FixedInt<2>(v_.capabilities().to_ulong()))
3083 .step(bw::FixedInt<3>(v_.max_packet_size()))
3084 .step(bw::NulTermString<Borrowed>(v_.username()));
3085 if (shared_caps
3087 accu.step(bw::NulTermString<Borrowed>(v_.auth_method_data()))
3088 .step(bw::String<Borrowed>(v_.schema()));
3089 } else {
3090 accu.step(bw::String<Borrowed>(v_.auth_method_data()));
3091 }
3092 }
3093
3094 return accu.result();
3095 }
3096
3097 public:
3100
3101 friend __base;
3102
3104 : __base(caps), v_{std::move(v)} {}
3105
3106 /**
3107 * capabilities the codec depends on.
3108 */
3113 }
3114
3118
3119 namespace bw = borrowable::wire;
3120
3121 auto capabilities_lo_res = accu.template step<bw::FixedInt<2>>();
3122 if (!capabilities_lo_res)
3123 return stdx::unexpected(capabilities_lo_res.error());
3124
3125 auto client_capabilities = classic_protocol::capabilities::value_type(
3126 capabilities_lo_res->value());
3127
3128 // decoding depends on the capabilities that both client and server have
3129 // in common
3130 auto shared_capabilities = caps & client_capabilities;
3131
3132 if (shared_capabilities[classic_protocol::capabilities::pos::protocol_41]) {
3133 // if protocol_41 is set in the capabilities, we expected 2 more bytes
3134 // of capabilities
3135 auto capabilities_hi_res = accu.template step<bw::FixedInt<2>>();
3136 if (!capabilities_hi_res)
3137 return stdx::unexpected(capabilities_hi_res.error());
3138
3139 client_capabilities |= classic_protocol::capabilities::value_type(
3140 capabilities_hi_res->value() << 16);
3141
3142 shared_capabilities = caps & client_capabilities;
3143
3144 auto max_packet_size_res = accu.template step<bw::FixedInt<4>>();
3145 auto collation_res = accu.template step<bw::FixedInt<1>>();
3146
3147 accu.template step<bw::String<Borrowed>>(23); // skip 23 bytes
3148
3149 auto last_accu_res = accu.result();
3150
3151 auto username_res = accu.template step<bw::NulTermString<Borrowed>>();
3152 if (!accu.result()) {
3153 // if there isn't enough data for the nul-term-string, but we had the
3154 // 23-bytes ...
3155 if (last_accu_res &&
3156 shared_capabilities[classic_protocol::capabilities::pos::ssl]) {
3157 return std::make_pair(
3158 last_accu_res.value(),
3159 value_type(client_capabilities, max_packet_size_res->value(),
3160 collation_res->value(), {}, {}, {}, {}, {}));
3161 }
3162
3163 return stdx::unexpected(accu.result().error());
3164 }
3165
3166 // auth-method-data is either
3167 //
3168 // - varint length
3169 // - fixed-int-1 length
3170 // - null-term-string
3171 stdx::expected<bw::String<Borrowed>, std::error_code>
3172 auth_method_data_res;
3173 if (shared_capabilities[classic_protocol::capabilities::pos::
3175 auto res = accu.template step<bw::VarString<Borrowed>>();
3176 if (!res) return stdx::unexpected(res.error());
3177
3178 auth_method_data_res = bw::String<Borrowed>(res->value());
3179 } else if (shared_capabilities
3181 auto auth_method_data_len_res = accu.template step<bw::FixedInt<1>>();
3182 if (!auth_method_data_len_res)
3183 return stdx::unexpected(auth_method_data_len_res.error());
3184 auto auth_method_data_len = auth_method_data_len_res->value();
3185
3186 auto res =
3187 accu.template step<bw::String<Borrowed>>(auth_method_data_len);
3188 if (!res) return stdx::unexpected(res.error());
3189
3190 auth_method_data_res = bw::String<Borrowed>(res->value());
3191 } else {
3192 auto res = accu.template step<bw::NulTermString<Borrowed>>();
3193 if (!res) return stdx::unexpected(res.error());
3194
3195 auth_method_data_res = bw::String<Borrowed>(res->value());
3196 }
3197
3198 stdx::expected<bw::NulTermString<Borrowed>, std::error_code> schema_res;
3199 if (shared_capabilities
3201 schema_res = accu.template step<bw::NulTermString<Borrowed>>();
3202 }
3203 if (!schema_res) return stdx::unexpected(schema_res.error());
3204
3206 auth_method_res;
3207 if (shared_capabilities
3209 if (net::buffer_size(buffer) == accu.result().value()) {
3210 // even with plugin_auth set, the server is fine, if no
3211 // auth_method_name is sent.
3212 auth_method_res = bw::NulTermString<Borrowed>{};
3213 } else {
3214 auth_method_res = accu.template step<bw::NulTermString<Borrowed>>();
3215 }
3216 }
3217 if (!auth_method_res) return stdx::unexpected(auth_method_res.error());
3218
3219 stdx::expected<bw::VarString<Borrowed>, std::error_code> attributes_res;
3220 if (shared_capabilities
3222 attributes_res = accu.template step<bw::VarString<Borrowed>>();
3223 }
3224
3225 if (!accu.result()) return stdx::unexpected(accu.result().error());
3226
3227 return std::make_pair(
3228 accu.result().value(),
3229 value_type(client_capabilities, max_packet_size_res->value(),
3230 collation_res->value(), username_res->value(),
3231 auth_method_data_res->value(), schema_res->value(),
3232 auth_method_res->value(), attributes_res->value()));
3233
3234 } else {
3235 auto max_packet_size_res = accu.template step<bw::FixedInt<3>>();
3236
3237 auto username_res = accu.template step<bw::NulTermString<Borrowed>>();
3238
3239 stdx::expected<bw::String<Borrowed>, std::error_code>
3240 auth_method_data_res;
3241 stdx::expected<bw::String<Borrowed>, std::error_code> schema_res;
3242
3243 if (shared_capabilities
3245 auto res = accu.template step<bw::NulTermString<Borrowed>>();
3246 if (!res) return stdx::unexpected(res.error());
3247
3248 // auth_method_data is a wire::String, move it over
3249 auth_method_data_res = bw::String<Borrowed>(res->value());
3250
3251 schema_res = accu.template step<bw::String<Borrowed>>();
3252 } else {
3253 auth_method_data_res = accu.template step<bw::String<Borrowed>>();
3254 }
3255
3256 if (!accu.result()) return stdx::unexpected(accu.result().error());
3257
3258 // idea: benchmark in-place constructor where all parameters are passed
3259 // down to the lowest level.
3260 //
3261 // It should involve less copy-construction.
3262 //
3263 // - stdx::in_place is for in-place construction of stdx::expected's
3264 // value
3265 // - std::piecewise_construct for the parts of the std::pair that is
3266 // returned as value of stdx::expected
3267 //
3268 // return {stdx::in_place, std::piecewise_construct,
3269 // std::forward_as_tuple(accu.result().value()),
3270 // std::forward_as_tuple(capabilities,
3271 // max_packet_size_res->value(),
3272 // 0x00, username_res->value(),
3273 // auth_method_data_res->value(),
3274 // schema_res->value(), {},
3275 // {})};
3276 return std::make_pair(
3277 accu.result().value(),
3278 value_type(client_capabilities, max_packet_size_res->value(), 0x00,
3279 username_res->value(), auth_method_data_res->value(),
3280 schema_res->value(), {}, {}));
3281 }
3282 }
3283
3284 private:
3286};
3287
3288/**
3289 * codec for client::AuthMethodData message.
3290 *
3291 * format:
3292 *
3293 * - String auth_method_data
3294 *
3295 * sent after server::AuthMethodData or server::AuthMethodContinue
3296 */
3297template <bool Borrowed>
3298class Codec<borrowable::message::client::AuthMethodData<Borrowed>>
3299 : public impl::EncodeBase<
3300 Codec<borrowable::message::client::AuthMethodData<Borrowed>>> {
3301 template <class Accumulator>
3302 constexpr auto accumulate_fields(Accumulator &&accu) const {
3303 namespace bw = borrowable::wire;
3304
3305 return accu.step(bw::String<Borrowed>(v_.auth_method_data())).result();
3306 }
3307
3308 public:
3311
3312 friend __base;
3313
3315 : __base(caps), v_{std::move(v)} {}
3316
3317 /**
3318 * capabilities the codec depends on.
3319 */
3321 return {};
3322 }
3323
3327
3328 namespace bw = borrowable::wire;
3329
3330 auto auth_method_data_res = accu.template step<bw::String<Borrowed>>();
3331
3332 if (!accu.result()) return stdx::unexpected(accu.result().error());
3333
3334 return std::make_pair(accu.result().value(),
3335 value_type(auth_method_data_res->value()));
3336 }
3337
3338 private:
3340};
3341
3342/**
3343 * codec for client side change-user message.
3344 *
3345 * checked capabilities:
3346 * - protocol_41
3347 * - secure_connection
3348 * - plugin_auth
3349 * - connect_attributes
3350 */
3351template <bool Borrowed>
3352class Codec<borrowable::message::client::ChangeUser<Borrowed>>
3353 : public impl::EncodeBase<
3354 Codec<borrowable::message::client::ChangeUser<Borrowed>>> {
3355 template <class Accumulator>
3356 constexpr auto accumulate_fields(Accumulator &&accu) const {
3357 namespace bw = borrowable::wire;
3358
3359 accu.step(bw::FixedInt<1>(cmd_byte()))
3360 .step(bw::NulTermString<Borrowed>(v_.username()));
3361
3363 accu.step(bw::FixedInt<1>(v_.auth_method_data().size()))
3364 .step(bw::String<Borrowed>(v_.auth_method_data()));
3365 } else {
3366 accu.step(bw::NulTermString<Borrowed>(v_.auth_method_data()));
3367 }
3368 accu.step(bw::NulTermString<Borrowed>(v_.schema()));
3369
3370 // 4.1 and later have a collation
3371 //
3372 // this could be checked via the protocol_41 capability, but that's not
3373 // what the server does
3374 if (v_.collation() != 0x00 ||
3377 accu.step(bw::FixedInt<2>(v_.collation()));
3379 accu.step(bw::NulTermString<Borrowed>(v_.auth_method_name()));
3380 }
3381
3382 if (this->caps()
3384 accu.step(bw::VarString<Borrowed>(v_.attributes()));
3385 }
3386 }
3387
3388 return accu.result();
3389 }
3390
3391 public:
3394
3395 friend __base;
3396
3398 : __base(caps), v_{std::move(v)} {}
3399
3400 constexpr static uint8_t cmd_byte() noexcept {
3401 return static_cast<uint8_t>(CommandByte::ChangeUser);
3402 }
3403
3404 /**
3405 * capabilities the codec depends on.
3406 */
3410 }
3411
3415
3416 namespace bw = borrowable::wire;
3417
3418 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
3419 if (!accu.result()) return stdx::unexpected(accu.result().error());
3420
3421 if (cmd_byte_res->value() != cmd_byte()) {
3423 }
3424 auto username_res = accu.template step<bw::NulTermString<Borrowed>>();
3425
3426 // auth-method-data is either
3427 //
3428 // - fixed-int-1 length
3429 // - null-term-string
3430 stdx::expected<bw::String<Borrowed>, std::error_code> auth_method_data_res;
3432 auto auth_method_data_len_res = accu.template step<bw::FixedInt<1>>();
3433 if (!auth_method_data_len_res)
3434 return stdx::unexpected(auth_method_data_len_res.error());
3435 auto auth_method_data_len = auth_method_data_len_res->value();
3436
3437 auto res = accu.template step<bw::String<Borrowed>>(auth_method_data_len);
3438 if (!res) return stdx::unexpected(res.error());
3439
3440 auth_method_data_res = bw::String<Borrowed>(res->value());
3441 } else {
3442 auto res = accu.template step<bw::NulTermString<Borrowed>>();
3443 if (!res) return stdx::unexpected(res.error());
3444
3445 auth_method_data_res = bw::String<Borrowed>(res->value());
3446 }
3447
3448 auto schema_res = accu.template step<bw::NulTermString<Borrowed>>();
3449
3450 if (!accu.result()) return stdx::unexpected(accu.result().error());
3451
3452 // 3.23.x-4.0 don't send more.
3453 if (buffer_size(buffer) <= accu.result().value()) {
3454 return std::make_pair(
3455 accu.result().value(),
3456 value_type(username_res->value(), auth_method_data_res->value(),
3457 schema_res->value(), 0x00, {}, {}));
3458 }
3459
3460 // added in 4.1
3461 auto collation_res = accu.template step<bw::FixedInt<2>>();
3462
3464 auth_method_name_res;
3466 auth_method_name_res = accu.template step<bw::NulTermString<Borrowed>>();
3467 }
3468
3469 stdx::expected<bw::VarString<Borrowed>, std::error_code> attributes_res;
3471 attributes_res = accu.template step<bw::VarString<Borrowed>>();
3472 }
3473
3474 if (!accu.result()) return stdx::unexpected(accu.result().error());
3475
3476 return std::make_pair(
3477 accu.result().value(),
3478 value_type(username_res->value(), auth_method_data_res->value(),
3479 schema_res->value(), collation_res->value(),
3480 auth_method_name_res->value(), attributes_res->value()));
3481 }
3482
3483 private:
3485};
3486
3487/**
3488 * codec for client's Clone command.
3489 *
3490 * response: server::Ok or server::Error
3491 */
3492template <>
3494 : public CodecSimpleCommand<Codec<borrowable::message::client::Clone>,
3495 borrowable::message::client::Clone> {
3496 public:
3499
3501
3502 constexpr static uint8_t cmd_byte() noexcept {
3503 return static_cast<uint8_t>(CommandByte::Clone);
3504 }
3505
3506 /**
3507 * capabilities the codec depends on.
3508 */
3510 return {};
3511 }
3512};
3513
3514/**
3515 * codec for client side dump-binlog message.
3516 */
3517template <bool Borrowed>
3518class Codec<borrowable::message::client::BinlogDump<Borrowed>>
3519 : public impl::EncodeBase<
3520 Codec<borrowable::message::client::BinlogDump<Borrowed>>> {
3521 public:
3523
3524 private:
3525 template <class Accumulator>
3526 constexpr auto accumulate_fields(Accumulator &&accu) const {
3527 namespace bw = borrowable::wire;
3528
3529 return accu.step(bw::FixedInt<1>(cmd_byte()))
3530 .step(bw::FixedInt<4>(v_.position()))
3531 .step(bw::FixedInt<2>(v_.flags().underlying_value()))
3532 .step(bw::FixedInt<4>(v_.server_id()))
3533 .step(bw::String<Borrowed>(v_.filename()))
3534 .result();
3535 }
3536
3537 public:
3539
3540 friend __base;
3541
3543 : __base(caps), v_{std::move(v)} {}
3544
3545 constexpr static uint8_t cmd_byte() noexcept {
3546 return static_cast<uint8_t>(CommandByte::BinlogDump);
3547 }
3548
3549 /**
3550 * capabilities the codec depends on.
3551 */
3553 return {};
3554 }
3555
3559
3560 namespace bw = borrowable::wire;
3561
3562 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
3563 if (!accu.result()) return stdx::unexpected(accu.result().error());
3564
3565 if (cmd_byte_res->value() != cmd_byte()) {
3567 }
3568 auto position_res = accu.template step<bw::FixedInt<4>>();
3569 auto flags_res = accu.template step<bw::FixedInt<2>>();
3570 auto server_id_res = accu.template step<bw::FixedInt<4>>();
3571
3572 auto filename_res = accu.template step<bw::String<Borrowed>>();
3573
3574 if (!accu.result()) return stdx::unexpected(accu.result().error());
3575
3577 flags.underlying_value(flags_res->value());
3578
3579 return std::make_pair(
3580 accu.result().value(),
3581 value_type(flags, server_id_res->value(), filename_res->value(),
3582 position_res->value()));
3583 }
3584
3585 private:
3587};
3588
3589/**
3590 * codec for client side register-replica message.
3591 */
3592template <bool Borrowed>
3593class Codec<borrowable::message::client::RegisterReplica<Borrowed>>
3594 : public impl::EncodeBase<
3595 Codec<borrowable::message::client::RegisterReplica<Borrowed>>> {
3596 public:
3598
3599 private:
3600 template <class Accumulator>
3601 constexpr auto accumulate_fields(Accumulator &&accu) const {
3602 namespace bw = borrowable::wire;
3603
3604 return accu.step(bw::FixedInt<1>(cmd_byte()))
3605 .step(bw::FixedInt<4>(v_.server_id()))
3606 .step(bw::FixedInt<1>(v_.hostname().size()))
3607 .step(bw::String<Borrowed>(v_.hostname()))
3608 .step(bw::FixedInt<1>(v_.username().size()))
3609 .step(bw::String<Borrowed>(v_.username()))
3610 .step(bw::FixedInt<1>(v_.password().size()))
3611 .step(bw::String<Borrowed>(v_.password()))
3612 .step(bw::FixedInt<2>(v_.port()))
3613 .step(bw::FixedInt<4>(v_.replication_rank()))
3614 .step(bw::FixedInt<4>(v_.master_id()))
3615 .result();
3616 }
3617
3618 public:
3620
3621 friend __base;
3622
3624 : __base(caps), v_{std::move(v)} {}
3625
3626 constexpr static uint8_t cmd_byte() noexcept {
3627 return static_cast<uint8_t>(CommandByte::RegisterReplica);
3628 }
3629
3630 /**
3631 * capabilities the codec depends on.
3632 */
3634 return {};
3635 }
3636
3640
3641 namespace bw = borrowable::wire;
3642
3643 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
3644 if (!accu.result()) return stdx::unexpected(accu.result().error());
3645
3646 if (cmd_byte_res->value() != cmd_byte()) {
3648 }
3649 auto server_id_res = accu.template step<bw::FixedInt<4>>();
3650 auto hostname_len_res = accu.template step<bw::FixedInt<1>>();
3651 if (!accu.result()) return stdx::unexpected(accu.result().error());
3652
3653 auto hostname_res =
3654 accu.template step<bw::String<Borrowed>>(hostname_len_res->value());
3655
3656 auto username_len_res = accu.template step<bw::FixedInt<1>>();
3657 if (!accu.result()) return stdx::unexpected(accu.result().error());
3658
3659 auto username_res =
3660 accu.template step<bw::String<Borrowed>>(username_len_res->value());
3661
3662 auto password_len_res = accu.template step<bw::FixedInt<1>>();
3663 if (!accu.result()) return stdx::unexpected(accu.result().error());
3664
3665 auto password_res =
3666 accu.template step<bw::String<Borrowed>>(password_len_res->value());
3667
3668 auto port_res = accu.template step<bw::FixedInt<2>>();
3669 auto replication_rank_res = accu.template step<bw::FixedInt<4>>();
3670 auto master_id_res = accu.template step<bw::FixedInt<4>>();
3671
3672 if (!accu.result()) return stdx::unexpected(accu.result().error());
3673
3674 return std::make_pair(
3675 accu.result().value(),
3676 value_type(server_id_res->value(), hostname_res->value(),
3677 username_res->value(), password_res->value(),
3678 port_res->value(), replication_rank_res->value(),
3679 master_id_res->value()));
3680 }
3681
3682 private:
3684};
3685
3686/**
3687 * codec for client side dump-binlog-with-gtid message.
3688 */
3689template <bool Borrowed>
3690class Codec<borrowable::message::client::BinlogDumpGtid<Borrowed>>
3691 : public impl::EncodeBase<
3692 Codec<borrowable::message::client::BinlogDumpGtid<Borrowed>>> {
3693 public:
3695
3696 private:
3697 template <class Accumulator>
3698 constexpr auto accumulate_fields(Accumulator &&accu) const {
3699 namespace bw = borrowable::wire;
3700
3701 accu.step(bw::FixedInt<1>(cmd_byte()))
3702 .step(bw::FixedInt<2>(v_.flags().underlying_value()))
3703 .step(bw::FixedInt<4>(v_.server_id()))
3704 .step(bw::FixedInt<4>(v_.filename().size()))
3705 .step(bw::String<Borrowed>(v_.filename()))
3706 .step(bw::FixedInt<8>(v_.position()));
3707
3708 if (v_.flags() & value_type::Flags::through_gtid) {
3709 accu.step(bw::FixedInt<4>(v_.sids().size()))
3710 .step(bw::String<Borrowed>(v_.sids()));
3711 }
3712
3713 return accu.result();
3714 }
3715
3716 public:
3718
3719 friend base_;
3720
3722 : base_(caps), v_{std::move(val)} {}
3723
3724 constexpr static uint8_t cmd_byte() noexcept {
3725 return static_cast<uint8_t>(CommandByte::BinlogDumpGtid);
3726 }
3727
3728 /**
3729 * capabilities the codec depends on.
3730 */
3732 return {};
3733 }
3734
3738
3739 namespace bw = borrowable::wire;
3740
3741 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
3742 if (!accu.result()) return stdx::unexpected(accu.result().error());
3743
3744 if (cmd_byte_res->value() != cmd_byte()) {
3746 }
3747 auto flags_res = accu.template step<bw::FixedInt<2>>();
3748 auto server_id_res = accu.template step<bw::FixedInt<4>>();
3749 auto filename_len_res = accu.template step<bw::FixedInt<4>>();
3750 if (!accu.result()) return stdx::unexpected(accu.result().error());
3751
3752 auto filename_res =
3753 accu.template step<bw::String<Borrowed>>(filename_len_res->value());
3754 auto position_res = accu.template step<bw::FixedInt<8>>();
3755
3757 flags.underlying_value(flags_res->value());
3758
3759 if (!(flags & value_type::Flags::through_gtid)) {
3760 if (!accu.result()) return stdx::unexpected(accu.result().error());
3761
3762 return std::make_pair(
3763 accu.result().value(),
3764 value_type(flags, server_id_res->value(), filename_res->value(),
3765 position_res->value(), {}));
3766 }
3767
3768 auto sids_len_res = accu.template step<bw::FixedInt<4>>();
3769 if (!accu.result()) return stdx::unexpected(accu.result().error());
3770
3771 auto sids_res =
3772 accu.template step<bw::String<Borrowed>>(sids_len_res->value());
3773
3774 if (!accu.result()) return stdx::unexpected(accu.result().error());
3775
3776 return std::make_pair(
3777 accu.result().value(),
3778 value_type(flags, server_id_res->value(), filename_res->value(),
3779 position_res->value(), sids_res->value()));
3780 }
3781
3782 private:
3784};
3785
3786} // namespace classic_protocol
3787
3788#endif
CRTP base for client-side commands that are encoded as a single byte.
Definition: classic_protocol_codec_message.h:1454
constexpr CodecSimpleCommand(capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:1467
friend __base
Definition: classic_protocol_codec_message.h:1465
static constexpr size_t max_size() noexcept
Definition: classic_protocol_codec_message.h:1469
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:1471
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:1456
const value_type v_
Definition: classic_protocol_codec_message.h:3339
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:3324
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:3320
friend __base
Definition: classic_protocol_codec_message.h:3312
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:3302
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:3314
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:3724
const value_type v_
Definition: classic_protocol_codec_message.h:3783
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:3735
constexpr Codec(value_type val, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:3721
friend base_
Definition: classic_protocol_codec_message.h:3719
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:3731
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:3698
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:3542
friend __base
Definition: classic_protocol_codec_message.h:3540
const value_type v_
Definition: classic_protocol_codec_message.h:3586
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:3556
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:3526
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:3545
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:3552
const value_type v_
Definition: classic_protocol_codec_message.h:3484
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:3407
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:3400
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:3412
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:3397
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:3356
friend __base
Definition: classic_protocol_codec_message.h:3395
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:3502
constexpr Codec(value_type, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:3500
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:3509
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:1637
constexpr Codec(value_type, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:1635
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:1644
friend __base
Definition: classic_protocol_codec_message.h:3101
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:3115
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:3103
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:3029
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:3109
const value_type v_
Definition: classic_protocol_codec_message.h:3285
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:1685
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:1657
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:1681
const value_type v_
Definition: classic_protocol_codec_message.h:1706
friend __base
Definition: classic_protocol_codec_message.h:1669
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:1671
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:1674
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:2217
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:2193
value_type v_
Definition: classic_protocol_codec_message.h:2242
friend __base
Definition: classic_protocol_codec_message.h:2205
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:2221
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:2210
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:2207
const value_type v_
Definition: classic_protocol_codec_message.h:2120
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:2083
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:2086
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:2093
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:2068
friend __base
Definition: classic_protocol_codec_message.h:2081
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:2097
constexpr Codec(value_type, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:1585
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:1594
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:1587
const value_type v_
Definition: classic_protocol_codec_message.h:2004
friend __base
Definition: classic_protocol_codec_message.h:1881
auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:1717
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:1897
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:1886
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:1893
static stdx::expected< size_t, std::error_code > decode_field_size(Accu &accu, uint8_t type)
Definition: classic_protocol_codec_message.h:1823
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:1883
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:1536
constexpr Codec(value_type, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:1534
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:1543
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:3601
const value_type v_
Definition: classic_protocol_codec_message.h:3683
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:3626
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:3623
friend __base
Definition: classic_protocol_codec_message.h:3621
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:3637
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:3633
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:2154
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:2130
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:2147
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:2144
friend __base
Definition: classic_protocol_codec_message.h:2142
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:2158
const value_type v_
Definition: classic_protocol_codec_message.h:2178
constexpr Codec(value_type, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:1560
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:1562
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:1569
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:2043
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:2021
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:2039
friend __base
Definition: classic_protocol_codec_message.h:2031
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:2033
const value_type v_
Definition: classic_protocol_codec_message.h:2057
const value_type v_
Definition: classic_protocol_codec_message.h:2920
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:2899
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:2885
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:2895
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:2871
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:2888
friend __base
Definition: classic_protocol_codec_message.h:2883
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:1619
constexpr Codec(value_type, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:1610
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:1612
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:2777
friend __base
Definition: classic_protocol_codec_message.h:2765
const value_type v_
Definition: classic_protocol_codec_message.h:2802
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:2770
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:2753
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:2781
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:2767
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:2430
friend __base
Definition: classic_protocol_codec_message.h:2418
const value_type v_
Definition: classic_protocol_codec_message.h:2678
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:2478
auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:2313
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:2423
constexpr Codec(value_type val, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:2420
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:2959
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:2948
const value_type v_
Definition: classic_protocol_codec_message.h:2982
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:2930
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:2945
friend __base
Definition: classic_protocol_codec_message.h:2943
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:2955
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:2705
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:2708
const value_type v_
Definition: classic_protocol_codec_message.h:2743
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:2715
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:2719
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:2689
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:2270
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:2281
const value_type v_
Definition: classic_protocol_codec_message.h:2302
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:2267
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:2277
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:2253
friend __base
Definition: classic_protocol_codec_message.h:2265
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:2829
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:2840
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:2812
friend __base
Definition: classic_protocol_codec_message.h:2824
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:2836
const value_type v_
Definition: classic_protocol_codec_message.h:2861
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:2826
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:786
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:791
friend __base
Definition: classic_protocol_codec_message.h:789
const value_type v_
Definition: classic_protocol_codec_message.h:812
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:779
static constexpr size_t max_size() noexcept
Definition: classic_protocol_codec_message.h:794
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:798
auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:826
const value_type v_
Definition: classic_protocol_codec_message.h:980
friend __base
Definition: classic_protocol_codec_message.h:870
Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:872
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:879
static size_t max_size() noexcept
Definition: classic_protocol_codec_message.h:875
borrowable::message::server::ColumnMeta< Borrowed > value_type
Definition: classic_protocol_codec_message.h:867
borrowable::message::server::Eof< Borrowed > value_type
Definition: classic_protocol_codec_message.h:561
const value_type v_
Definition: classic_protocol_codec_message.h:668
friend __base
Definition: classic_protocol_codec_message.h:564
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:574
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:566
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:519
static constexpr uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:569
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:599
friend __base
Definition: classic_protocol_codec_message.h:717
static constexpr uint8_t cmd_byte()
Definition: classic_protocol_codec_message.h:722
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:719
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:727
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:735
borrowable::message::server::Error< Borrowed > value_type
Definition: classic_protocol_codec_message.h:714
const value_type v_
Definition: classic_protocol_codec_message.h:769
static constexpr size_t max_size() noexcept
Definition: classic_protocol_codec_message.h:731
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:700
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:417
const value_type v_
Definition: classic_protocol_codec_message.h:493
borrowable::message::server::Ok< Borrowed > value_type
Definition: classic_protocol_codec_message.h:404
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:409
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:437
friend __base
Definition: classic_protocol_codec_message.h:407
static constexpr uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:412
static size_t max_size() noexcept
Definition: classic_protocol_codec_message.h:1174
Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:1171
const value_type v_
Definition: classic_protocol_codec_message.h:1207
auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:1151
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:1178
borrowable::message::server::Row< Borrowed > value_type
Definition: classic_protocol_codec_message.h:1166
friend __base
Definition: classic_protocol_codec_message.h:1169
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:1019
const value_type v_
Definition: classic_protocol_codec_message.h:1044
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:1011
friend __base
Definition: classic_protocol_codec_message.h:1009
borrowable::message::server::SendFileRequest< Borrowed > value_type
Definition: classic_protocol_codec_message.h:1006
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:1023
static constexpr uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:1014
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:997
const value_type v_
Definition: classic_protocol_codec_message.h:1446
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:1428
borrowable::message::server::Statistics< Borrowed > value_type
Definition: classic_protocol_codec_message.h:1423
friend __base
Definition: classic_protocol_codec_message.h:1426
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:1431
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:1416
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:1096
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:1105
friend __base
Definition: classic_protocol_codec_message.h:1091
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:1093
static constexpr capabilities::value_type depends_on_capabilities() noexcept
capabilities the codec depends on.
Definition: classic_protocol_codec_message.h:1101
borrowable::message::server::StmtPrepareOk value_type
Definition: classic_protocol_codec_message.h:1088
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:1070
const value_type v_
Definition: classic_protocol_codec_message.h:1140
const value_type v_
Definition: classic_protocol_codec_message.h:1405
Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:1299
borrowable::message::server::StmtRow< Borrowed > value_type
Definition: classic_protocol_codec_message.h:1294
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:1306
static size_t max_size() noexcept
Definition: classic_protocol_codec_message.h:1302
auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:1229
friend __base
Definition: classic_protocol_codec_message.h:1297
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:153
result_type result() const
get result of the step().
Definition: classic_protocol_codec_base.h:219
CRTP base for the Codec's encode part.
Definition: classic_protocol_codec_base.h:374
constexpr capabilities::value_type caps() const noexcept
Definition: classic_protocol_codec_base.h:389
Definition: buffer.h:135
size_t size() const noexcept
Definition: buffer.h:120
Definition: expected.h:284
constexpr const error_type & error() const &
Definition: expected.h:751
constexpr value_type & value() &
Definition: expected.h:636
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:1488
constexpr size_t bytes_per_bits(size_t bits)
Definition: classic_protocol_codec_base.h:55
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:142
unexpected(E) -> unexpected< E >
required string type
Definition: replication_group_member_actions.proto:34
int n
Definition: xcom_base.cc:509