MySQL 8.0.40
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::make_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::make_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::make_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::make_unexpected(accu.result().error());
194
195 // should be 21, but least 8
196 if (auth_method_data_len_res->value() < 8) {
199 }
200 auth_method_data_len = auth_method_data_len_res->value() - 8;
201 } else {
202 accu.template step<void>(1); // should be 0 ...
203 }
204
205 accu.template step<void>(10); // skip the filler
206
208 auth_method_data_2_res;
210 auth_method_res;
211 if (capabilities
213 // auth-method-data
214 auth_method_data_2_res =
215 accu.template step<bw::String<Borrowed>>(auth_method_data_len);
216
218 // auth_method
219 auth_method_res = accu.template step<bw::NulTermString<Borrowed>>();
220 }
221 }
222
223 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
224
225 return std::make_pair(
226 accu.result().value(),
228 protocol_version_res->value(), version_res->value(),
229 connection_id_res->value(),
230 auth_method_data_res->value() + auth_method_data_2_res->value(),
231 capabilities, collation_res->value(), status_flags_res->value(),
232 auth_method_res->value()));
233 }
234 }
235
236 private:
238};
239
240/**
241 * codec for server::AuthMethodSwitch message.
242 */
243template <bool Borrowed>
244class Codec<borrowable::message::server::AuthMethodSwitch<Borrowed>>
245 : public impl::EncodeBase<
246 Codec<borrowable::message::server::AuthMethodSwitch<Borrowed>>> {
247 template <class Accumulator>
248 constexpr auto accumulate_fields(Accumulator &&accu) const {
249 namespace bw = borrowable::wire;
250
251 accu.step(bw::FixedInt<1>(cmd_byte()));
252
254 accu.step(bw::NulTermString<Borrowed>(v_.auth_method()))
255 .step(bw::String<Borrowed>(v_.auth_method_data()));
256 }
257
258 return accu.result();
259 }
260
261 public:
262 using value_type = borrowable::message::server::AuthMethodSwitch<Borrowed>;
264
265 friend __base;
266
268 : __base(caps), v_{std::move(v)} {}
269
270 static constexpr uint8_t cmd_byte() noexcept { return 0xfe; }
271
275
276 namespace bw = borrowable::wire;
277
278 // proto-version
279 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
280 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
281
282 if (cmd_byte_res->value() != cmd_byte()) {
284 }
285
287 return std::make_pair(accu.result().value(), value_type());
288 }
289
290 auto auth_method_res = accu.template step<bw::NulTermString<Borrowed>>();
291 auto auth_method_data_res = accu.template step<bw::String<Borrowed>>();
292
293 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
294
295 return std::make_pair(
296 accu.result().value(),
297 value_type(auth_method_res->value(), auth_method_data_res->value()));
298 }
299
300 private:
302};
303
304/**
305 * codec for server::AuthMethodData message.
306 */
307template <bool Borrowed>
308class Codec<borrowable::message::server::AuthMethodData<Borrowed>>
309 : public impl::EncodeBase<
310 Codec<borrowable::message::server::AuthMethodData<Borrowed>>> {
311 template <class Accumulator>
312 constexpr auto accumulate_fields(Accumulator &&accu) const {
313 namespace bw = borrowable::wire;
314
315 return accu.step(bw::FixedInt<1>(cmd_byte()))
316 .step(bw::String<Borrowed>(v_.auth_method_data()))
317 .result();
318 }
319
320 public:
321 using value_type = borrowable::message::server::AuthMethodData<Borrowed>;
323
324 friend __base;
325
327 : __base(caps), v_{std::move(v)} {}
328
329 static constexpr uint8_t cmd_byte() noexcept { return 0x01; }
330
334
335 namespace bw = borrowable::wire;
336
337 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
338 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
339
340 if (cmd_byte_res->value() != cmd_byte()) {
342 }
343 auto auth_method_data_res = accu.template step<bw::String<Borrowed>>();
344
345 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
346
347 return std::make_pair(accu.result().value(),
348 value_type(auth_method_data_res->value()));
349 }
350
351 private:
353};
354
355/**
356 * codec for server-side Ok message.
357 */
358template <bool Borrowed>
359class Codec<borrowable::message::server::Ok<Borrowed>>
360 : public impl::EncodeBase<
361 Codec<borrowable::message::server::Ok<Borrowed>>> {
362 template <class Accumulator>
363 constexpr auto accumulate_fields(Accumulator &&accu) const {
364 namespace bw = borrowable::wire;
365
366 accu.step(bw::FixedInt<1>(cmd_byte()))
367 .step(bw::VarInt(v_.affected_rows()))
368 .step(bw::VarInt(v_.last_insert_id()));
369
370 if (this->caps()[capabilities::pos::protocol_41] ||
371 this->caps()[capabilities::pos::transactions]) {
372 accu.step(bw::FixedInt<2>(v_.status_flags().to_ulong()));
373 if (this->caps().test(capabilities::pos::protocol_41)) {
374 accu.step(bw::FixedInt<2>(v_.warning_count()));
375 }
376 }
377
378 if (this->caps().test(capabilities::pos::session_track)) {
379 accu.step(bw::VarString<Borrowed>(v_.message()));
380 if (v_.status_flags().test(status::pos::session_state_changed)) {
381 accu.step(bw::VarString<Borrowed>(v_.session_changes()));
382 }
383 } else {
384 accu.step(bw::String<Borrowed>(v_.message()));
385 }
386
387 return accu.result();
388 }
389
390 public:
391 using value_type = borrowable::message::server::Ok<Borrowed>;
393
394 friend __base;
395
397 : __base(caps), v_{std::move(v)} {}
398
399 static constexpr uint8_t cmd_byte() noexcept { return 0x00; }
400
401 /**
402 * decode a server::Ok message from a buffer-sequence.
403 *
404 * precondition:
405 * - input starts with cmd_byte()
406 *
407 * @param buffer input buffser sequence
408 * @param caps protocol capabilities
409 *
410 * @retval std::pair<size_t, message::server::Ok> on success, with bytes
411 * processed
412 * @retval codec_errc::invalid_input if preconditions aren't met
413 * @retval codec_errc::not_enough_input not enough data to parse the whole
414 * message
415 */
419
420 namespace bw = borrowable::wire;
421
422 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
423 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
424
425 if (cmd_byte_res->value() != cmd_byte()) {
427 }
428
429 auto affected_rows_res = accu.template step<bw::VarInt>();
430 auto last_insert_id_res = accu.template step<bw::VarInt>();
431
432 stdx::expected<bw::FixedInt<2>, std::error_code> status_flags_res(0);
433 stdx::expected<bw::FixedInt<2>, std::error_code> warning_count_res(0);
436 status_flags_res = accu.template step<bw::FixedInt<2>>();
438 warning_count_res = accu.template step<bw::FixedInt<2>>();
439 }
440 }
441
442 stdx::expected<bw::String<Borrowed>, std::error_code> message_res;
444 session_changes_res;
446 // if there is more data.
447 const auto var_message_res =
448 accu.template try_step<bw::VarString<Borrowed>>();
449 if (var_message_res) {
450 // set the message from the var-string
451 message_res = var_message_res.value();
452 }
453
454 if (status_flags_res->value() &
456 session_changes_res = accu.template step<bw::VarString<Borrowed>>();
457 }
458 } else {
459 message_res = accu.template step<bw::String<Borrowed>>();
460 }
461
462 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
463
464 return std::make_pair(
465 accu.result().value(),
466 value_type(affected_rows_res->value(), last_insert_id_res->value(),
467 status_flags_res->value(), warning_count_res->value(),
468 message_res->value(), session_changes_res->value()));
469 }
470
471 private:
473};
474
475/**
476 * codec for server-side Eof message.
477 *
478 * Eof message is encoded differently dependending on protocol capabiltiies,
479 * but always starts with:
480 *
481 * - 0xef
482 *
483 * If capabilities has text_result_with_session_tracking, it is followed by
484 * - [rest of Ok packet]
485 *
486 * otherwise, if capabilities has protocol_41
487 * - FixedInt<2> warning-count
488 * - FixedInt<2> status flags
489 *
490 * otherwise
491 * - nothing
492 */
493template <bool Borrowed>
494class Codec<borrowable::message::server::Eof<Borrowed>>
495 : public impl::EncodeBase<
496 Codec<borrowable::message::server::Eof<Borrowed>>> {
497 template <class Accumulator>
498 constexpr auto accumulate_fields(Accumulator &&accu) const {
499 namespace bw = borrowable::wire;
500
501 accu.step(bw::FixedInt<1>(cmd_byte()));
502
503 auto shared_caps = this->caps();
504
505 if (shared_caps.test(
507 accu.step(bw::VarInt(v_.affected_rows()))
508 .step(bw::VarInt(v_.last_insert_id()));
509
510 if (shared_caps[capabilities::pos::protocol_41] ||
511 shared_caps[capabilities::pos::transactions]) {
512 accu.step(bw::FixedInt<2>(v_.status_flags().to_ulong()));
513 if (shared_caps[capabilities::pos::protocol_41]) {
514 accu.step(bw::FixedInt<2>(v_.warning_count()));
515 }
516 }
517
518 if (shared_caps[capabilities::pos::session_track]) {
519 if (!v_.message().empty() ||
520 v_.status_flags()[status::pos::session_state_changed]) {
521 // only write message and session-changes if both of them aren't
522 // empty.
523 accu.step(bw::VarString<Borrowed>(v_.message()));
524 if (v_.status_flags()[status::pos::session_state_changed]) {
525 accu.step(bw::VarString<Borrowed>(v_.session_changes()));
526 }
527 }
528 } else {
529 accu.step(bw::String<Borrowed>(v_.message()));
530 }
531 } else if (shared_caps[capabilities::pos::protocol_41]) {
532 accu.step(bw::FixedInt<2>(v_.warning_count()))
533 .step(bw::FixedInt<2>(v_.status_flags().to_ulong()));
534 }
535
536 return accu.result();
537 }
538
539 public:
540 using value_type = borrowable::message::server::Eof<Borrowed>;
542
543 friend __base;
544
546 : __base(caps), v_{std::move(v)} {}
547
548 static constexpr uint8_t cmd_byte() noexcept { return 0xfe; }
549
550 /**
551 * decode a server::Eof message from a buffer-sequence.
552 *
553 * capabilities checked:
554 * - protocol_41
555 * - text_resultset_with_session_tracking
556 *
557 * precondition:
558 * - input starts with cmd_byte()
559 *
560 * @param buffer input buffser sequence
561 * @param caps protocol capabilities
562 *
563 * @retval std::pair<size_t, message::server::Eof> on success, with bytes
564 * processed
565 * @retval codec_errc::invalid_input if preconditions aren't met
566 * @retval codec_errc::not_enough_input not enough data to parse the whole
567 * message
568 */
572
573 namespace bw = borrowable::wire;
574
575 const auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
576 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
577
578 if (cmd_byte_res->value() != cmd_byte()) {
580 }
581
583 const auto affected_rows_res = accu.template step<bw::VarInt>();
584 const auto last_insert_id_res = accu.template step<bw::VarInt>();
585
586 stdx::expected<bw::FixedInt<2>, std::error_code> status_flags_res(0);
587 stdx::expected<bw::FixedInt<2>, std::error_code> warning_count_res(0);
590 status_flags_res = accu.template step<bw::FixedInt<2>>();
592 warning_count_res = accu.template step<bw::FixedInt<2>>();
593 }
594 }
595
596 stdx::expected<bw::String<Borrowed>, std::error_code> message_res;
598 session_state_info_res;
600 // when session-track is supported, the 'message' part is a VarString.
601 // But only if there is actually session-data and the message has data.
602 const auto var_message_res =
603 accu.template try_step<bw::VarString<Borrowed>>();
604 if (var_message_res) {
605 // set the message from the var-string
606 message_res = var_message_res.value();
607 }
608
609 if (status_flags_res->value() &
611 session_state_info_res =
612 accu.template step<bw::VarString<Borrowed>>();
613 }
614 } else {
615 message_res = accu.template step<bw::String<Borrowed>>();
616 }
617
618 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
619
620 return std::make_pair(
621 accu.result().value(),
622 value_type(affected_rows_res->value(), last_insert_id_res->value(),
623 status_flags_res->value(), warning_count_res->value(),
624 message_res->value(), session_state_info_res->value()));
625 } else if (caps[capabilities::pos::protocol_41]) {
626 const auto warning_count_res = accu.template step<bw::FixedInt<2>>();
627 const auto status_flags_res = accu.template step<bw::FixedInt<2>>();
628
629 return std::make_pair(
630 accu.result().value(),
631 value_type(status_flags_res->value(), warning_count_res->value()));
632 } else {
633 return std::make_pair(accu.result().value(), value_type());
634 }
635 }
636
637 private:
639};
640
641/**
642 * codec for Error message.
643 *
644 * note: Format overview:
645 *
646 * 3.21: protocol_version <= 9 [not supported]
647 *
648 * FixedInt<1> 0xff
649 * String message
650 *
651 * 3.21: protocol_version > 9
652 *
653 * FixedInt<1> 0xff
654 * FixedInt<2> error_code
655 * String message
656 *
657 * 4.1 and later:
658 *
659 * FixedInt<1> 0xff
660 * FixedInt<2> error_code
661 * '#'
662 * String<5> sql_state
663 * String message
664 */
665template <bool Borrowed>
666class Codec<borrowable::message::server::Error<Borrowed>>
667 : public impl::EncodeBase<
668 Codec<borrowable::message::server::Error<Borrowed>>> {
669 template <class Accumulator>
670 constexpr auto accumulate_fields(Accumulator &&accu) const {
671 namespace bw = borrowable::wire;
672
673 accu.step(bw::FixedInt<1>(cmd_byte()))
674 .step(bw::FixedInt<2>(v_.error_code()));
675 if (this->caps()[capabilities::pos::protocol_41]) {
676 accu.step(bw::FixedInt<1>('#'))
677 .step(bw::String<Borrowed>(v_.sql_state()));
678 }
679
680 return accu.step(bw::String<Borrowed>(v_.message())).result();
681 }
682
683 public:
684 using value_type = borrowable::message::server::Error<Borrowed>;
686
687 friend __base;
688
690 : __base(caps), v_{std::move(v)} {}
691
692 static constexpr uint8_t cmd_byte() { return 0xff; }
693
694 static constexpr size_t max_size() noexcept {
695 return std::numeric_limits<size_t>::max();
696 }
697
701
702 namespace bw = borrowable::wire;
703
704 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
705 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
706
707 if (cmd_byte_res->value() != cmd_byte()) {
709 }
710
711 // decode all fields, check result later before they are used.
712 auto error_code_res = accu.template step<bw::FixedInt<2>>();
713 stdx::expected<bw::String<Borrowed>, std::error_code> sql_state_res;
715 auto sql_state_hash_res = accu.template step<bw::FixedInt<1>>();
716 sql_state_res = accu.template step<bw::String<Borrowed>>(5);
717 }
718 auto message_res = accu.template step<bw::String<Borrowed>>();
719
720 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
721
722 return std::make_pair(
723 accu.result().value(),
724 value_type(error_code_res->value(), message_res->value(),
725 sql_state_res->value()));
726 }
727
728 private:
730};
731
732/**
733 * codec for ColumnCount message.
734 */
735template <>
737 : public impl::EncodeBase<Codec<borrowable::message::server::ColumnCount>> {
738 template <class Accumulator>
739 constexpr auto accumulate_fields(Accumulator &&accu) const {
740 namespace bw = borrowable::wire;
741
742 return accu.step(bw::VarInt(v_.count())).result();
743 }
744
745 public:
748
749 friend __base;
750
752 : __base(caps), v_{std::move(v)} {}
753
754 static constexpr size_t max_size() noexcept {
755 return std::numeric_limits<size_t>::max();
756 }
757
761
762 namespace bw = borrowable::wire;
763
764 auto count_res = accu.template step<bw::VarInt>();
765 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
766
767 return std::make_pair(accu.result().value(),
768 value_type(count_res->value()));
769 }
770
771 private:
773};
774
775/**
776 * Codec of ColumnMeta.
777 *
778 * capabilities checked:
779 * - protocol_41
780 */
781template <bool Borrowed>
782class Codec<borrowable::message::server::ColumnMeta<Borrowed>>
783 : public impl::EncodeBase<
784 Codec<borrowable::message::server::ColumnMeta<Borrowed>>> {
785 template <class Accumulator>
786 auto accumulate_fields(Accumulator &&accu) const {
787 namespace bw = borrowable::wire;
788
789 if (!this->caps()[capabilities::pos::protocol_41]) {
790 accu.step(bw::VarString<Borrowed>(v_.table()))
791 .step(bw::VarString<Borrowed>(v_.name()))
792 .step(bw::VarInt(3))
793 .step(bw::FixedInt<3>(v_.column_length()))
794 .step(bw::VarInt(1))
795 .step(bw::FixedInt<1>(v_.type()));
796
797 if (this->caps()[capabilities::pos::long_flag]) {
798 accu.step(bw::VarInt(3))
799 .step(bw::FixedInt<2>(v_.flags().to_ulong()))
800 .step(bw::FixedInt<1>(v_.decimals()));
801 } else {
802 accu.step(bw::VarInt(2))
803 .step(bw::FixedInt<1>(v_.flags().to_ulong()))
804 .step(bw::FixedInt<1>(v_.decimals()));
805 }
806
807 return accu.result();
808 } else {
809 return accu.step(bw::VarString<Borrowed>(v_.catalog()))
810 .step(bw::VarString<Borrowed>(v_.schema()))
811 .step(bw::VarString<Borrowed>(v_.table()))
812 .step(bw::VarString<Borrowed>(v_.orig_table()))
813 .step(bw::VarString<Borrowed>(v_.name()))
814 .step(bw::VarString<Borrowed>(v_.orig_name()))
815 .step(bw::VarInt(12))
816 .step(bw::FixedInt<2>(v_.collation()))
817 .step(bw::FixedInt<4>(v_.column_length()))
818 .step(bw::FixedInt<1>(v_.type()))
819 .step(bw::FixedInt<2>(v_.flags().to_ulong()))
820 .step(bw::FixedInt<1>(v_.decimals()))
821 .step(bw::FixedInt<2>(0))
822 .result();
823 }
824 }
825
826 public:
827 using value_type = borrowable::message::server::ColumnMeta<Borrowed>;
829
830 friend __base;
831
833 : __base(caps), v_{std::move(v)} {}
834
835 static size_t max_size() noexcept {
836 return std::numeric_limits<size_t>::max();
837 }
838
842
843 namespace bw = borrowable::wire;
844
846 // 3.2x protocol used up to 4.0.x
847
848 // bit-size of the 'flags' field
849 const uint8_t flags_size = caps[capabilities::pos::long_flag] ? 2 : 1;
850
851 const auto table_res = accu.template step<bw::VarString<Borrowed>>();
852 const auto name_res = accu.template step<bw::VarString<Borrowed>>();
853
854 const auto column_length_len_res = accu.template step<bw::VarInt>();
855 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
856
857 if (column_length_len_res->value() != 3) {
860 }
861
862 const auto column_length_res = accu.template step<bw::FixedInt<3>>();
863 const auto type_len_res = accu.template step<bw::VarInt>();
864 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
865
866 if (type_len_res->value() != 1) {
869 }
870
871 const auto type_res = accu.template step<bw::FixedInt<1>>();
872 const auto flags_and_decimals_len_res = accu.template step<bw::VarInt>();
873 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
874
875 if (flags_and_decimals_len_res->value() != flags_size + 1) {
878 }
879
880 stdx::expected<bw::FixedInt<3>, std::error_code> flags_and_decimals_res(
881 0);
882 if (flags_size == 2) {
883 flags_and_decimals_res = accu.template step<bw::FixedInt<3>>();
884 } else {
885 const auto small_flags_and_decimals_res =
886 accu.template step<bw::FixedInt<2>>();
887 if (small_flags_and_decimals_res) {
888 flags_and_decimals_res =
889 bw::FixedInt<3>(small_flags_and_decimals_res->value());
890 }
891 }
892
893 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
894
895 const uint16_t flags =
896 flags_and_decimals_res->value() & ((1 << (flags_size * 8)) - 1);
897 const uint8_t decimals =
898 flags_and_decimals_res->value() >> (flags_size * 8);
899
900 return std::make_pair(
901 accu.result().value(),
902 value_type({}, {}, table_res->value(), {}, name_res->value(), {}, {},
903 column_length_res->value(), type_res->value(), flags,
904 decimals));
905 } else {
906 const auto catalog_res = accu.template step<bw::VarString<Borrowed>>();
907 const auto schema_res = accu.template step<bw::VarString<Borrowed>>();
908 const auto table_res = accu.template step<bw::VarString<Borrowed>>();
909 const auto orig_table_res = accu.template step<bw::VarString<Borrowed>>();
910 const auto name_res = accu.template step<bw::VarString<Borrowed>>();
911 const auto orig_name_res = accu.template step<bw::VarString<Borrowed>>();
912
913 /* next is a collection of fields which is wrapped inside a varstring of
914 * 12-bytes size */
915 const auto other_len_res = accu.template step<bw::VarInt>();
916
917 if (other_len_res->value() != 12) {
920 }
921
922 const auto collation_res = accu.template step<bw::FixedInt<2>>();
923 const auto column_length_res = accu.template step<bw::FixedInt<4>>();
924 const auto type_res = accu.template step<bw::FixedInt<1>>();
925 const auto flags_res = accu.template step<bw::FixedInt<2>>();
926 const auto decimals_res = accu.template step<bw::FixedInt<1>>();
927
928 accu.template step<void>(2); // fillers
929
930 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
931
932 return std::make_pair(
933 accu.result().value(),
934 value_type(catalog_res->value(), schema_res->value(),
935 table_res->value(), orig_table_res->value(),
936 name_res->value(), orig_name_res->value(),
937 collation_res->value(), column_length_res->value(),
938 type_res->value(), flags_res->value(),
939 decimals_res->value()));
940 }
941 }
942
943 private:
945};
946
947/**
948 * codec for server's SendFileRequest response.
949 *
950 * sent as response after client::Query
951 *
952 * layout:
953 *
954 * 0xfb<filename>
955 */
956template <bool Borrowed>
957class Codec<borrowable::message::server::SendFileRequest<Borrowed>>
958 : public impl::EncodeBase<
959 Codec<borrowable::message::server::SendFileRequest<Borrowed>>> {
960 template <class Accumulator>
961 constexpr auto accumulate_fields(Accumulator &&accu) const {
962 namespace bw = borrowable::wire;
963
964 return accu.step(bw::FixedInt<1>(cmd_byte()))
965 .step(bw::String<Borrowed>(v_.filename()))
966 .result();
967 }
968
969 public:
970 using value_type = borrowable::message::server::SendFileRequest<Borrowed>;
972
973 friend __base;
974
976 : __base(caps), v_{std::move(v)} {}
977
978 static constexpr uint8_t cmd_byte() noexcept { return 0xfb; }
979
983
984 namespace bw = borrowable::wire;
985
986 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
987 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
988
989 if (cmd_byte_res->value() != cmd_byte()) {
991 }
992
993 auto filename_res = accu.template step<bw::String<Borrowed>>();
994 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
995
996 return std::make_pair(accu.result().value(),
997 value_type(filename_res->value()));
998 }
999
1000 private:
1002};
1003
1004/**
1005 * codec for server::StmtPrepareOk message.
1006 *
1007 * format:
1008 *
1009 * - FixedInt<1> == 0x00 [ok]
1010 * - FixedInt<4> stmt-id
1011 * - FixedInt<2> column-count
1012 * - FixedInt<2> param-count
1013 * - FixedInt<1> == 0x00 [filler]
1014 * - FixedInt<2> warning-count
1015 *
1016 * If caps contains optional_resultset_metadata:
1017 *
1018 * - FixedInt<1> with_metadata
1019 *
1020 * sent as response after a client::StmtPrepare
1021 */
1022template <>
1024 : public impl::EncodeBase<
1025 Codec<borrowable::message::server::StmtPrepareOk>> {
1026 template <class Accumulator>
1027 constexpr auto accumulate_fields(Accumulator &&accu) const {
1028 namespace bw = borrowable::wire;
1029
1030 accu.step(bw::FixedInt<1>(cmd_byte()))
1031 .step(bw::FixedInt<4>(v_.statement_id()))
1032 .step(bw::FixedInt<2>(v_.column_count()))
1033 .step(bw::FixedInt<2>(v_.param_count()))
1034 .step(bw::FixedInt<1>(0))
1035 .step(bw::FixedInt<2>(v_.warning_count()));
1036
1038 accu.step(bw::FixedInt<1>(v_.with_metadata()));
1039 }
1040
1041 return accu.result();
1042 }
1043
1044 public:
1047
1048 friend __base;
1049
1051 : __base(caps), v_{std::move(v)} {}
1052
1053 constexpr static uint8_t cmd_byte() noexcept { return 0x00; }
1054
1058
1059 namespace bw = borrowable::wire;
1060
1061 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
1062 auto stmt_id_res = accu.template step<bw::FixedInt<4>>();
1063 auto column_count_res = accu.template step<bw::FixedInt<2>>();
1064 auto param_count_res = accu.template step<bw::FixedInt<2>>();
1065 auto filler_res = accu.template step<bw::FixedInt<1>>();
1066 auto warning_count_res = accu.template step<bw::FixedInt<2>>();
1067
1068 // by default, metadata isn't optional
1069 int8_t with_metadata{1};
1071 auto with_metadata_res = accu.template step<bw::FixedInt<1>>();
1072
1073 if (with_metadata_res) {
1074 with_metadata = with_metadata_res->value();
1075 }
1076 }
1077
1078 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
1079
1080 return std::make_pair(
1081 accu.result().value(),
1082 value_type(stmt_id_res->value(), column_count_res->value(),
1083 param_count_res->value(), warning_count_res->value(),
1084 with_metadata));
1085 }
1086
1087 private:
1089};
1090
1091/**
1092 * codec for a Row from the server.
1093 */
1094template <bool Borrowed>
1095class Codec<borrowable::message::server::Row<Borrowed>>
1096 : public impl::EncodeBase<
1097 Codec<borrowable::message::server::Row<Borrowed>>> {
1098 template <class Accumulator>
1099 auto accumulate_fields(Accumulator &&accu) const {
1100 namespace bw = borrowable::wire;
1101
1102 for (const auto &field : v_) {
1103 if (field) {
1104 accu.step(bw::VarString<Borrowed>(*field));
1105 } else {
1106 accu.step(bw::Null());
1107 }
1108 }
1109
1110 return accu.result();
1111 }
1112
1113 public:
1114 using value_type = borrowable::message::server::Row<Borrowed>;
1116
1117 friend __base;
1118
1120 : __base(caps), v_{std::move(v)} {}
1121
1122 static size_t max_size() noexcept {
1123 return std::numeric_limits<size_t>::max();
1124 }
1125
1129
1130 namespace bw = borrowable::wire;
1131
1132 std::vector<typename value_type::value_type> fields;
1133
1134 const size_t buf_size = buffer_size(buffer);
1135
1136 while (accu.result() && (accu.result().value() < buf_size)) {
1137 // field may other be a Null or a VarString
1138 auto null_res = accu.template try_step<bw::Null>();
1139 if (null_res) {
1140 fields.emplace_back(std::nullopt);
1141 } else {
1142 auto field_res = accu.template step<bw::VarString<Borrowed>>();
1143 if (!field_res) return stdx::make_unexpected(field_res.error());
1144
1145 fields.emplace_back(field_res->value());
1146 }
1147 }
1148
1149 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
1150
1151 return std::make_pair(accu.result().value(), value_type(fields));
1152 }
1153
1154 private:
1156};
1157
1158/**
1159 * codec for a StmtRow from the server.
1160 *
1161 * StmtRow is the Row of a StmtExecute's resultset.
1162 *
1163 * - 0x00
1164 * - NULL bitmap
1165 * - non-NULL-values in binary encoding
1166 *
1167 * both encode and decode require type information to know:
1168 *
1169 * - size the NULL bitmap
1170 * - length of each field
1171 */
1172template <bool Borrowed>
1173class Codec<borrowable::message::server::StmtRow<Borrowed>>
1174 : public impl::EncodeBase<
1175 Codec<borrowable::message::server::StmtRow<Borrowed>>> {
1176 template <class Accumulator>
1177 auto accumulate_fields(Accumulator &&accu) const {
1178 namespace bw = borrowable::wire;
1179
1180 accu.step(bw::FixedInt<1>(0));
1181
1182 // null-bitmap starts with a 2-bit offset
1183 size_t bit_pos{2};
1184 uint8_t null_bit_byte{};
1185
1186 for (auto const &field : v_) {
1187 if (!field) null_bit_byte |= (1 << bit_pos);
1188
1189 if (++bit_pos > 7) {
1190 accu.step(bw::FixedInt<1>(null_bit_byte));
1191
1192 bit_pos = 0;
1193 null_bit_byte = 0;
1194 }
1195 }
1196
1197 if (bit_pos != 0) accu.step(bw::FixedInt<1>(null_bit_byte));
1198
1199 for (auto [n, field] : stdx::views::enumerate(v_)) {
1200 if (!field) continue;
1201
1202 switch (v_.types()[n]) {
1203 case field_type::Bit:
1204 case field_type::Blob:
1207 case field_type::Set:
1208 case field_type::String:
1209 case field_type::Enum:
1216 accu.step(bw::VarInt(field->size()));
1217 break;
1218 case field_type::Date:
1221 case field_type::Time:
1222 accu.step(bw::FixedInt<1>(field->size()));
1223 break;
1225 case field_type::Double:
1226 case field_type::Long:
1227 case field_type::Int24:
1228 case field_type::Float:
1229 case field_type::Short:
1230 case field_type::Year:
1231 case field_type::Tiny:
1232 // fixed size
1233 break;
1234 }
1235 accu.step(borrowed::wire::String(*field));
1236 }
1237
1238 return accu.result();
1239 }
1240
1241 public:
1242 using value_type = borrowable::message::server::StmtRow<Borrowed>;
1244
1245 friend __base;
1246
1248 : __base(caps), v_{std::move(v)} {}
1249
1250 static size_t max_size() noexcept {
1251 return std::numeric_limits<size_t>::max();
1252 }
1253
1256 std::vector<field_type::value_type> types) {
1257 namespace bw = borrowable::wire;
1258
1260
1261 const auto row_byte_res = accu.template step<bw::FixedInt<1>>();
1262 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
1263
1264 // first byte is 0x00
1265 if (row_byte_res->value() != 0x00) {
1267 }
1268
1269 const auto nullbits_res =
1270 accu.template step<bw::String<Borrowed>>(bytes_per_bits(types.size()));
1271 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
1272
1273 const auto nullbits = nullbits_res->value();
1274
1275 std::vector<typename value_type::value_type> values;
1276
1277 for (size_t n{}, bit_pos{2}, byte_pos{}; n < types.size(); ++n, ++bit_pos) {
1278 if (bit_pos > 7) {
1279 bit_pos = 0;
1280 ++byte_pos;
1281 }
1282
1283 if (!(nullbits[byte_pos] & (1 << bit_pos))) {
1286 make_error_code(std::errc::invalid_argument)));
1287 switch (types[n]) {
1288 case field_type::Bit:
1289 case field_type::Blob:
1292 case field_type::Set:
1293 case field_type::String:
1294 case field_type::Enum:
1300 case field_type::Geometry: {
1301 auto string_field_size_res = accu.template step<bw::VarInt>();
1302 if (!accu.result())
1303 return stdx::make_unexpected(accu.result().error());
1304
1305 field_size_res = string_field_size_res->value();
1306 } break;
1307 case field_type::Date:
1310 case field_type::Time: {
1311 auto time_field_size_res = accu.template step<bw::FixedInt<1>>();
1312 if (!accu.result())
1313 return stdx::make_unexpected(accu.result().error());
1314
1315 field_size_res = time_field_size_res->value();
1316 } break;
1318 case field_type::Double:
1319 field_size_res = 8;
1320 break;
1321 case field_type::Long:
1322 case field_type::Int24:
1323 case field_type::Float:
1324 field_size_res = 4;
1325 break;
1326 case field_type::Short:
1327 case field_type::Year:
1328 field_size_res = 2;
1329 break;
1330 case field_type::Tiny:
1331 field_size_res = 1;
1332 break;
1333 }
1334
1335 if (!field_size_res) {
1336 return stdx::make_unexpected(
1338 }
1339
1340 const auto value_res =
1341 accu.template step<bw::String<Borrowed>>(field_size_res.value());
1342 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
1343
1344 values.push_back(value_res->value());
1345 } else {
1346 values.emplace_back(std::nullopt);
1347 }
1348 }
1349
1350 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
1351
1352 return std::make_pair(accu.result().value(), value_type(types, values));
1353 }
1354
1355 private:
1357};
1358
1359/**
1360 * codec for server::Statistics message.
1361 */
1362template <bool Borrowed>
1363class Codec<borrowable::message::server::Statistics<Borrowed>>
1364 : public impl::EncodeBase<
1365 Codec<borrowable::message::server::Statistics<Borrowed>>> {
1366 template <class Accumulator>
1367 constexpr auto accumulate_fields(Accumulator &&accu) const {
1368 namespace bw = borrowable::wire;
1369
1370 return accu.step(bw::String<Borrowed>(v_.stats())).result();
1371 }
1372
1373 public:
1374 using value_type = borrowable::message::server::Statistics<Borrowed>;
1376
1377 friend __base;
1378
1380 : __base(caps), v_{std::move(v)} {}
1381
1385
1386 namespace bw = borrowable::wire;
1387
1388 auto stats_res = accu.template step<bw::String<Borrowed>>();
1389
1390 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
1391
1392 return std::make_pair(accu.result().value(),
1393 value_type(stats_res->value()));
1394 }
1395
1396 private:
1398};
1399
1400/**
1401 * CRTP base for client-side commands that are encoded as a single byte.
1402 */
1403template <class Base, class ValueType>
1405 : public impl::EncodeBase<CodecSimpleCommand<Base, ValueType>> {
1406 template <class Accumulator>
1407 constexpr auto accumulate_fields(Accumulator &&accu) const {
1408 namespace bw = borrowable::wire;
1409
1410 return accu.step(bw::FixedInt<1>(Base::cmd_byte())).result();
1411 }
1412
1413 public:
1415
1416 friend __base;
1417
1419
1420 static constexpr size_t max_size() noexcept { return 1; }
1421
1425
1426 namespace bw = borrowable::wire;
1427
1428 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
1429 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
1430
1431 if (cmd_byte_res->value() != Base::cmd_byte()) {
1433 }
1434
1435 return std::make_pair(accu.result().value(), ValueType());
1436 }
1437};
1438
1439enum class CommandByte {
1440 Quit = 0x01,
1441 InitSchema,
1442 Query,
1443 ListFields,
1444 CreateDb,
1445 DropDb,
1446 Refresh,
1447 Shutdown,
1448 Statistics,
1450 Connect,
1452 Debug,
1453 Ping,
1454 Time,
1456 ChangeUser,
1457 BinlogDump,
1458 TableDump,
1459 ConnectOut,
1464 StmtClose,
1465 StmtReset,
1466 SetOption,
1467 StmtFetch,
1468 Deamon,
1471 Clone
1472};
1473
1474/**
1475 * codec for client's Quit command.
1476 */
1477template <>
1479 : public CodecSimpleCommand<Codec<borrowable::message::client::Quit>,
1480 borrowable::message::client::Quit> {
1481 public:
1484
1486
1487 constexpr static uint8_t cmd_byte() noexcept {
1488 return static_cast<uint8_t>(CommandByte::Quit);
1489 }
1490};
1491
1492/**
1493 * codec for client's ResetConnection command.
1494 */
1495template <>
1497 : public CodecSimpleCommand<
1498 Codec<borrowable::message::client::ResetConnection>,
1499 borrowable::message::client::ResetConnection> {
1500 public:
1503
1505
1506 constexpr static uint8_t cmd_byte() noexcept {
1507 return static_cast<uint8_t>(CommandByte::ResetConnection);
1508 }
1509};
1510
1511/**
1512 * codec for client's Ping command.
1513 */
1514template <>
1516 : public CodecSimpleCommand<Codec<borrowable::message::client::Ping>,
1517 borrowable::message::client::Ping> {
1518 public:
1521
1523
1524 constexpr static uint8_t cmd_byte() noexcept {
1525 return static_cast<uint8_t>(CommandByte::Ping);
1526 }
1527};
1528
1529/**
1530 * codec for client's Statistics command.
1531 */
1532template <>
1534 : public CodecSimpleCommand<Codec<borrowable::message::client::Statistics>,
1535 borrowable::message::client::Statistics> {
1536 public:
1539
1541
1542 constexpr static uint8_t cmd_byte() noexcept {
1543 return static_cast<uint8_t>(CommandByte::Statistics);
1544 }
1545};
1546
1547/**
1548 * codec for client's InitSchema command.
1549 */
1550template <bool Borrowed>
1551class Codec<borrowable::message::client::InitSchema<Borrowed>>
1552 : public impl::EncodeBase<
1553 Codec<borrowable::message::client::InitSchema<Borrowed>>> {
1554 template <class Accumulator>
1555 constexpr auto accumulate_fields(Accumulator &&accu) const {
1556 namespace bw = borrowable::wire;
1557
1558 return accu.step(bw::FixedInt<1>(cmd_byte()))
1559 .step(bw::String<Borrowed>(v_.schema()))
1560 .result();
1561 }
1562
1563 public:
1566
1567 friend __base;
1568
1570 : __base(caps), v_{std::move(v)} {}
1571
1572 constexpr static uint8_t cmd_byte() noexcept {
1573 return static_cast<uint8_t>(CommandByte::InitSchema);
1574 }
1575
1579
1580 namespace bw = borrowable::wire;
1581
1582 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
1583 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
1584
1585 if (cmd_byte_res->value() != cmd_byte()) {
1587 }
1588
1589 auto schema_res = accu.template step<bw::String<Borrowed>>();
1590 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
1591
1592 return std::make_pair(accu.result().value(),
1593 value_type(schema_res->value()));
1594 }
1595
1596 private:
1598};
1599
1600/**
1601 * codec for client's Query command.
1602 */
1603template <bool Borrowed>
1604class Codec<borrowable::message::client::Query<Borrowed>>
1605 : public impl::EncodeBase<
1606 Codec<borrowable::message::client::Query<Borrowed>>> {
1607 template <class Accumulator>
1608 auto accumulate_fields(Accumulator &&accu) const {
1609 namespace bw = borrowable::wire;
1610
1611 accu.step(bw::FixedInt<1>(cmd_byte()));
1612
1613 auto caps = this->caps();
1614
1615 if (caps.test(capabilities::pos::query_attributes)) {
1616 uint64_t param_count = v_.values().size();
1617 accu.step(bw::VarInt(param_count)); // param_count
1618 accu.step(bw::VarInt(1)); // param_set_count: always 1
1619
1620 if (param_count > 0) {
1621 // mark all that are NULL in the nullbits
1622 //
1623 // - one bit per parameter to send
1624 // - if a parameter is NULL, the bit is set, and later no value is
1625 // added.
1626
1627 uint8_t null_bit_byte{};
1628 int bit_pos{};
1629
1630 for (auto const &param : v_.values()) {
1631 if (!param.value) null_bit_byte |= 1 << bit_pos;
1632
1633 if (++bit_pos > 7) {
1634 accu.step(bw::FixedInt<1>(null_bit_byte));
1635
1636 bit_pos = 0;
1637 null_bit_byte = 0;
1638 }
1639 }
1640
1641 if (bit_pos != 0) accu.step(bw::FixedInt<1>(null_bit_byte));
1642
1643 accu.step(bw::FixedInt<1>(1)); // new_param_bind_flag: always 1
1644
1645 for (const auto &param : v_.values()) {
1646 accu.step(bw::FixedInt<2>(param.type_and_flags))
1647 .step(bw::VarString<Borrowed>(param.name));
1648 }
1649
1650 for (const auto &param : v_.values()) {
1651 if (!param.value) continue;
1652
1653 auto type = param.type_and_flags & 0xff;
1654 switch (type) {
1655 case field_type::Bit:
1656 case field_type::Blob:
1659 case field_type::Set:
1660 case field_type::String:
1661 case field_type::Enum:
1666 case field_type::Json:
1669 accu.template step<bw::VarInt>(param.value->size());
1670 break;
1671 case field_type::Date:
1674 case field_type::Time:
1675 assert(param.value->size() <= 255);
1676
1677 accu.template step<bw::FixedInt<1>>(param.value->size());
1678
1679 break;
1681 case field_type::Double:
1682 assert(param.value->size() == 8);
1683
1684 break;
1685 case field_type::Long:
1686 case field_type::Int24:
1687 case field_type::Float:
1688 assert(param.value->size() == 4);
1689
1690 break;
1691 case field_type::Short:
1692 case field_type::Year:
1693 assert(param.value->size() == 2);
1694
1695 break;
1696 case field_type::Tiny:
1697 assert(param.value->size() == 1);
1698
1699 break;
1700 default:
1701 assert(true || "unknown field-type");
1702 break;
1703 }
1704 accu.template step<bw::String<Borrowed>>(*param.value);
1705 }
1706 }
1707 }
1708
1709 accu.step(bw::String<Borrowed>(v_.statement()));
1710 return accu.result();
1711 }
1712
1713 template <class Accu>
1715 Accu &accu, uint8_t type) {
1716 namespace bw = borrowable::wire;
1717
1718 switch (type) {
1719 case field_type::Bit:
1720 case field_type::Blob:
1723 case field_type::Set:
1724 case field_type::String:
1725 case field_type::Enum:
1730 case field_type::Json:
1732 case field_type::Geometry: {
1733 auto string_field_size_res = accu.template step<bw::VarInt>();
1734 if (!accu.result()) {
1735 return stdx::make_unexpected(accu.result().error());
1736 }
1737
1738 return string_field_size_res->value();
1739 }
1740 case field_type::Date:
1743 case field_type::Time: {
1744 auto time_field_size_res = accu.template step<bw::FixedInt<1>>();
1745 if (!accu.result()) {
1746 return stdx::make_unexpected(accu.result().error());
1747 }
1748
1749 return time_field_size_res->value();
1750 }
1752 case field_type::Double:
1753 return 8;
1754 case field_type::Long:
1755 case field_type::Int24:
1756 case field_type::Float:
1757 return 4;
1758 case field_type::Short:
1759 case field_type::Year:
1760 return 2;
1761 case field_type::Tiny:
1762 return 1;
1763 }
1764
1766 }
1767
1768 public:
1771
1772 friend __base;
1773
1775 : __base(caps), v_{std::move(v)} {}
1776
1777 constexpr static uint8_t cmd_byte() noexcept {
1778 return static_cast<uint8_t>(CommandByte::Query);
1779 }
1780
1784
1785 namespace bw = borrowable::wire;
1786
1787 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
1788 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
1789
1790 if (cmd_byte_res->value() != cmd_byte()) {
1792 }
1793
1794 std::vector<typename value_type::Param> params;
1795 if (caps.test(capabilities::pos::query_attributes)) {
1796 //
1797 auto param_count_res = accu.template step<bw::VarInt>();
1798 if (!param_count_res) return param_count_res.get_unexpected();
1799
1800 // currently always 1.
1801 auto param_set_count_res = accu.template step<bw::VarInt>();
1802 if (!param_set_count_res) return param_set_count_res.get_unexpected();
1803
1804 if (param_set_count_res->value() != 1) {
1805 return stdx::make_unexpected(
1807 }
1808
1809 const auto param_count = param_count_res->value();
1810 if (param_count > 0) {
1811 // bit-map
1812 const auto nullbits_res = accu.template step<bw::String<Borrowed>>(
1813 bytes_per_bits(param_count));
1814 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
1815
1816 const auto nullbits = nullbits_res->value();
1817
1818 // always 1
1819 auto new_params_bound_res = accu.template step<bw::FixedInt<1>>();
1820 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
1821
1822 auto new_params_bound = new_params_bound_res->value();
1823 if (new_params_bound != 1) {
1824 // Always 1, malformed packet error of not 1
1825 return stdx::make_unexpected(
1827 }
1828
1829 // redundant, but protocol-docs says:
1830 //
1831 // 'if new-params-bind-flag == 1'
1832 //
1833 // therefore keep it.
1834 if (new_params_bound == 1) {
1835 for (long n{}; n < param_count; ++n) {
1836 auto param_type_res = accu.template step<bw::FixedInt<2>>();
1837 if (!accu.result()) {
1838 return stdx::make_unexpected(accu.result().error());
1839 }
1840 auto param_name_res = accu.template step<bw::VarString<Borrowed>>();
1841 if (!accu.result()) {
1842 return stdx::make_unexpected(accu.result().error());
1843 }
1844
1845 params.emplace_back(param_type_res->value(),
1846 param_name_res->value(),
1847 std::optional<std::string>());
1848 }
1849 }
1850
1851 for (long n{}, nullbit_pos{}, nullbyte_pos{}; n < param_count;
1852 ++n, ++nullbit_pos) {
1853 if (nullbit_pos > 7) {
1854 ++nullbyte_pos;
1855 nullbit_pos = 0;
1856 }
1857
1858 if (!(nullbits[nullbyte_pos] & (1 << nullbit_pos))) {
1859 auto &param = params[n];
1860
1861 auto field_size_res =
1862 decode_field_size(accu, param.type_and_flags & 0xff);
1863 if (!field_size_res) {
1864 return stdx::make_unexpected(field_size_res.error());
1865 }
1866
1867 auto param_value_res = accu.template step<bw::String<Borrowed>>(
1868 field_size_res.value());
1869 if (!accu.result()) {
1870 return stdx::make_unexpected(accu.result().error());
1871 }
1872
1873 param.value = param_value_res->value();
1874 }
1875 }
1876 }
1877 }
1878
1879 auto statement_res = accu.template step<bw::String<Borrowed>>();
1880
1881 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
1882
1883 return std::make_pair(
1884 accu.result().value(),
1885 value_type(statement_res->value(), std::move(params)));
1886 }
1887
1888 private:
1890};
1891
1892/**
1893 * codec for client::SendFile message.
1894 *
1895 * sent by client as response to server::SendFileRequest
1896 *
1897 * format:
1898 *
1899 * - String payload
1900 */
1901template <bool Borrowed>
1902class Codec<borrowable::message::client::SendFile<Borrowed>>
1903 : public impl::EncodeBase<
1904 Codec<borrowable::message::client::SendFile<Borrowed>>> {
1905 template <class Accumulator>
1906 constexpr auto accumulate_fields(Accumulator &&accu) const {
1907 namespace bw = borrowable::wire;
1908
1909 return accu.step(bw::String<Borrowed>(v_.payload())).result();
1910 }
1911
1912 public:
1915
1916 friend __base;
1917
1919 : __base(caps), v_{std::move(v)} {}
1920
1924
1925 namespace bw = borrowable::wire;
1926
1927 auto payload_res = accu.template step<bw::String<Borrowed>>();
1928 if (!accu.result()) return accu.result().get_unexpected();
1929
1930 return std::make_pair(accu.result().value(),
1931 value_type(payload_res->value()));
1932 }
1933
1934 private:
1936};
1937
1938/**
1939 * codec for client's ListFields command.
1940 */
1941template <bool Borrowed>
1942class Codec<borrowable::message::client::ListFields<Borrowed>>
1943 : public impl::EncodeBase<
1944 Codec<borrowable::message::client::ListFields<Borrowed>>> {
1945 template <class Accumulator>
1946 constexpr auto accumulate_fields(Accumulator &&accu) const {
1947 namespace bw = borrowable::wire;
1948
1949 return accu.step(bw::FixedInt<1>(cmd_byte()))
1950 .step(bw::NulTermString<Borrowed>(v_.table_name()))
1951 .step(bw::String<Borrowed>(v_.wildcard()))
1952 .result();
1953 }
1954
1955 public:
1958
1959 friend __base;
1960
1962 : __base(caps), v_{std::move(v)} {}
1963
1964 constexpr static uint8_t cmd_byte() noexcept {
1965 return static_cast<uint8_t>(CommandByte::ListFields);
1966 }
1967
1971
1972 namespace bw = borrowable::wire;
1973
1974 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
1975 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
1976
1977 if (cmd_byte_res->value() != cmd_byte()) {
1979 }
1980
1981 auto table_name_res = accu.template step<bw::NulTermString<Borrowed>>();
1982 auto wildcard_res = accu.template step<bw::String<Borrowed>>();
1983 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
1984
1985 return std::make_pair(
1986 accu.result().value(),
1987 value_type(table_name_res->value(), wildcard_res->value()));
1988 }
1989
1990 private:
1992};
1993
1994/**
1995 * codec for client's Reload command.
1996 */
1997template <>
1999 : public impl::EncodeBase<Codec<borrowable::message::client::Reload>> {
2000 template <class Accumulator>
2001 constexpr auto accumulate_fields(Accumulator &&accu) const {
2002 namespace bw = borrowable::wire;
2003
2004 return accu.step(bw::FixedInt<1>(cmd_byte()))
2005 .step(bw::FixedInt<1>(v_.cmds().to_ulong()))
2006 .result();
2007 }
2008
2009 public:
2012
2013 friend __base;
2014
2016 : __base(caps), v_{std::move(v)} {}
2017
2018 constexpr static uint8_t cmd_byte() noexcept {
2019 return static_cast<uint8_t>(CommandByte::Refresh);
2020 }
2021
2025
2026 namespace bw = borrowable::wire;
2027
2028 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
2029 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
2030
2031 if (cmd_byte_res->value() != cmd_byte()) {
2033 }
2034
2035 auto cmds_res = accu.template step<bw::FixedInt<1>>();
2036 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
2037
2038 return std::make_pair(accu.result().value(), value_type(cmds_res->value()));
2039 }
2040
2041 private:
2043};
2044
2045/**
2046 * codec for client's Kill command.
2047 *
2048 * format:
2049 *
2050 * - FixedInt<1> == 0x0c, ProcessKill
2051 * - FixedInt<4> id
2052 */
2053template <>
2055 : public impl::EncodeBase<Codec<borrowable::message::client::Kill>> {
2056 template <class Accumulator>
2057 constexpr auto accumulate_fields(Accumulator &&accu) const {
2058 namespace bw = borrowable::wire;
2059
2060 return accu.step(bw::FixedInt<1>(cmd_byte()))
2061 .step(bw::FixedInt<4>(v_.connection_id()))
2062 .result();
2063 }
2064
2065 public:
2068
2069 friend __base;
2070
2072 : __base(caps), v_{std::move(v)} {}
2073
2074 constexpr static uint8_t cmd_byte() noexcept {
2075 return static_cast<uint8_t>(CommandByte::ProcessKill);
2076 }
2077
2081
2082 namespace bw = borrowable::wire;
2083
2084 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
2085 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
2086
2087 if (cmd_byte_res->value() != cmd_byte()) {
2089 }
2090
2091 auto connection_id_res = accu.template step<bw::FixedInt<4>>();
2092 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
2093
2094 return std::make_pair(accu.result().value(),
2095 value_type(connection_id_res->value()));
2096 }
2097
2098 private:
2100};
2101
2102/**
2103 * codec for client's Prepared Statement command.
2104 */
2105template <bool Borrowed>
2106class Codec<borrowable::message::client::StmtPrepare<Borrowed>>
2107 : public impl::EncodeBase<
2108 Codec<borrowable::message::client::StmtPrepare<Borrowed>>> {
2109 template <class Accumulator>
2110 constexpr auto accumulate_fields(Accumulator &&accu) const {
2111 namespace bw = borrowable::wire;
2112
2113 return accu.step(bw::FixedInt<1>(cmd_byte()))
2114 .step(bw::String<Borrowed>(v_.statement()))
2115 .result();
2116 }
2117
2118 public:
2121
2122 friend __base;
2123
2125 : __base(caps), v_{std::move(v)} {}
2126
2127 constexpr static uint8_t cmd_byte() noexcept {
2128 return static_cast<uint8_t>(CommandByte::StmtPrepare);
2129 }
2130
2134
2135 namespace bw = borrowable::wire;
2136
2137 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
2138 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
2139
2140 if (cmd_byte_res->value() != cmd_byte()) {
2142 }
2143
2144 auto statement_res = accu.template step<bw::String<Borrowed>>();
2145 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
2146
2147 return std::make_pair(accu.result().value(),
2148 value_type(statement_res->value()));
2149 }
2150
2151 private:
2153};
2154
2155/**
2156 * codec for client's Execute Statement command.
2157 */
2158template <bool Borrowed>
2159class Codec<borrowable::message::client::StmtExecute<Borrowed>>
2160 : public impl::EncodeBase<
2161 Codec<borrowable::message::client::StmtExecute<Borrowed>>> {
2162 template <class Accumulator>
2163 auto accumulate_fields(Accumulator &&accu) const {
2164 namespace bw = borrowable::wire;
2165
2166 auto caps = this->caps();
2167
2168 accu.step(bw::FixedInt<1>(cmd_byte()))
2169 .step(bw::FixedInt<4>(v_.statement_id()))
2170 .step(bw::FixedInt<1>(v_.flags().to_ullong()))
2171 .step(bw::FixedInt<4>(v_.iteration_count()));
2172
2173 // num-params from the StmtPrepareOk
2174 auto num_params = v_.values().size();
2175
2176 const bool supports_query_attributes =
2178
2179 if (supports_query_attributes &&
2180 v_.flags().test(cursor::pos::param_count_available)) {
2181 accu.step(bw::VarInt(num_params));
2182 }
2183
2184 if (num_params == 0) return accu.result();
2185
2186 // mark all that are NULL in the nullbits
2187 //
2188 // - one bit per parameter to send
2189 // - if a parameter is NULL, the bit is set, and later no value is added.
2190 uint8_t null_bit_byte{};
2191 int bit_pos{};
2192
2193 for (auto const &param : v_.values()) {
2194 if (!param.has_value()) null_bit_byte |= 1 << bit_pos;
2195
2196 if (++bit_pos > 7) {
2197 accu.step(bw::FixedInt<1>(null_bit_byte));
2198
2199 bit_pos = 0;
2200 null_bit_byte = 0;
2201 }
2202 }
2203
2204 if (bit_pos != 0) accu.step(bw::FixedInt<1>(null_bit_byte));
2205
2206 accu.step(bw::FixedInt<1>(v_.new_params_bound()));
2207
2208 if (v_.new_params_bound()) {
2209 for (const auto &param_def : v_.types()) {
2210 accu.step(bw::FixedInt<2>(param_def.type_and_flags));
2211
2212 if (supports_query_attributes) {
2213 accu.step(borrowed::wire::VarString(param_def.name));
2214 }
2215 }
2216 }
2217
2218 for (auto [n, v] : stdx::views::enumerate(v_.values())) {
2219 // add all the values that aren't NULL
2220 if (!v.has_value()) continue;
2221
2222 // write length of the type is a variable length
2223 switch (v_.types()[n].type_and_flags & 0xff) {
2224 case field_type::Bit:
2225 case field_type::Blob:
2228 case field_type::Set:
2229 case field_type::String:
2230 case field_type::Enum:
2237 accu.step(bw::VarInt(v->size()));
2238 break;
2239 case field_type::Date:
2242 case field_type::Time:
2243 accu.step(bw::FixedInt<1>(v->size()));
2244 break;
2246 case field_type::Double:
2247 case field_type::Long:
2248 case field_type::Int24:
2249 case field_type::Float:
2250 case field_type::Short:
2251 case field_type::Year:
2252 case field_type::Tiny:
2253 // fixed size
2254 break;
2255 default:
2256 assert(false || "Unknown Type");
2257 }
2258 accu.step(borrowed::wire::String(v.value()));
2259 }
2260
2261 return accu.result();
2262 }
2263
2264 public:
2267
2268 friend __base;
2269
2271 : __base(caps), v_{std::move(val)} {}
2272
2273 constexpr static uint8_t cmd_byte() noexcept {
2274 return static_cast<uint8_t>(CommandByte::StmtExecute);
2275 }
2276
2277 /**
2278 * decode a buffer into a message::client::StmtExecute.
2279 *
2280 * @param buffer a buffer
2281 * @param caps protocol capabilities
2282 * @param metadata_lookup callable that expects a 'uint32_t statement_id'
2283 * that returns a result that's convertible to
2284 * 'stdx::expected<std::vector<ParamDef>, std::error_code>' representing the
2285 * parameter-definitions of the prepared statement
2286 *
2287 * decoding a StmtExecute message requires the parameter-definitions of the
2288 * prepared statement. The metadata_lookup function may be called to get
2289 * the parameter-definitions for the statement-id.
2290 *
2291 * The function may return a parameter-definitions directly
2292 *
2293 * \code
2294 * StmtExecute::decode(
2295 * buffers,
2296 * capabilities::protocol_41,
2297 * [](uint32_t stmt_id) { return std::vector<ParamDef>{}; });
2298 * \endcode
2299 *
2300 * ... or a stdx::expected<std::vector<ParamDef>, std::error_code> if it wants
2301 * to signal that a statement-id wasn't found
2302 *
2303 * \code
2304 * StmtExecute::decode(
2305 * buffers,
2306 * capabilities::protocol_41,
2307 * [](uint32_t stmt_id) ->
2308 * stdx::expected<std::vector<ParamDef>, std::error_code> {
2309 * bool found{true};
2310 *
2311 * if (found) {
2312 * return {};
2313 * } else {
2314 * return stdx::make_unexpected(make_error_code(
2315 * codec_errc::statement_id_not_found));
2316 * }
2317 * });
2318 * \endcode
2319 */
2320 template <class Func>
2323 Func &&metadata_lookup) {
2325
2326 namespace bw = borrowable::wire;
2327
2328 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
2329 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
2330
2331 if (cmd_byte_res->value() != cmd_byte()) {
2333 }
2334
2335 auto statement_id_res = accu.template step<bw::FixedInt<4>>();
2336 auto flags_res = accu.template step<bw::FixedInt<1>>();
2337 auto iteration_count_res = accu.template step<bw::FixedInt<4>>();
2338
2339 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
2340
2342
2343 const bool supports_query_attributes =
2345
2347 metadata_res = metadata_lookup(statement_id_res->value());
2348 if (!metadata_res) {
2349 return stdx::make_unexpected(
2351 }
2352
2353 size_t param_count = metadata_res->size();
2354
2355 if (supports_query_attributes &&
2356 (flags_res->value() & param_count_available) != 0) {
2357 auto param_count_res = accu.template step<bw::VarInt>();
2358 if (!accu.result()) {
2359 return stdx::make_unexpected(accu.result().error());
2360 }
2361
2362 if (static_cast<uint64_t>(param_count_res->value()) < param_count) {
2363 // can the param-count shrink?
2364 return stdx::make_unexpected(
2366 }
2367
2368 param_count = param_count_res->value();
2369 }
2370
2371 if (param_count == 0) {
2372 return std::make_pair(
2373 accu.result().value(),
2374 value_type(statement_id_res->value(), flags_res->value(),
2375 iteration_count_res->value(), false, {}, {}));
2376 }
2377
2378 auto nullbits_res =
2379 accu.template step<bw::String<Borrowed>>(bytes_per_bits(param_count));
2380 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
2381
2382 auto new_params_bound_res = accu.template step<bw::FixedInt<1>>();
2383 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
2384
2385 std::vector<typename value_type::ParamDef> types;
2386
2387 auto new_params_bound = new_params_bound_res->value();
2388 if (new_params_bound == 0) {
2389 // no new params, use the last known params.
2390 types = *metadata_res;
2391 } else if (new_params_bound == 1) {
2392 // check that there is at least enough data for the types (a FixedInt<2>)
2393 // before reserving memory.
2394 if (param_count >= buffer.size() / 2) {
2395 return stdx::make_unexpected(
2397 }
2398
2399 types.reserve(param_count);
2400
2401 for (size_t n{}; n < param_count; ++n) {
2402 auto type_res = accu.template step<bw::FixedInt<2>>();
2403 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
2404
2405 if (supports_query_attributes) {
2406 auto name_res = accu.template step<bw::VarString<Borrowed>>();
2407 if (!accu.result()) {
2408 return stdx::make_unexpected(accu.result().error());
2409 }
2410 types.emplace_back(type_res->value(), name_res->value());
2411 } else {
2412 types.emplace_back(type_res->value());
2413 }
2414 }
2415 } else {
2417 }
2418
2419 if (param_count != types.size()) {
2420 // param-count and available types doesn't match.
2422 }
2423
2424 std::vector<std::optional<typename value_type::string_type>> values;
2425 values.reserve(param_count);
2426
2427 const auto nullbits = nullbits_res->value();
2428 for (size_t n{}, bit_pos{}, byte_pos{}; n < param_count; ++n, ++bit_pos) {
2429 if (bit_pos > 7) {
2430 bit_pos = 0;
2431 ++byte_pos;
2432 }
2433
2434 if (!(nullbits[byte_pos] & (1 << bit_pos))) {
2437 make_error_code(std::errc::invalid_argument)));
2438 switch (types[n].type_and_flags & 0xff) {
2439 case field_type::Bit:
2440 case field_type::Blob:
2443 case field_type::Set:
2444 case field_type::String:
2445 case field_type::Enum:
2451 case field_type::Geometry: {
2452 auto string_field_size_res = accu.template step<bw::VarInt>();
2453 if (!accu.result())
2454 return stdx::make_unexpected(accu.result().error());
2455
2456 field_size_res = string_field_size_res->value();
2457 } break;
2458 case field_type::Date:
2461 case field_type::Time: {
2462 auto time_field_size_res = accu.template step<bw::FixedInt<1>>();
2463 if (!accu.result())
2464 return stdx::make_unexpected(accu.result().error());
2465
2466 field_size_res = time_field_size_res->value();
2467 } break;
2469 case field_type::Double:
2470 field_size_res = 8;
2471 break;
2472 case field_type::Long:
2473 case field_type::Int24:
2474 case field_type::Float:
2475 field_size_res = 4;
2476 break;
2477 case field_type::Short:
2478 case field_type::Year:
2479 field_size_res = 2;
2480 break;
2481 case field_type::Tiny:
2482 field_size_res = 1;
2483 break;
2484 }
2485
2486 if (!field_size_res) {
2487 return stdx::make_unexpected(
2489 }
2490
2491 auto value_res =
2492 accu.template step<bw::String<Borrowed>>(field_size_res.value());
2493 if (!accu.result()) {
2494 return stdx::make_unexpected(accu.result().error());
2495 }
2496
2497 values.push_back(value_res->value());
2498 } else {
2499 // NULL
2500 values.emplace_back(std::nullopt);
2501 }
2502 }
2503
2504 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
2505
2506 return std::make_pair(
2507 accu.result().value(),
2508 value_type(statement_id_res->value(), flags_res->value(),
2509 iteration_count_res->value(), new_params_bound_res->value(),
2510 types, values));
2511 }
2512
2513 private:
2515};
2516
2517/**
2518 * codec for client's append data Statement command.
2519 */
2520template <bool Borrowed>
2522 : public impl::EncodeBase<
2523 Codec<borrowable::message::client::StmtParamAppendData<Borrowed>>> {
2524 template <class Accumulator>
2525 constexpr auto accumulate_fields(Accumulator &&accu) const {
2526 namespace bw = borrowable::wire;
2527
2528 return accu.step(bw::FixedInt<1>(cmd_byte()))
2529 .step(bw::FixedInt<4>(v_.statement_id()))
2530 .step(bw::FixedInt<2>(v_.param_id()))
2531 .step(bw::String<Borrowed>(v_.data()))
2532 .result();
2533 }
2534
2535 public:
2538
2539 friend __base;
2540
2542 : __base(caps), v_{std::move(v)} {}
2543
2544 constexpr static uint8_t cmd_byte() noexcept {
2545 return static_cast<uint8_t>(CommandByte::StmtSendLongData);
2546 }
2547
2551
2552 namespace bw = borrowable::wire;
2553
2554 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
2555 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
2556
2557 if (cmd_byte_res->value() != cmd_byte()) {
2559 }
2560
2561 auto statement_id_res = accu.template step<bw::FixedInt<4>>();
2562 auto param_id_res = accu.template step<bw::FixedInt<2>>();
2563 auto data_res = accu.template step<bw::String<Borrowed>>();
2564 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
2565
2566 return std::make_pair(accu.result().value(),
2567 value_type(statement_id_res->value(),
2568 param_id_res->value(), data_res->value()));
2569 }
2570
2571 private:
2573};
2574
2575/**
2576 * codec for client's Close Statement command.
2577 */
2578template <>
2580 : public impl::EncodeBase<Codec<borrowable::message::client::StmtClose>> {
2581 template <class Accumulator>
2582 constexpr auto accumulate_fields(Accumulator &&accu) const {
2583 namespace bw = borrowable::wire;
2584
2585 return accu.step(bw::FixedInt<1>(cmd_byte()))
2586 .step(bw::FixedInt<4>(v_.statement_id()))
2587 .result();
2588 }
2589
2590 public:
2593
2594 friend __base;
2595
2597 : __base(caps), v_{std::move(v)} {}
2598
2599 constexpr static uint8_t cmd_byte() noexcept {
2600 return static_cast<uint8_t>(CommandByte::StmtClose);
2601 }
2602
2606
2607 namespace bw = borrowable::wire;
2608
2609 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
2610 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
2611
2612 if (cmd_byte_res->value() != cmd_byte()) {
2614 }
2615
2616 auto statement_id_res = accu.template step<bw::FixedInt<4>>();
2617 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
2618
2619 return std::make_pair(accu.result().value(),
2620 value_type(statement_id_res->value()));
2621 }
2622
2623 private:
2625};
2626
2627/**
2628 * codec for client's Reset Statement command.
2629 */
2630template <>
2632 : public impl::EncodeBase<Codec<borrowable::message::client::StmtReset>> {
2633 template <class Accumulator>
2634 constexpr auto accumulate_fields(Accumulator &&accu) const {
2635 namespace bw = borrowable::wire;
2636
2637 return accu.step(bw::FixedInt<1>(cmd_byte()))
2638 .step(bw::FixedInt<4>(v_.statement_id()))
2639 .result();
2640 }
2641
2642 public:
2645
2646 friend __base;
2647
2649 : __base(caps), v_{std::move(v)} {}
2650
2651 constexpr static uint8_t cmd_byte() noexcept {
2652 return static_cast<uint8_t>(CommandByte::StmtReset);
2653 }
2654
2658
2659 namespace bw = borrowable::wire;
2660
2661 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
2662 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
2663
2664 if (cmd_byte_res->value() != cmd_byte()) {
2666 }
2667
2668 auto statement_id_res = accu.template step<bw::FixedInt<4>>();
2669 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
2670
2671 return std::make_pair(accu.result().value(),
2672 value_type(statement_id_res->value()));
2673 }
2674
2675 private:
2677};
2678
2679/**
2680 * codec for client's SetOption command.
2681 */
2682template <>
2684 : public impl::EncodeBase<Codec<borrowable::message::client::SetOption>> {
2685 template <class Accumulator>
2686 constexpr auto accumulate_fields(Accumulator &&accu) const {
2687 namespace bw = borrowable::wire;
2688
2689 return accu.step(bw::FixedInt<1>(cmd_byte()))
2690 .step(bw::FixedInt<2>(v_.option()))
2691 .result();
2692 }
2693
2694 public:
2697
2698 friend __base;
2699
2701 : __base(caps), v_{std::move(v)} {}
2702
2703 constexpr static uint8_t cmd_byte() noexcept {
2704 return static_cast<uint8_t>(CommandByte::SetOption);
2705 }
2706
2710
2711 namespace bw = borrowable::wire;
2712
2713 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
2714 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
2715
2716 if (cmd_byte_res->value() != cmd_byte()) {
2718 }
2719
2720 auto option_res = accu.template step<bw::FixedInt<2>>();
2721 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
2722
2723 return std::make_pair(accu.result().value(),
2724 value_type(option_res->value()));
2725 }
2726
2727 private:
2729};
2730
2731/**
2732 * codec for client's Fetch Cursor command.
2733 */
2734template <>
2736 : public impl::EncodeBase<Codec<borrowable::message::client::StmtFetch>> {
2737 template <class Accumulator>
2738 constexpr auto accumulate_fields(Accumulator &&accu) const {
2739 namespace bw = borrowable::wire;
2740
2741 return accu.step(bw::FixedInt<1>(cmd_byte()))
2742 .step(bw::FixedInt<4>(v_.statement_id()))
2743 .step(bw::FixedInt<4>(v_.row_count()))
2744 .result();
2745 }
2746
2747 public:
2750
2751 friend __base;
2752
2754 : __base(caps), v_{std::move(v)} {}
2755
2756 constexpr static uint8_t cmd_byte() noexcept {
2757 return static_cast<uint8_t>(CommandByte::StmtFetch);
2758 }
2759
2763
2764 namespace bw = borrowable::wire;
2765
2766 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
2767 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
2768
2769 if (cmd_byte_res->value() != cmd_byte()) {
2771 }
2772
2773 auto statement_id_res = accu.template step<bw::FixedInt<4>>();
2774 auto row_count_res = accu.template step<bw::FixedInt<4>>();
2775 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
2776
2777 return std::make_pair(
2778 accu.result().value(),
2779 value_type(statement_id_res->value(), row_count_res->value()));
2780 }
2781
2782 private:
2784};
2785
2786/**
2787 * codec for client side greeting message.
2788 *
2789 *
2790 * in 3.21 ... 4.0:
2791 *
2792 * FixedInt<2> capabilities [protocol_41 not set]
2793 * FixedInt<3> max-allowed-packet
2794 * NulTermString username
2795 * NulTermString auth-method-data
2796 *
2797 * [if not connect_with_schema, there may be no trailing Nul-byte]
2798 *
2799 * if connect_with_schema {
2800 * String schema
2801 * }
2802 *
2803 * the auth-method is "old_password" if "protocol_version == 10 &&
2804 * (capabilities & long_password)", it is "older_password" otherwise
2805 *
2806 * FixedInt<2> capabilities_lo [protocol_41 set]
2807 * FixedInt<2> capabilities_hi
2808 * FixedInt<4> max_allowed-packet
2809 * ...
2810 *
2811 * The capabilities that are part of the message are the client's capabilities
2812 * (which may announce more than what the server supports). The codec
2813 * uses the capabilities that are shared between client and server to decide
2814 * which parts and how they are understood, though.
2815 *
2816 * checked capabilities:
2817 * - protocol_41
2818 * - ssl
2819 * - client_auth_method_data_varint
2820 * - secure_connection
2821 * - connect_with_schema
2822 * - plugin_auth
2823 * - connect_attributes
2824 */
2825template <bool Borrowed>
2826class Codec<borrowable::message::client::Greeting<Borrowed>>
2827 : public impl::EncodeBase<
2828 Codec<borrowable::message::client::Greeting<Borrowed>>> {
2829 template <class Accumulator>
2830 constexpr auto accumulate_fields(Accumulator &&accu) const {
2831 namespace bw = borrowable::wire;
2832
2833 const auto shared_caps = v_.capabilities() & this->caps();
2834
2836 accu.step(bw::FixedInt<4>(v_.capabilities().to_ulong()))
2837 .step(bw::FixedInt<4>(v_.max_packet_size()))
2838 .step(bw::FixedInt<1>(v_.collation()))
2839 .step(bw::String<Borrowed>(std::string(23, '\0')));
2840 if (!(shared_caps[classic_protocol::capabilities::pos::ssl] &&
2841 v_.username().empty())) {
2842 // the username is empty and SSL is set, this is a short SSL-greeting
2843 // packet
2844 accu.step(bw::NulTermString<Borrowed>(v_.username()));
2845
2846 if (shared_caps[classic_protocol::capabilities::pos::
2848 accu.step(bw::VarString<Borrowed>(v_.auth_method_data()));
2849 } else if (shared_caps[classic_protocol::capabilities::pos::
2851 accu.step(bw::FixedInt<1>(v_.auth_method_data().size()))
2852 .step(bw::String<Borrowed>(v_.auth_method_data()));
2853 } else {
2854 accu.step(bw::NulTermString<Borrowed>(v_.auth_method_data()));
2855 }
2856
2857 if (shared_caps
2859 accu.step(bw::NulTermString<Borrowed>(v_.schema()));
2860 }
2861
2862 if (!shared_caps
2864 // special handling for off-spec client/server implementations.
2865 //
2866 // 1. older clients may set ::plugin_auth, but
2867 // ::connection_attributes which means nothing follows the
2868 // "auth-method-name" field
2869 // 2. auth-method-name is empty, it MAY be skipped.
2871 !v_.auth_method_name().empty()) {
2872 accu.step(bw::NulTermString<Borrowed>(v_.auth_method_name()));
2873 }
2874 } else {
2876 accu.step(bw::NulTermString<Borrowed>(v_.auth_method_name()));
2877 }
2878
2879 accu.step(bw::VarString<Borrowed>(v_.attributes()));
2880 }
2881 }
2882 } else {
2883 accu.step(bw::FixedInt<2>(v_.capabilities().to_ulong()))
2884 .step(bw::FixedInt<3>(v_.max_packet_size()))
2885 .step(bw::NulTermString<Borrowed>(v_.username()));
2886 if (shared_caps
2888 accu.step(bw::NulTermString<Borrowed>(v_.auth_method_data()))
2889 .step(bw::String<Borrowed>(v_.schema()));
2890 } else {
2891 accu.step(bw::String<Borrowed>(v_.auth_method_data()));
2892 }
2893 }
2894
2895 return accu.result();
2896 }
2897
2898 public:
2901
2902 friend __base;
2903
2905 : __base(caps), v_{std::move(v)} {}
2906
2910
2911 namespace bw = borrowable::wire;
2912
2913 auto capabilities_lo_res = accu.template step<bw::FixedInt<2>>();
2914 if (!capabilities_lo_res)
2915 return stdx::make_unexpected(capabilities_lo_res.error());
2916
2917 auto client_capabilities = classic_protocol::capabilities::value_type(
2918 capabilities_lo_res->value());
2919
2920 // decoding depends on the capabilities that both client and server have
2921 // in common
2922 auto shared_capabilities = caps & client_capabilities;
2923
2924 if (shared_capabilities[classic_protocol::capabilities::pos::protocol_41]) {
2925 // if protocol_41 is set in the capabilities, we expected 2 more bytes
2926 // of capabilities
2927 auto capabilities_hi_res = accu.template step<bw::FixedInt<2>>();
2928 if (!capabilities_hi_res)
2929 return stdx::make_unexpected(capabilities_hi_res.error());
2930
2931 client_capabilities |= classic_protocol::capabilities::value_type(
2932 capabilities_hi_res->value() << 16);
2933
2934 shared_capabilities = caps & client_capabilities;
2935
2936 auto max_packet_size_res = accu.template step<bw::FixedInt<4>>();
2937 auto collation_res = accu.template step<bw::FixedInt<1>>();
2938
2939 accu.template step<bw::String<Borrowed>>(23); // skip 23 bytes
2940
2941 auto last_accu_res = accu.result();
2942
2943 auto username_res = accu.template step<bw::NulTermString<Borrowed>>();
2944 if (!accu.result()) {
2945 // if there isn't enough data for the nul-term-string, but we had the
2946 // 23-bytes ...
2947 if (last_accu_res &&
2948 shared_capabilities[classic_protocol::capabilities::pos::ssl]) {
2949 return std::make_pair(
2950 last_accu_res.value(),
2951 value_type(client_capabilities, max_packet_size_res->value(),
2952 collation_res->value(), {}, {}, {}, {}, {}));
2953 }
2954
2955 return stdx::make_unexpected(accu.result().error());
2956 }
2957
2958 // auth-method-data is either
2959 //
2960 // - varint length
2961 // - fixed-int-1 length
2962 // - null-term-string
2963 stdx::expected<bw::String<Borrowed>, std::error_code>
2964 auth_method_data_res;
2965 if (shared_capabilities[classic_protocol::capabilities::pos::
2967 auto res = accu.template step<bw::VarString<Borrowed>>();
2968 if (!res) return stdx::make_unexpected(res.error());
2969
2970 auth_method_data_res = bw::String<Borrowed>(res->value());
2971 } else if (shared_capabilities
2973 auto auth_method_data_len_res = accu.template step<bw::FixedInt<1>>();
2974 if (!auth_method_data_len_res)
2975 return stdx::make_unexpected(auth_method_data_len_res.error());
2976 auto auth_method_data_len = auth_method_data_len_res->value();
2977
2978 auto res =
2979 accu.template step<bw::String<Borrowed>>(auth_method_data_len);
2980 if (!res) return stdx::make_unexpected(res.error());
2981
2982 auth_method_data_res = bw::String<Borrowed>(res->value());
2983 } else {
2984 auto res = accu.template step<bw::NulTermString<Borrowed>>();
2985 if (!res) return stdx::make_unexpected(res.error());
2986
2987 auth_method_data_res = bw::String<Borrowed>(res->value());
2988 }
2989
2990 stdx::expected<bw::NulTermString<Borrowed>, std::error_code> schema_res;
2991 if (shared_capabilities
2993 schema_res = accu.template step<bw::NulTermString<Borrowed>>();
2994 }
2995 if (!schema_res) return stdx::make_unexpected(schema_res.error());
2996
2998 auth_method_res;
2999 if (shared_capabilities
3001 if (net::buffer_size(buffer) == accu.result().value()) {
3002 // even with plugin_auth set, the server is fine, if no
3003 // auth_method_name is sent.
3004 auth_method_res = bw::NulTermString<Borrowed>{};
3005 } else {
3006 auth_method_res = accu.template step<bw::NulTermString<Borrowed>>();
3007 }
3008 }
3009 if (!auth_method_res)
3010 return stdx::make_unexpected(auth_method_res.error());
3011
3012 stdx::expected<bw::VarString<Borrowed>, std::error_code> attributes_res;
3013 if (shared_capabilities
3015 attributes_res = accu.template step<bw::VarString<Borrowed>>();
3016 }
3017
3018 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
3019
3020 return std::make_pair(
3021 accu.result().value(),
3022 value_type(client_capabilities, max_packet_size_res->value(),
3023 collation_res->value(), username_res->value(),
3024 auth_method_data_res->value(), schema_res->value(),
3025 auth_method_res->value(), attributes_res->value()));
3026
3027 } else {
3028 auto max_packet_size_res = accu.template step<bw::FixedInt<3>>();
3029
3030 auto username_res = accu.template step<bw::NulTermString<Borrowed>>();
3031
3032 stdx::expected<bw::String<Borrowed>, std::error_code>
3033 auth_method_data_res;
3034 stdx::expected<bw::String<Borrowed>, std::error_code> schema_res;
3035
3036 if (shared_capabilities
3038 auto res = accu.template step<bw::NulTermString<Borrowed>>();
3039 if (!res) return stdx::make_unexpected(res.error());
3040
3041 // auth_method_data is a wire::String, move it over
3042 auth_method_data_res = bw::String<Borrowed>(res->value());
3043
3044 schema_res = accu.template step<bw::String<Borrowed>>();
3045 } else {
3046 auth_method_data_res = accu.template step<bw::String<Borrowed>>();
3047 }
3048
3049 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
3050
3051 // idea: benchmark in-place constructor where all parameters are passed
3052 // down to the lowest level.
3053 //
3054 // It should involve less copy-construction.
3055 //
3056 // - stdx::in_place is for in-place construction of stdx::expected's
3057 // value
3058 // - std::piecewise_construct for the parts of the std::pair that is
3059 // returned as value of stdx::expected
3060 //
3061 // return {stdx::in_place, std::piecewise_construct,
3062 // std::forward_as_tuple(accu.result().value()),
3063 // std::forward_as_tuple(capabilities,
3064 // max_packet_size_res->value(),
3065 // 0x00, username_res->value(),
3066 // auth_method_data_res->value(),
3067 // schema_res->value(), {},
3068 // {})};
3069 return std::make_pair(
3070 accu.result().value(),
3071 value_type(client_capabilities, max_packet_size_res->value(), 0x00,
3072 username_res->value(), auth_method_data_res->value(),
3073 schema_res->value(), {}, {}));
3074 }
3075 }
3076
3077 private:
3079};
3080
3081/**
3082 * codec for client::AuthMethodData message.
3083 *
3084 * format:
3085 *
3086 * - String auth_method_data
3087 *
3088 * sent after server::AuthMethodData or server::AuthMethodContinue
3089 */
3090template <bool Borrowed>
3091class Codec<borrowable::message::client::AuthMethodData<Borrowed>>
3092 : public impl::EncodeBase<
3093 Codec<borrowable::message::client::AuthMethodData<Borrowed>>> {
3094 template <class Accumulator>
3095 constexpr auto accumulate_fields(Accumulator &&accu) const {
3096 namespace bw = borrowable::wire;
3097
3098 return accu.step(bw::String<Borrowed>(v_.auth_method_data())).result();
3099 }
3100
3101 public:
3104
3105 friend __base;
3106
3108 : __base(caps), v_{std::move(v)} {}
3109
3113
3114 namespace bw = borrowable::wire;
3115
3116 auto auth_method_data_res = accu.template step<bw::String<Borrowed>>();
3117
3118 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
3119
3120 return std::make_pair(accu.result().value(),
3121 value_type(auth_method_data_res->value()));
3122 }
3123
3124 private:
3126};
3127
3128/**
3129 * codec for client side change-user message.
3130 *
3131 * checked capabilities:
3132 * - protocol_41
3133 * - secure_connection
3134 * - plugin_auth
3135 * - connect_attributes
3136 */
3137template <bool Borrowed>
3138class Codec<borrowable::message::client::ChangeUser<Borrowed>>
3139 : public impl::EncodeBase<
3140 Codec<borrowable::message::client::ChangeUser<Borrowed>>> {
3141 template <class Accumulator>
3142 constexpr auto accumulate_fields(Accumulator &&accu) const {
3143 namespace bw = borrowable::wire;
3144
3145 accu.step(bw::FixedInt<1>(cmd_byte()))
3146 .step(bw::NulTermString<Borrowed>(v_.username()));
3147
3149 accu.step(bw::FixedInt<1>(v_.auth_method_data().size()))
3150 .step(bw::String<Borrowed>(v_.auth_method_data()));
3151 } else {
3152 accu.step(bw::NulTermString<Borrowed>(v_.auth_method_data()));
3153 }
3154 accu.step(bw::NulTermString<Borrowed>(v_.schema()));
3155
3156 // 4.1 and later have a collation
3157 //
3158 // this could be checked via the protocol_41 capability, but that's not
3159 // what the server does
3160 if (v_.collation() != 0x00 ||
3163 accu.step(bw::FixedInt<2>(v_.collation()));
3165 accu.step(bw::NulTermString<Borrowed>(v_.auth_method_name()));
3166 }
3167
3168 if (this->caps()
3170 accu.step(bw::VarString<Borrowed>(v_.attributes()));
3171 }
3172 }
3173
3174 return accu.result();
3175 }
3176
3177 public:
3180
3181 friend __base;
3182
3184 : __base(caps), v_{std::move(v)} {}
3185
3186 constexpr static uint8_t cmd_byte() noexcept {
3187 return static_cast<uint8_t>(CommandByte::ChangeUser);
3188 }
3189
3193
3194 namespace bw = borrowable::wire;
3195
3196 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
3197 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
3198
3199 if (cmd_byte_res->value() != cmd_byte()) {
3201 }
3202 auto username_res = accu.template step<bw::NulTermString<Borrowed>>();
3203
3204 // auth-method-data is either
3205 //
3206 // - fixed-int-1 length
3207 // - null-term-string
3208 stdx::expected<bw::String<Borrowed>, std::error_code> auth_method_data_res;
3210 auto auth_method_data_len_res = accu.template step<bw::FixedInt<1>>();
3211 if (!auth_method_data_len_res)
3212 return stdx::make_unexpected(auth_method_data_len_res.error());
3213 auto auth_method_data_len = auth_method_data_len_res->value();
3214
3215 auto res = accu.template step<bw::String<Borrowed>>(auth_method_data_len);
3216 if (!res) return stdx::make_unexpected(res.error());
3217
3218 auth_method_data_res = bw::String<Borrowed>(res->value());
3219 } else {
3220 auto res = accu.template step<bw::NulTermString<Borrowed>>();
3221 if (!res) return stdx::make_unexpected(res.error());
3222
3223 auth_method_data_res = bw::String<Borrowed>(res->value());
3224 }
3225
3226 auto schema_res = accu.template step<bw::NulTermString<Borrowed>>();
3227
3228 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
3229
3230 // 3.23.x-4.0 don't send more.
3231 if (buffer_size(buffer) <= accu.result().value()) {
3232 return std::make_pair(
3233 accu.result().value(),
3234 value_type(username_res->value(), auth_method_data_res->value(),
3235 schema_res->value(), 0x00, {}, {}));
3236 }
3237
3238 // added in 4.1
3239 auto collation_res = accu.template step<bw::FixedInt<2>>();
3240
3242 auth_method_name_res;
3244 auth_method_name_res = accu.template step<bw::NulTermString<Borrowed>>();
3245 }
3246
3247 stdx::expected<bw::VarString<Borrowed>, std::error_code> attributes_res;
3249 attributes_res = accu.template step<bw::VarString<Borrowed>>();
3250 }
3251
3252 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
3253
3254 return std::make_pair(
3255 accu.result().value(),
3256 value_type(username_res->value(), auth_method_data_res->value(),
3257 schema_res->value(), collation_res->value(),
3258 auth_method_name_res->value(), attributes_res->value()));
3259 }
3260
3261 private:
3263};
3264
3265/**
3266 * codec for client's Clone command.
3267 *
3268 * response: server::Ok or server::Error
3269 */
3270template <>
3272 : public CodecSimpleCommand<Codec<borrowable::message::client::Clone>,
3273 borrowable::message::client::Clone> {
3274 public:
3277
3279
3280 constexpr static uint8_t cmd_byte() noexcept {
3281 return static_cast<uint8_t>(CommandByte::Clone);
3282 }
3283};
3284
3285/**
3286 * codec for client side dump-binlog message.
3287 */
3288template <bool Borrowed>
3289class Codec<borrowable::message::client::BinlogDump<Borrowed>>
3290 : public impl::EncodeBase<
3291 Codec<borrowable::message::client::BinlogDump<Borrowed>>> {
3292 public:
3294
3295 private:
3296 template <class Accumulator>
3297 constexpr auto accumulate_fields(Accumulator &&accu) const {
3298 namespace bw = borrowable::wire;
3299
3300 return accu.step(bw::FixedInt<1>(cmd_byte()))
3301 .step(bw::FixedInt<4>(v_.position()))
3302 .step(bw::FixedInt<2>(v_.flags().underlying_value()))
3303 .step(bw::FixedInt<4>(v_.server_id()))
3304 .step(bw::String<Borrowed>(v_.filename()))
3305 .result();
3306 }
3307
3308 public:
3310
3311 friend __base;
3312
3314 : __base(caps), v_{std::move(v)} {}
3315
3316 constexpr static uint8_t cmd_byte() noexcept {
3317 return static_cast<uint8_t>(CommandByte::BinlogDump);
3318 }
3319
3323
3324 namespace bw = borrowable::wire;
3325
3326 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
3327 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
3328
3329 if (cmd_byte_res->value() != cmd_byte()) {
3331 }
3332 auto position_res = accu.template step<bw::FixedInt<4>>();
3333 auto flags_res = accu.template step<bw::FixedInt<2>>();
3334 auto server_id_res = accu.template step<bw::FixedInt<4>>();
3335
3336 auto filename_res = accu.template step<bw::String<Borrowed>>();
3337
3338 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
3339
3341 flags.underlying_value(flags_res->value());
3342
3343 return std::make_pair(
3344 accu.result().value(),
3345 value_type(flags, server_id_res->value(), filename_res->value(),
3346 position_res->value()));
3347 }
3348
3349 private:
3351};
3352
3353/**
3354 * codec for client side register-replica message.
3355 */
3356template <bool Borrowed>
3357class Codec<borrowable::message::client::RegisterReplica<Borrowed>>
3358 : public impl::EncodeBase<
3359 Codec<borrowable::message::client::RegisterReplica<Borrowed>>> {
3360 public:
3362
3363 private:
3364 template <class Accumulator>
3365 constexpr auto accumulate_fields(Accumulator &&accu) const {
3366 namespace bw = borrowable::wire;
3367
3368 return accu.step(bw::FixedInt<1>(cmd_byte()))
3369 .step(bw::FixedInt<4>(v_.server_id()))
3370 .step(bw::FixedInt<1>(v_.hostname().size()))
3371 .step(bw::String<Borrowed>(v_.hostname()))
3372 .step(bw::FixedInt<1>(v_.username().size()))
3373 .step(bw::String<Borrowed>(v_.username()))
3374 .step(bw::FixedInt<1>(v_.password().size()))
3375 .step(bw::String<Borrowed>(v_.password()))
3376 .step(bw::FixedInt<2>(v_.port()))
3377 .step(bw::FixedInt<4>(v_.replication_rank()))
3378 .step(bw::FixedInt<4>(v_.master_id()))
3379 .result();
3380 }
3381
3382 public:
3384
3385 friend __base;
3386
3388 : __base(caps), v_{std::move(v)} {}
3389
3390 constexpr static uint8_t cmd_byte() noexcept {
3391 return static_cast<uint8_t>(CommandByte::RegisterReplica);
3392 }
3393
3397
3398 namespace bw = borrowable::wire;
3399
3400 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
3401 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
3402
3403 if (cmd_byte_res->value() != cmd_byte()) {
3405 }
3406 auto server_id_res = accu.template step<bw::FixedInt<4>>();
3407 auto hostname_len_res = accu.template step<bw::FixedInt<1>>();
3408 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
3409
3410 auto hostname_res =
3411 accu.template step<bw::String<Borrowed>>(hostname_len_res->value());
3412
3413 auto username_len_res = accu.template step<bw::FixedInt<1>>();
3414 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
3415
3416 auto username_res =
3417 accu.template step<bw::String<Borrowed>>(username_len_res->value());
3418
3419 auto password_len_res = accu.template step<bw::FixedInt<1>>();
3420 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
3421
3422 auto password_res =
3423 accu.template step<bw::String<Borrowed>>(password_len_res->value());
3424
3425 auto port_res = accu.template step<bw::FixedInt<2>>();
3426 auto replication_rank_res = accu.template step<bw::FixedInt<4>>();
3427 auto master_id_res = accu.template step<bw::FixedInt<4>>();
3428
3429 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
3430
3431 return std::make_pair(
3432 accu.result().value(),
3433 value_type(server_id_res->value(), hostname_res->value(),
3434 username_res->value(), password_res->value(),
3435 port_res->value(), replication_rank_res->value(),
3436 master_id_res->value()));
3437 }
3438
3439 private:
3441};
3442
3443/**
3444 * codec for client side dump-binlog-with-gtid message.
3445 */
3446template <bool Borrowed>
3447class Codec<borrowable::message::client::BinlogDumpGtid<Borrowed>>
3448 : public impl::EncodeBase<
3449 Codec<borrowable::message::client::BinlogDumpGtid<Borrowed>>> {
3450 public:
3452
3453 private:
3454 template <class Accumulator>
3455 constexpr auto accumulate_fields(Accumulator &&accu) const {
3456 namespace bw = borrowable::wire;
3457
3458 accu.step(bw::FixedInt<1>(cmd_byte()))
3459 .step(bw::FixedInt<2>(v_.flags().underlying_value()))
3460 .step(bw::FixedInt<4>(v_.server_id()))
3461 .step(bw::FixedInt<4>(v_.filename().size()))
3462 .step(bw::String<Borrowed>(v_.filename()))
3463 .step(bw::FixedInt<8>(v_.position()));
3464
3465 if (v_.flags() & value_type::Flags::through_gtid) {
3466 accu.step(bw::FixedInt<4>(v_.sids().size()))
3467 .step(bw::String<Borrowed>(v_.sids()));
3468 }
3469
3470 return accu.result();
3471 }
3472
3473 public:
3475
3476 friend base_;
3477
3479 : base_(caps), v_{std::move(val)} {}
3480
3481 constexpr static uint8_t cmd_byte() noexcept {
3482 return static_cast<uint8_t>(CommandByte::BinlogDumpGtid);
3483 }
3484
3488
3489 namespace bw = borrowable::wire;
3490
3491 auto cmd_byte_res = accu.template step<bw::FixedInt<1>>();
3492 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
3493
3494 if (cmd_byte_res->value() != cmd_byte()) {
3496 }
3497 auto flags_res = accu.template step<bw::FixedInt<2>>();
3498 auto server_id_res = accu.template step<bw::FixedInt<4>>();
3499 auto filename_len_res = accu.template step<bw::FixedInt<4>>();
3500 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
3501
3502 auto filename_res =
3503 accu.template step<bw::String<Borrowed>>(filename_len_res->value());
3504 auto position_res = accu.template step<bw::FixedInt<8>>();
3505
3507 flags.underlying_value(flags_res->value());
3508
3509 if (!(flags & value_type::Flags::through_gtid)) {
3510 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
3511
3512 return std::make_pair(
3513 accu.result().value(),
3514 value_type(flags, server_id_res->value(), filename_res->value(),
3515 position_res->value(), {}));
3516 }
3517
3518 auto sids_len_res = accu.template step<bw::FixedInt<4>>();
3519 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
3520
3521 auto sids_res =
3522 accu.template step<bw::String<Borrowed>>(sids_len_res->value());
3523
3524 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
3525
3526 return std::make_pair(
3527 accu.result().value(),
3528 value_type(flags, server_id_res->value(), filename_res->value(),
3529 position_res->value(), sids_res->value()));
3530 }
3531
3532 private:
3534};
3535
3536} // namespace classic_protocol
3537
3538#endif
CRTP base for client-side commands that are encoded as a single byte.
Definition: classic_protocol_codec_message.h:1405
constexpr CodecSimpleCommand(capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:1418
friend __base
Definition: classic_protocol_codec_message.h:1416
static constexpr size_t max_size() noexcept
Definition: classic_protocol_codec_message.h:1420
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:1422
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:1407
const value_type v_
Definition: classic_protocol_codec_message.h:3125
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:3110
friend __base
Definition: classic_protocol_codec_message.h:3105
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:3095
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:3107
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:3481
const value_type v_
Definition: classic_protocol_codec_message.h:3533
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:3485
constexpr Codec(value_type val, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:3478
friend base_
Definition: classic_protocol_codec_message.h:3476
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:3455
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:3313
friend __base
Definition: classic_protocol_codec_message.h:3311
const value_type v_
Definition: classic_protocol_codec_message.h:3350
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:3320
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:3297
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:3316
const value_type v_
Definition: classic_protocol_codec_message.h:3262
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:3186
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:3190
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:3183
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:3142
friend __base
Definition: classic_protocol_codec_message.h:3181
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:3280
constexpr Codec(value_type, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:3278
friend __base
Definition: classic_protocol_codec_message.h:2902
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:2907
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:2904
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:2830
const value_type v_
Definition: classic_protocol_codec_message.h:3078
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:1576
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:1555
const value_type v_
Definition: classic_protocol_codec_message.h:1597
friend __base
Definition: classic_protocol_codec_message.h:1567
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:1569
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:1572
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:2057
value_type v_
Definition: classic_protocol_codec_message.h:2099
friend __base
Definition: classic_protocol_codec_message.h:2069
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:2078
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:2074
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:2071
const value_type v_
Definition: classic_protocol_codec_message.h:1991
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:1961
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:1964
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:1946
friend __base
Definition: classic_protocol_codec_message.h:1959
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:1968
constexpr Codec(value_type, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:1522
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:1524
const value_type v_
Definition: classic_protocol_codec_message.h:1889
friend __base
Definition: classic_protocol_codec_message.h:1772
auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:1608
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:1781
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:1777
static stdx::expected< size_t, std::error_code > decode_field_size(Accu &accu, uint8_t type)
Definition: classic_protocol_codec_message.h:1714
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:1774
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:1487
constexpr Codec(value_type, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:1485
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:3365
const value_type v_
Definition: classic_protocol_codec_message.h:3440
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:3390
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:3387
friend __base
Definition: classic_protocol_codec_message.h:3385
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:3394
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:2001
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:2018
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:2015
friend __base
Definition: classic_protocol_codec_message.h:2013
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:2022
const value_type v_
Definition: classic_protocol_codec_message.h:2042
constexpr Codec(value_type, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:1504
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:1506
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:1921
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:1906
friend __base
Definition: classic_protocol_codec_message.h:1916
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:1918
const value_type v_
Definition: classic_protocol_codec_message.h:1935
const value_type v_
Definition: classic_protocol_codec_message.h:2728
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:2707
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:2700
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:2686
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:2703
friend __base
Definition: classic_protocol_codec_message.h:2698
constexpr Codec(value_type, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:1540
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:1542
friend __base
Definition: classic_protocol_codec_message.h:2594
const value_type v_
Definition: classic_protocol_codec_message.h:2624
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:2599
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:2582
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:2603
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:2596
friend __base
Definition: classic_protocol_codec_message.h:2268
const value_type v_
Definition: classic_protocol_codec_message.h:2514
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:2321
auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:2163
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:2273
constexpr Codec(value_type val, capabilities::value_type caps)
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:2760
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:2756
const value_type v_
Definition: classic_protocol_codec_message.h:2783
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:2738
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:2753
friend __base
Definition: classic_protocol_codec_message.h:2751
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:2541
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:2544
const value_type v_
Definition: classic_protocol_codec_message.h:2572
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:2548
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:2525
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:2127
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:2131
const value_type v_
Definition: classic_protocol_codec_message.h:2152
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:2124
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:2110
friend __base
Definition: classic_protocol_codec_message.h:2122
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:2651
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:2655
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:2634
friend __base
Definition: classic_protocol_codec_message.h:2646
const value_type v_
Definition: classic_protocol_codec_message.h:2676
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:2648
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:326
const value_type v_
Definition: classic_protocol_codec_message.h:352
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:312
borrowable::message::server::AuthMethodData< Borrowed > value_type
Definition: classic_protocol_codec_message.h:321
static constexpr uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:329
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:331
friend __base
Definition: classic_protocol_codec_message.h:324
borrowable::message::server::AuthMethodSwitch< Borrowed > value_type
Definition: classic_protocol_codec_message.h:262
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:267
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:248
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:272
static constexpr uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:270
const value_type v_
Definition: classic_protocol_codec_message.h:301
borrowable::message::server::ColumnCount value_type
Definition: classic_protocol_codec_message.h:746
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:751
friend __base
Definition: classic_protocol_codec_message.h:749
const value_type v_
Definition: classic_protocol_codec_message.h:772
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:739
static constexpr size_t max_size() noexcept
Definition: classic_protocol_codec_message.h:754
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:758
auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:786
const value_type v_
Definition: classic_protocol_codec_message.h:944
friend __base
Definition: classic_protocol_codec_message.h:830
Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:832
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:839
static size_t max_size() noexcept
Definition: classic_protocol_codec_message.h:835
borrowable::message::server::ColumnMeta< Borrowed > value_type
Definition: classic_protocol_codec_message.h:827
borrowable::message::server::Eof< Borrowed > value_type
Definition: classic_protocol_codec_message.h:540
const value_type v_
Definition: classic_protocol_codec_message.h:638
friend __base
Definition: classic_protocol_codec_message.h:543
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:545
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:498
static constexpr uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:548
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:569
friend __base
Definition: classic_protocol_codec_message.h:687
static constexpr uint8_t cmd_byte()
Definition: classic_protocol_codec_message.h:692
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:689
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:698
borrowable::message::server::Error< Borrowed > value_type
Definition: classic_protocol_codec_message.h:684
const value_type v_
Definition: classic_protocol_codec_message.h:729
static constexpr size_t max_size() noexcept
Definition: classic_protocol_codec_message.h:694
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:670
const value_type v_
Definition: classic_protocol_codec_message.h:237
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
const value_type v_
Definition: classic_protocol_codec_message.h:472
borrowable::message::server::Ok< Borrowed > value_type
Definition: classic_protocol_codec_message.h:391
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:363
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:396
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:416
friend __base
Definition: classic_protocol_codec_message.h:394
static constexpr uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:399
static size_t max_size() noexcept
Definition: classic_protocol_codec_message.h:1122
Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:1119
const value_type v_
Definition: classic_protocol_codec_message.h:1155
auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:1099
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:1126
borrowable::message::server::Row< Borrowed > value_type
Definition: classic_protocol_codec_message.h:1114
friend __base
Definition: classic_protocol_codec_message.h:1117
const value_type v_
Definition: classic_protocol_codec_message.h:1001
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:975
friend __base
Definition: classic_protocol_codec_message.h:973
borrowable::message::server::SendFileRequest< Borrowed > value_type
Definition: classic_protocol_codec_message.h:970
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:980
static constexpr uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:978
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:961
const value_type v_
Definition: classic_protocol_codec_message.h:1397
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:1379
borrowable::message::server::Statistics< Borrowed > value_type
Definition: classic_protocol_codec_message.h:1374
friend __base
Definition: classic_protocol_codec_message.h:1377
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:1382
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:1367
constexpr static uint8_t cmd_byte() noexcept
Definition: classic_protocol_codec_message.h:1053
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:1055
friend __base
Definition: classic_protocol_codec_message.h:1048
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:1050
borrowable::message::server::StmtPrepareOk value_type
Definition: classic_protocol_codec_message.h:1045
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:1027
const value_type v_
Definition: classic_protocol_codec_message.h:1088
const value_type v_
Definition: classic_protocol_codec_message.h:1356
Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_message.h:1247
borrowable::message::server::StmtRow< Borrowed > value_type
Definition: classic_protocol_codec_message.h:1242
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:1254
static size_t max_size() noexcept
Definition: classic_protocol_codec_message.h:1250
auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_message.h:1177
friend __base
Definition: classic_protocol_codec_message.h:1245
Codec for a type.
Definition: classic_protocol_codec_base.h:72
Definition: classic_protocol_message.h:1261
Definition: classic_protocol_message.h:1323
Definition: classic_protocol_message.h:1295
Definition: classic_protocol_message.h:888
Definition: classic_protocol_message.h:1292
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:1256
Definition: classic_protocol_message.h:786
Definition: classic_protocol_message.h:1251
Definition: classic_protocol_message.h:1355
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:1231
Definition: classic_protocol_message.h:948
close a prepared statement.
Definition: classic_protocol_message.h:1161
execute a prepared statement.
Definition: classic_protocol_message.h:1090
fetch rows from an executed statement.
Definition: classic_protocol_message.h:1205
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:1183
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:375
constexpr capabilities::value_type caps() const noexcept
Definition: classic_protocol_codec_base.h:390
Definition: buffer.h:135
size_t size() const noexcept
Definition: buffer.h:120
constexpr const value_type & value() const &
Definition: expected.h:688
constexpr unexpected_type get_unexpected() const
Definition: expected.h:754
constexpr const error_type & error() const &
Definition: expected.h:737
Definition: expected.h:944
a type-safe flags type.
Definition: flags.h:115
constexpr DWORD buf_size
Definition: create_def.cc:228
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
std::bitset< 32 > value_type
Definition: classic_protocol_constants.h:73
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:1433
borrowable::message::client::StmtReset StmtReset
Definition: classic_protocol_message.h:1428
borrowable::message::client::Reload Reload
Definition: classic_protocol_message.h:1423
borrowable::message::client::SetOption SetOption
Definition: classic_protocol_message.h:1432
borrowable::message::client::Kill Kill
Definition: classic_protocol_message.h:1421
borrowable::message::client::StmtClose StmtClose
Definition: classic_protocol_message.h:1429
borrowable::message::server::AuthMethodSwitch< false > AuthMethodSwitch
Definition: classic_protocol_message.h:1404
borrowable::message::server::Error< false > Error
Definition: classic_protocol_message.h:1399
borrowable::message::server::StmtPrepareOk StmtPrepareOk
Definition: classic_protocol_message.h:1409
borrowable::message::server::Greeting< false > Greeting
Definition: classic_protocol_message.h:1401
borrowable::message::server::Row< false > Row
Definition: classic_protocol_message.h:1407
borrowable::message::server::Eof< false > Eof
Definition: classic_protocol_message.h:1400
borrowable::message::server::ColumnCount ColumnCount
Definition: classic_protocol_message.h:1402
borrowable::message::server::Ok< false > Ok
Definition: classic_protocol_message.h:1398
borrowable::message::server::AuthMethodData< false > AuthMethodData
Definition: classic_protocol_message.h:1405
borrowable::message::server::Statistics< false > Statistics
Definition: classic_protocol_message.h:1410
borrowable::message::server::StmtRow< false > StmtRow
Definition: classic_protocol_message.h:1408
borrowable::message::server::SendFileRequest< false > SendFileRequest
Definition: classic_protocol_message.h:1406
borrowable::message::server::ColumnMeta< false > ColumnMeta
Definition: classic_protocol_message.h:1403
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:1439
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:420
size_t buffer_size(const ConstBufferSequence &buffers) noexcept
Definition: buffer.h:315
Definition: gcs_xcom_synode.h:64
constexpr auto enumerate(T &&iterable)
Definition: ranges.h:142
constexpr auto make_unexpected(E &&e) -> unexpected< std::decay_t< E > >
Definition: expected.h:125
required string type
Definition: replication_group_member_actions.proto:34
int n
Definition: xcom_base.cc:509