fb-cpp 0.0.2
A modern C++ wrapper for the Firebird database API
Loading...
Searching...
No Matches
Statement.h
1/*
2 * MIT License
3 *
4 * Copyright (c) 2025 Adriano dos Santos Fernandes
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
25#ifndef FBCPP_STATEMENT_H
26#define FBCPP_STATEMENT_H
27
28#include "config.h"
29#include "fb-cpp-export.h"
30#include "fb-api.h"
31#include "types.h"
32#include "Blob.h"
33#include "Client.h"
34#include "Row.h"
35#include "StatementOptions.h"
36#include "NumericConverter.h"
37#include "CalendarConverter.h"
38#include "Descriptor.h"
39#include "SmartPtrs.h"
40#include "Exception.h"
41#include "StructBinding.h"
42#include "VariantTypeTraits.h"
43#include <charconv>
44#include <cerrno>
45#include <cstdlib>
46#include <limits>
47#include <memory>
48#include <optional>
49#include <stdexcept>
50#include <string>
51#include <string_view>
52#include <type_traits>
53#include <vector>
54#include <cassert>
55#include <cmath>
56#include <cstddef>
57#include <cstdint>
58
59#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
60#include <boost/multiprecision/cpp_int.hpp>
61#include <boost/multiprecision/cpp_dec_float.hpp>
62#endif
63
64#if FB_CPP_USE_BOOST_DECIMAL != 0
65#include <boost/decimal.hpp>
66#endif
67
71namespace fbcpp
72{
73 class Attachment;
74 class Transaction;
75
79 enum class StatementType : unsigned
80 {
84 SELECT = isc_info_sql_stmt_select,
88 INSERT = isc_info_sql_stmt_insert,
92 UPDATE = isc_info_sql_stmt_update,
96 DELETE = isc_info_sql_stmt_delete,
100 DDL = isc_info_sql_stmt_ddl,
104 GET_SEGMENT = isc_info_sql_stmt_get_segment,
108 PUT_SEGMENT = isc_info_sql_stmt_put_segment,
112 EXEC_PROCEDURE = isc_info_sql_stmt_exec_procedure,
116 START_TRANSACTION = isc_info_sql_stmt_start_trans,
120 COMMIT = isc_info_sql_stmt_commit,
124 ROLLBACK = isc_info_sql_stmt_rollback,
128 SELECT_FOR_UPDATE = isc_info_sql_stmt_select_for_upd,
132 SET_GENERATOR = isc_info_sql_stmt_set_generator,
136 SAVEPOINT = isc_info_sql_stmt_savepoint,
137 };
138
142 class FB_CPP_EXPORT Statement final
143 {
144 public:
152 explicit Statement(Attachment& attachment, Transaction& transaction, std::string_view sql,
153 const StatementOptions& options = {});
154
158 Statement(Statement&& o) noexcept;
159
166 Statement& operator=(Statement&& o) noexcept;
167
168 Statement(const Statement&) = delete;
169 Statement& operator=(const Statement&) = delete;
170
174 ~Statement() noexcept
175 {
176 if (isValid())
177 {
178 try
179 {
180 free();
181 }
182 catch (...)
183 {
184 // swallow
185 }
186 }
187 }
188
189 public:
195
200 {
201 return *attachment;
202 }
203
207 bool isValid() noexcept
208 {
209 return statementHandle != nullptr;
210 }
211
217 {
218 return statementHandle;
219 }
220
226 {
227 return resultSetHandle;
228 }
229
234 {
235 return inMetadata;
236 }
237
241 std::vector<std::byte>& getInputMessage() noexcept
242 {
243 return inMessage;
244 }
245
250 {
251 return outMetadata;
252 }
253
257 std::vector<std::byte>& getOutputMessage() noexcept
258 {
259 return outMessage;
260 }
261
266 {
267 return type;
268 }
269
273
279
283 const std::vector<Descriptor>& getInputDescriptors() noexcept
284 {
285 return inDescriptors;
286 }
287
291 const std::vector<Descriptor>& getOutputDescriptors() noexcept
292 {
293 return outDescriptors;
294 }
295
299
303 void free();
304
308 std::string getLegacyPlan();
309
313 std::string getPlan();
314
320 bool execute(Transaction& transaction);
321
325
329 bool fetchNext();
330
334 bool fetchPrior();
335
339 bool fetchFirst();
340
344 bool fetchLast();
345
349 bool fetchAbsolute(unsigned position);
350
354 bool fetchRelative(int offset);
355
359
363
368 {
369 assert(isValid());
370
371 const auto message = inMessage.data();
372
373 for (const auto& descriptor : inDescriptors)
374 *reinterpret_cast<std::int16_t*>(&message[descriptor.nullOffset]) = FB_TRUE;
375 }
376
381 void setNull(unsigned index)
382 {
383 assert(isValid());
384
385 const auto& descriptor = getInDescriptor(index);
386 const auto message = inMessage.data();
387
388 *reinterpret_cast<std::int16_t*>(&message[descriptor.nullOffset]) = FB_TRUE;
389 }
390
396 void setBool(unsigned index, std::optional<bool> optValue)
397 {
398 if (!optValue.has_value())
399 {
400 setNull(index);
401 return;
402 }
403
404 assert(isValid());
405
406 const auto& value = optValue.value();
407 const auto& descriptor = getInDescriptor(index);
408 const auto message = inMessage.data();
409
410 switch (descriptor.adjustedType)
411 {
412 case DescriptorAdjustedType::BOOLEAN:
413 message[descriptor.offset] = value ? std::byte{1} : std::byte{0};
414 break;
415
416 default:
417 throwInvalidType("bool", descriptor.adjustedType);
418 }
419
420 *reinterpret_cast<std::int16_t*>(&message[descriptor.nullOffset]) = FB_FALSE;
421 }
422
426 void setInt16(unsigned index, std::optional<std::int16_t> optValue)
427 {
428 if (!optValue.has_value())
429 {
430 setNull(index);
431 return;
432 }
433
434 setNumber(index, DescriptorAdjustedType::INT16, optValue.value(), 0, "std::int16_t");
435 }
436
440 void setScaledInt16(unsigned index, std::optional<ScaledInt16> optValue)
441 {
442 if (!optValue.has_value())
443 {
444 setNull(index);
445 return;
446 }
447
448 const auto& value = optValue.value();
449 setNumber(index, DescriptorAdjustedType::INT16, value.value, value.scale, "ScaledInt16");
450 }
451
455 void setInt32(unsigned index, std::optional<std::int32_t> optValue)
456 {
457 if (!optValue.has_value())
458 {
459 setNull(index);
460 return;
461 }
462
463 setNumber(index, DescriptorAdjustedType::INT32, optValue.value(), 0, "std::int32_t");
464 }
465
469 void setScaledInt32(unsigned index, std::optional<ScaledInt32> optValue)
470 {
471 if (!optValue.has_value())
472 {
473 setNull(index);
474 return;
475 }
476
477 const auto& value = optValue.value();
478 setNumber(index, DescriptorAdjustedType::INT32, value.value, value.scale, "ScaledInt32");
479 }
480
484 void setInt64(unsigned index, std::optional<std::int64_t> optValue)
485 {
486 if (!optValue.has_value())
487 {
488 setNull(index);
489 return;
490 }
491
492 setNumber(index, DescriptorAdjustedType::INT64, optValue.value(), 0, "std::int64_t");
493 }
494
498 void setScaledInt64(unsigned index, std::optional<ScaledInt64> optValue)
499 {
500 if (!optValue.has_value())
501 {
502 setNull(index);
503 return;
504 }
505
506 const auto& value = optValue.value();
507 setNumber(index, DescriptorAdjustedType::INT64, value.value, value.scale, "ScaledInt64");
508 }
509
513 void setOpaqueInt128(unsigned index, std::optional<OpaqueInt128> optValue)
514 {
515 if (!optValue.has_value())
516 {
517 setNull(index);
518 return;
519 }
520
521 assert(isValid());
522
523 const auto& value = optValue.value();
524 const auto& descriptor = getInDescriptor(index);
525 const auto message = inMessage.data();
526
527 switch (descriptor.adjustedType)
528 {
529 case DescriptorAdjustedType::INT128:
530 *reinterpret_cast<OpaqueInt128*>(&message[descriptor.offset]) = value;
531 break;
532
533 default:
534 throwInvalidType("OpaqueInt128", descriptor.adjustedType);
535 }
536
537 *reinterpret_cast<std::int16_t*>(&message[descriptor.nullOffset]) = FB_FALSE;
538 }
539
543 void setScaledOpaqueInt128(unsigned index, std::optional<ScaledOpaqueInt128> optValue)
544 {
545 if (!optValue.has_value())
546 {
547 setNull(index);
548 return;
549 }
550
551 assert(isValid());
552
553 const auto& value = optValue.value();
554 const auto& descriptor = getInDescriptor(index);
555 auto* const message = inMessage.data();
556
557 switch (descriptor.adjustedType)
558 {
559 case DescriptorAdjustedType::INT128:
560 if (value.scale == descriptor.scale)
561 *reinterpret_cast<OpaqueInt128*>(&message[descriptor.offset]) = value.value;
562 else
563 {
564 const auto valueString =
565 numericConverter.opaqueInt128ToString(&statusWrapper, value.value, value.scale);
566 getClient()
567 .getInt128Util(&statusWrapper)
568 ->fromString(&statusWrapper, descriptor.scale, valueString.c_str(),
569 reinterpret_cast<OpaqueInt128*>(&message[descriptor.offset]));
570 }
571 break;
572
573 default:
574 throwInvalidType("ScaledOpaqueInt128", descriptor.adjustedType);
575 }
576
577 *reinterpret_cast<std::int16_t*>(&message[descriptor.nullOffset]) = FB_FALSE;
578 }
579
580#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
584 void setBoostInt128(unsigned index, std::optional<BoostInt128> optValue)
585 {
586 if (!optValue.has_value())
587 {
588 setNull(index);
589 return;
590 }
591
592 setNumber(index, DescriptorAdjustedType::INT128, optValue.value(), 0, "BoostInt128");
593 }
594
598 void setScaledBoostInt128(unsigned index, std::optional<ScaledBoostInt128> optValue)
599 {
600 if (!optValue.has_value())
601 {
602 setNull(index);
603 return;
604 }
605
606 const auto& value = optValue.value();
607 setNumber(index, DescriptorAdjustedType::INT128, value.value, value.scale, "ScaledBoostInt128");
608 }
609#endif
610
614 void setFloat(unsigned index, std::optional<float> optValue)
615 {
616 if (!optValue.has_value())
617 {
618 setNull(index);
619 return;
620 }
621
622 setNumber(index, DescriptorAdjustedType::FLOAT, optValue.value(), 0, "float");
623 }
624
628 void setDouble(unsigned index, std::optional<double> optValue)
629 {
630 if (!optValue.has_value())
631 {
632 setNull(index);
633 return;
634 }
635
636 setNumber(index, DescriptorAdjustedType::DOUBLE, optValue.value(), 0, "double");
637 }
638
642 void setOpaqueDecFloat16(unsigned index, std::optional<OpaqueDecFloat16> optValue)
643 {
644 if (!optValue.has_value())
645 {
646 setNull(index);
647 return;
648 }
649
650 assert(isValid());
651
652 const auto& value = optValue.value();
653 const auto& descriptor = getInDescriptor(index);
654 const auto message = inMessage.data();
655
656 switch (descriptor.adjustedType)
657 {
658 case DescriptorAdjustedType::DECFLOAT16:
659 *reinterpret_cast<OpaqueDecFloat16*>(&message[descriptor.offset]) = value;
660 break;
661
662 default:
663 throwInvalidType("OpaqueDecFloat16", descriptor.adjustedType);
664 }
665
666 *reinterpret_cast<std::int16_t*>(&message[descriptor.nullOffset]) = FB_FALSE;
667 }
668
669#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
673 void setBoostDecFloat16(unsigned index, std::optional<BoostDecFloat16> optValue)
674 {
675 if (!optValue.has_value())
676 {
677 setNull(index);
678 return;
679 }
680
681 setNumber(index, DescriptorAdjustedType::DECFLOAT16, optValue.value(), 0, "BoostDecFloat16");
682 }
683#endif
684
685#if FB_CPP_USE_BOOST_DECIMAL != 0
689 void setBoostDecimal32(unsigned index, std::optional<BoostDecimal32> optValue)
690 {
691 if (!optValue.has_value())
692 {
693 setNull(index);
694 return;
695 }
696
697 setNumber(index, DescriptorAdjustedType::DECFLOAT16, optValue.value(), 0, "BoostDecimal32");
698 }
699
703 void setBoostDecimal64(unsigned index, std::optional<BoostDecimal64> optValue)
704 {
705 if (!optValue.has_value())
706 {
707 setNull(index);
708 return;
709 }
710
711 setNumber(index, DescriptorAdjustedType::DECFLOAT16, optValue.value(), 0, "BoostDecimal64");
712 }
713#endif
714
718 void setOpaqueDecFloat34(unsigned index, std::optional<OpaqueDecFloat34> optValue)
719 {
720 if (!optValue.has_value())
721 {
722 setNull(index);
723 return;
724 }
725
726 assert(isValid());
727
728 const auto& value = optValue.value();
729 const auto& descriptor = getInDescriptor(index);
730 const auto message = inMessage.data();
731
732 switch (descriptor.adjustedType)
733 {
734 case DescriptorAdjustedType::DECFLOAT34:
735 *reinterpret_cast<OpaqueDecFloat34*>(&message[descriptor.offset]) = value;
736 break;
737
738 default:
739 throwInvalidType("OpaqueDecFloat34", descriptor.adjustedType);
740 }
741
742 *reinterpret_cast<std::int16_t*>(&message[descriptor.nullOffset]) = FB_FALSE;
743 }
744
745#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
749 void setBoostDecFloat34(unsigned index, std::optional<BoostDecFloat34> optValue)
750 {
751 if (!optValue.has_value())
752 {
753 setNull(index);
754 return;
755 }
756
757 setNumber(index, DescriptorAdjustedType::DECFLOAT34, optValue.value(), 0, "BoostDecFloat34");
758 }
759#endif
760
761#if FB_CPP_USE_BOOST_DECIMAL != 0
765 void setBoostDecimal128(unsigned index, std::optional<BoostDecimal128> optValue)
766 {
767 if (!optValue.has_value())
768 {
769 setNull(index);
770 return;
771 }
772
773 setNumber(index, DescriptorAdjustedType::DECFLOAT34, optValue.value(), 0, "BoostDecimal128");
774 }
775#endif
776
780 void setDate(unsigned index, std::optional<Date> optValue)
781 {
782 if (!optValue.has_value())
783 {
784 setNull(index);
785 return;
786 }
787
788 assert(isValid());
789
790 const auto& value = optValue.value();
791 const auto& descriptor = getInDescriptor(index);
792 const auto message = inMessage.data();
793
794 switch (descriptor.adjustedType)
795 {
796 case DescriptorAdjustedType::DATE:
797 *reinterpret_cast<OpaqueDate*>(&message[descriptor.offset]) =
798 calendarConverter.dateToOpaqueDate(value);
799 break;
800
801 default:
802 throwInvalidType("Date", descriptor.adjustedType);
803 }
804
805 *reinterpret_cast<std::int16_t*>(&message[descriptor.nullOffset]) = FB_FALSE;
806 }
807
811 void setOpaqueDate(unsigned index, std::optional<OpaqueDate> optValue)
812 {
813 if (!optValue.has_value())
814 {
815 setNull(index);
816 return;
817 }
818
819 assert(isValid());
820
821 const auto& value = optValue.value();
822 const auto& descriptor = getInDescriptor(index);
823 const auto message = inMessage.data();
824
825 switch (descriptor.adjustedType)
826 {
827 case DescriptorAdjustedType::DATE:
828 *reinterpret_cast<OpaqueDate*>(&message[descriptor.offset]) = value;
829 break;
830
831 default:
832 throwInvalidType("OpaqueDate", descriptor.adjustedType);
833 }
834
835 *reinterpret_cast<std::int16_t*>(&message[descriptor.nullOffset]) = FB_FALSE;
836 }
837
841 void setTime(unsigned index, std::optional<Time> optValue)
842 {
843 if (!optValue.has_value())
844 {
845 setNull(index);
846 return;
847 }
848
849 assert(isValid());
850
851 const auto& value = optValue.value();
852 const auto& descriptor = getInDescriptor(index);
853 const auto message = inMessage.data();
854
855 switch (descriptor.adjustedType)
856 {
857 case DescriptorAdjustedType::TIME:
858 *reinterpret_cast<OpaqueTime*>(&message[descriptor.offset]) =
859 calendarConverter.timeToOpaqueTime(value);
860 break;
861
862 default:
863 throwInvalidType("Time", descriptor.adjustedType);
864 }
865
866 *reinterpret_cast<std::int16_t*>(&message[descriptor.nullOffset]) = FB_FALSE;
867 }
868
872 void setOpaqueTime(unsigned index, std::optional<OpaqueTime> optValue)
873 {
874 if (!optValue.has_value())
875 {
876 setNull(index);
877 return;
878 }
879
880 assert(isValid());
881
882 const auto& value = optValue.value();
883 const auto& descriptor = getInDescriptor(index);
884 const auto message = inMessage.data();
885
886 switch (descriptor.adjustedType)
887 {
888 case DescriptorAdjustedType::TIME:
889 *reinterpret_cast<OpaqueTime*>(&message[descriptor.offset]) = value;
890 break;
891
892 default:
893 throwInvalidType("OpaqueTime", descriptor.adjustedType);
894 }
895
896 *reinterpret_cast<std::int16_t*>(&message[descriptor.nullOffset]) = FB_FALSE;
897 }
898
902 void setTimestamp(unsigned index, std::optional<Timestamp> optValue)
903 {
904 if (!optValue.has_value())
905 {
906 setNull(index);
907 return;
908 }
909
910 assert(isValid());
911
912 const auto& value = optValue.value();
913 const auto& descriptor = getInDescriptor(index);
914 const auto message = inMessage.data();
915
916 switch (descriptor.adjustedType)
917 {
918 case DescriptorAdjustedType::TIMESTAMP:
919 *reinterpret_cast<OpaqueTimestamp*>(&message[descriptor.offset]) =
920 calendarConverter.timestampToOpaqueTimestamp(value);
921 break;
922
923 default:
924 throwInvalidType("Timestamp", descriptor.adjustedType);
925 }
926
927 *reinterpret_cast<std::int16_t*>(&message[descriptor.nullOffset]) = FB_FALSE;
928 }
929
933 void setOpaqueTimestamp(unsigned index, std::optional<OpaqueTimestamp> optValue)
934 {
935 if (!optValue.has_value())
936 {
937 setNull(index);
938 return;
939 }
940
941 assert(isValid());
942
943 const auto& value = optValue.value();
944 const auto& descriptor = getInDescriptor(index);
945 const auto message = inMessage.data();
946
947 switch (descriptor.adjustedType)
948 {
949 case DescriptorAdjustedType::TIMESTAMP:
950 *reinterpret_cast<OpaqueTimestamp*>(&message[descriptor.offset]) = value;
951 break;
952
953 default:
954 throwInvalidType("OpaqueTimestamp", descriptor.adjustedType);
955 }
956
957 *reinterpret_cast<std::int16_t*>(&message[descriptor.nullOffset]) = FB_FALSE;
958 }
959
963 void setTimeTz(unsigned index, std::optional<TimeTz> optValue)
964 {
965 if (!optValue.has_value())
966 {
967 setNull(index);
968 return;
969 }
970
971 assert(isValid());
972
973 const auto& value = optValue.value();
974 const auto& descriptor = getInDescriptor(index);
975 auto* const message = inMessage.data();
976
977 switch (descriptor.adjustedType)
978 {
979 case DescriptorAdjustedType::TIME_TZ:
980 *reinterpret_cast<OpaqueTimeTz*>(&message[descriptor.offset]) =
981 calendarConverter.timeTzToOpaqueTimeTz(&statusWrapper, value);
982 break;
983
984 default:
985 throwInvalidType("TimeTz", descriptor.adjustedType);
986 }
987
988 *reinterpret_cast<std::int16_t*>(&message[descriptor.nullOffset]) = FB_FALSE;
989 }
990
994 void setOpaqueTimeTz(unsigned index, std::optional<OpaqueTimeTz> optValue)
995 {
996 if (!optValue.has_value())
997 {
998 setNull(index);
999 return;
1000 }
1001
1002 assert(isValid());
1003
1004 const auto& value = optValue.value();
1005 const auto& descriptor = getInDescriptor(index);
1006 auto* const message = inMessage.data();
1007
1008 switch (descriptor.adjustedType)
1009 {
1010 case DescriptorAdjustedType::TIME_TZ:
1011 *reinterpret_cast<OpaqueTimeTz*>(&message[descriptor.offset]) = value;
1012 break;
1013
1014 default:
1015 throwInvalidType("OpaqueTimeTz", descriptor.adjustedType);
1016 }
1017
1018 *reinterpret_cast<std::int16_t*>(&message[descriptor.nullOffset]) = FB_FALSE;
1019 }
1020
1024 void setTimestampTz(unsigned index, std::optional<TimestampTz> optValue)
1025 {
1026 if (!optValue.has_value())
1027 {
1028 setNull(index);
1029 return;
1030 }
1031
1032 assert(isValid());
1033
1034 const auto& value = optValue.value();
1035 const auto& descriptor = getInDescriptor(index);
1036 auto* const message = inMessage.data();
1037
1038 switch (descriptor.adjustedType)
1039 {
1040 case DescriptorAdjustedType::TIMESTAMP_TZ:
1041 *reinterpret_cast<OpaqueTimestampTz*>(&message[descriptor.offset]) =
1042 calendarConverter.timestampTzToOpaqueTimestampTz(&statusWrapper, value);
1043 break;
1044
1045 default:
1046 throwInvalidType("TimestampTz", descriptor.adjustedType);
1047 }
1048
1049 *reinterpret_cast<std::int16_t*>(&message[descriptor.nullOffset]) = FB_FALSE;
1050 }
1051
1055 void setOpaqueTimestampTz(unsigned index, std::optional<OpaqueTimestampTz> optValue)
1056 {
1057 if (!optValue.has_value())
1058 {
1059 setNull(index);
1060 return;
1061 }
1062
1063 assert(isValid());
1064
1065 const auto& value = optValue.value();
1066 const auto& descriptor = getInDescriptor(index);
1067 auto* const message = inMessage.data();
1068
1069 switch (descriptor.adjustedType)
1070 {
1071 case DescriptorAdjustedType::TIMESTAMP_TZ:
1072 *reinterpret_cast<OpaqueTimestampTz*>(&message[descriptor.offset]) = value;
1073 break;
1074
1075 default:
1076 throwInvalidType("OpaqueTimestampTz", descriptor.adjustedType);
1077 }
1078
1079 *reinterpret_cast<std::int16_t*>(&message[descriptor.nullOffset]) = FB_FALSE;
1080 }
1081
1085 void setString(unsigned index, std::optional<std::string_view> optValue)
1086 {
1087 if (!optValue.has_value())
1088 {
1089 setNull(index);
1090 return;
1091 }
1092
1093 assert(isValid());
1094
1095 auto& client = getClient();
1096 const auto value = optValue.value();
1097 const auto& descriptor = getInDescriptor(index);
1098 const auto message = inMessage.data();
1099 const auto data = &message[descriptor.offset];
1100
1101 switch (descriptor.adjustedType)
1102 {
1103 case DescriptorAdjustedType::BOOLEAN:
1104 message[descriptor.offset] = numericConverter.stringToBoolean(value);
1105 break;
1106
1107 case DescriptorAdjustedType::INT16:
1108 case DescriptorAdjustedType::INT32:
1109 case DescriptorAdjustedType::INT64:
1110 {
1111 std::string strValue(value);
1112 int scale = 0;
1113
1114 if (const auto dotPos = strValue.find_last_of('.'); dotPos != std::string_view::npos)
1115 {
1116 for (auto pos = dotPos + 1; pos < strValue.size(); ++pos)
1117 {
1118 const char c = value[pos];
1119
1120 if (c < '0' || c > '9')
1121 break;
1122
1123 --scale;
1124 }
1125
1126 strValue.erase(dotPos, 1);
1127 }
1128
1129 static_assert(sizeof(long long) == sizeof(std::int64_t));
1130 std::int64_t intValue;
1131 const auto convResult =
1132 std::from_chars(strValue.data(), strValue.data() + strValue.size(), intValue);
1133 if (convResult.ec != std::errc{} || convResult.ptr != strValue.data() + strValue.size())
1134 numericConverter.throwConversionErrorFromString(strValue);
1135 auto scaledValue = ScaledInt64{intValue, scale};
1136
1137 if (scale != descriptor.scale)
1138 {
1139 scaledValue.value =
1140 numericConverter.numberToNumber<std::int64_t>(scaledValue, descriptor.scale);
1141 scaledValue.scale = descriptor.scale;
1142 }
1143
1144 setScaledInt64(index, scaledValue);
1145 return;
1146 }
1147
1148 case DescriptorAdjustedType::INT128:
1149 {
1150 std::string strValue(value);
1151 client.getInt128Util(&statusWrapper)
1152 ->fromString(
1153 &statusWrapper, descriptor.scale, strValue.c_str(), reinterpret_cast<OpaqueInt128*>(data));
1154 break;
1155 }
1156
1157 case DescriptorAdjustedType::FLOAT:
1158 case DescriptorAdjustedType::DOUBLE:
1159 {
1160 double doubleValue;
1161#if defined(__APPLE__)
1162 errno = 0;
1163 std::string valueString{value};
1164 char* parseEnd = nullptr;
1165 doubleValue = std::strtod(valueString.c_str(), &parseEnd);
1166 if (parseEnd != valueString.c_str() + valueString.size() || errno == ERANGE)
1167 numericConverter.throwConversionErrorFromString(std::move(valueString));
1168#else
1169 const auto convResult = std::from_chars(value.data(), value.data() + value.size(), doubleValue);
1170 if (convResult.ec != std::errc{} || convResult.ptr != value.data() + value.size())
1171 numericConverter.throwConversionErrorFromString(std::string{value});
1172#endif
1173 setDouble(index, doubleValue);
1174 return;
1175 }
1176
1177 case DescriptorAdjustedType::DATE:
1178 *reinterpret_cast<OpaqueDate*>(data) = calendarConverter.stringToOpaqueDate(value);
1179 break;
1180
1181 case DescriptorAdjustedType::TIME:
1182 *reinterpret_cast<OpaqueTime*>(data) = calendarConverter.stringToOpaqueTime(value);
1183 break;
1184
1185 case DescriptorAdjustedType::TIMESTAMP:
1186 *reinterpret_cast<OpaqueTimestamp*>(data) = calendarConverter.stringToOpaqueTimestamp(value);
1187 break;
1188
1189 case DescriptorAdjustedType::TIME_TZ:
1190 *reinterpret_cast<OpaqueTimeTz*>(data) =
1191 calendarConverter.stringToOpaqueTimeTz(&statusWrapper, value);
1192 break;
1193
1194 case DescriptorAdjustedType::TIMESTAMP_TZ:
1195 *reinterpret_cast<OpaqueTimestampTz*>(data) =
1196 calendarConverter.stringToOpaqueTimestampTz(&statusWrapper, value);
1197 break;
1198
1199 case DescriptorAdjustedType::DECFLOAT16:
1200 {
1201 std::string strValue{value};
1202 client.getDecFloat16Util(&statusWrapper)
1203 ->fromString(&statusWrapper, strValue.c_str(), reinterpret_cast<OpaqueDecFloat16*>(data));
1204 break;
1205 }
1206
1207 case DescriptorAdjustedType::DECFLOAT34:
1208 {
1209 std::string strValue{value};
1210 client.getDecFloat34Util(&statusWrapper)
1211 ->fromString(&statusWrapper, strValue.c_str(), reinterpret_cast<OpaqueDecFloat34*>(data));
1212 break;
1213 }
1214
1215 case DescriptorAdjustedType::STRING:
1216 if (value.length() > descriptor.length)
1217 {
1218 static constexpr std::intptr_t STATUS_STRING_TRUNCATION[] = {
1219 isc_arith_except,
1220 isc_string_truncation,
1221 isc_arg_end,
1222 };
1223
1224 throw DatabaseException(client, STATUS_STRING_TRUNCATION);
1225 }
1226
1227 *reinterpret_cast<std::uint16_t*>(data) = static_cast<std::uint16_t>(value.length());
1228 std::copy(value.begin(), value.end(),
1229 reinterpret_cast<char*>(&message[descriptor.offset + sizeof(std::uint16_t)]));
1230 break;
1231
1232 default:
1233 throwInvalidType("std::string_view", descriptor.adjustedType);
1234 }
1235
1236 *reinterpret_cast<std::int16_t*>(&message[descriptor.nullOffset]) = FB_FALSE;
1237 }
1238
1242 void setBlobId(unsigned index, std::optional<BlobId> optValue)
1243 {
1244 if (!optValue.has_value())
1245 {
1246 setNull(index);
1247 return;
1248 }
1249
1250 assert(isValid());
1251
1252 const auto& value = optValue.value();
1253 const auto& descriptor = getInDescriptor(index);
1254 auto* const message = inMessage.data();
1255
1256 switch (descriptor.adjustedType)
1257 {
1258 case DescriptorAdjustedType::BLOB:
1259 *reinterpret_cast<ISC_QUAD*>(&message[descriptor.offset]) = value.id;
1260 break;
1261
1262 default:
1263 throwInvalidType("BlobId", descriptor.adjustedType);
1264 }
1265
1266 *reinterpret_cast<std::int16_t*>(&message[descriptor.nullOffset]) = FB_FALSE;
1267 }
1268
1271 void set(unsigned index, std::nullopt_t)
1272 {
1273 setNull(index);
1274 }
1275
1279 void set(unsigned index, BlobId value)
1280 {
1281 setBlobId(index, value);
1282 }
1283
1287 void set(unsigned index, std::optional<BlobId> value)
1288 {
1289 setBlobId(index, value);
1290 }
1291
1295 void set(unsigned index, bool value)
1296 {
1297 setBool(index, value);
1298 }
1299
1303 void set(unsigned index, std::int16_t value)
1304 {
1305 setInt16(index, value);
1306 }
1307
1311 void set(unsigned index, ScaledInt16 value)
1312 {
1313 setScaledInt16(index, value);
1314 }
1315
1319 void set(unsigned index, std::int32_t value)
1320 {
1321 setInt32(index, value);
1322 }
1323
1327 void set(unsigned index, ScaledInt32 value)
1328 {
1329 setScaledInt32(index, value);
1330 }
1331
1335 void set(unsigned index, std::int64_t value)
1336 {
1337 setInt64(index, value);
1338 }
1339
1343 void set(unsigned index, ScaledInt64 value)
1344 {
1345 setScaledInt64(index, value);
1346 }
1347
1351 void set(unsigned index, OpaqueInt128 value)
1352 {
1353 setOpaqueInt128(index, value);
1354 }
1355
1359 void set(unsigned index, ScaledOpaqueInt128 value)
1360 {
1361 setScaledOpaqueInt128(index, value);
1362 }
1363
1364#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
1368 void set(unsigned index, BoostInt128 value)
1369 {
1370 setBoostInt128(index, value);
1371 }
1372
1376 void set(unsigned index, ScaledBoostInt128 value)
1377 {
1378 setScaledBoostInt128(index, value);
1379 }
1380#endif
1381
1385 void set(unsigned index, float value)
1386 {
1387 setFloat(index, value);
1388 }
1389
1393 void set(unsigned index, double value)
1394 {
1395 setDouble(index, value);
1396 }
1397
1401 void set(unsigned index, OpaqueDecFloat16 value)
1402 {
1403 setOpaqueDecFloat16(index, value);
1404 }
1405
1406#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
1410 void set(unsigned index, BoostDecFloat16 value)
1411 {
1412 setBoostDecFloat16(index, value);
1413 }
1414#endif
1415
1416#if FB_CPP_USE_BOOST_DECIMAL != 0
1420 void set(unsigned index, BoostDecimal32 value)
1421 {
1422 setBoostDecimal32(index, value);
1423 }
1424
1428 void set(unsigned index, BoostDecimal64 value)
1429 {
1430 setBoostDecimal64(index, value);
1431 }
1432#endif
1433
1437 void set(unsigned index, OpaqueDecFloat34 value)
1438 {
1439 setOpaqueDecFloat34(index, value);
1440 }
1441
1442#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
1446 void set(unsigned index, BoostDecFloat34 value)
1447 {
1448 setBoostDecFloat34(index, value);
1449 }
1450#endif
1451
1452#if FB_CPP_USE_BOOST_DECIMAL != 0
1456 void set(unsigned index, BoostDecimal128 value)
1457 {
1458 setBoostDecimal128(index, value);
1459 }
1460#endif
1461
1465 void set(unsigned index, Date value)
1466 {
1467 setDate(index, value);
1468 }
1469
1473 void set(unsigned index, OpaqueDate value)
1474 {
1475 setOpaqueDate(index, value);
1476 }
1477
1481 void set(unsigned index, Time value)
1482 {
1483 setTime(index, value);
1484 }
1485
1489 void set(unsigned index, OpaqueTime value)
1490 {
1491 setOpaqueTime(index, value);
1492 }
1493
1497 void set(unsigned index, Timestamp value)
1498 {
1499 setTimestamp(index, value);
1500 }
1501
1505 void set(unsigned index, OpaqueTimestamp value)
1506 {
1507 setOpaqueTimestamp(index, value);
1508 }
1509
1513 void set(unsigned index, TimeTz value)
1514 {
1515 setTimeTz(index, value);
1516 }
1517
1521 void set(unsigned index, OpaqueTimeTz value)
1522 {
1523 setOpaqueTimeTz(index, value);
1524 }
1525
1529 void set(unsigned index, TimestampTz value)
1530 {
1531 setTimestampTz(index, value);
1532 }
1533
1537 void set(unsigned index, OpaqueTimestampTz value)
1538 {
1539 setOpaqueTimestampTz(index, value);
1540 }
1541
1545 void set(unsigned index, std::string_view value)
1546 {
1547 setString(index, value);
1548 }
1549
1553 template <typename T>
1554 void set(unsigned index, std::optional<T> value)
1555 {
1556 if (value.has_value())
1557 set(index, value.value());
1558 else
1559 setNull(index);
1560 }
1561
1565
1569
1573 bool isNull(unsigned index)
1574 {
1575 assert(isValid());
1576 return outRow->isNull(index);
1577 }
1578
1582 std::optional<bool> getBool(unsigned index)
1583 {
1584 assert(isValid());
1585 return outRow->getBool(index);
1586 }
1587
1591 std::optional<std::int16_t> getInt16(unsigned index)
1592 {
1593 assert(isValid());
1594 return outRow->getInt16(index);
1595 }
1596
1600 std::optional<ScaledInt16> getScaledInt16(unsigned index)
1601 {
1602 assert(isValid());
1603 return outRow->getScaledInt16(index);
1604 }
1605
1609 std::optional<std::int32_t> getInt32(unsigned index)
1610 {
1611 assert(isValid());
1612 return outRow->getInt32(index);
1613 }
1614
1618 std::optional<ScaledInt32> getScaledInt32(unsigned index)
1619 {
1620 assert(isValid());
1621 return outRow->getScaledInt32(index);
1622 }
1623
1627 std::optional<std::int64_t> getInt64(unsigned index)
1628 {
1629 assert(isValid());
1630 return outRow->getInt64(index);
1631 }
1632
1636 std::optional<ScaledInt64> getScaledInt64(unsigned index)
1637 {
1638 assert(isValid());
1639 return outRow->getScaledInt64(index);
1640 }
1641
1645 std::optional<ScaledOpaqueInt128> getScaledOpaqueInt128(unsigned index)
1646 {
1647 assert(isValid());
1648 return outRow->getScaledOpaqueInt128(index);
1649 }
1650
1651#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
1655 std::optional<BoostInt128> getBoostInt128(unsigned index)
1656 {
1657 assert(isValid());
1658 return outRow->getBoostInt128(index);
1659 }
1660
1664 std::optional<ScaledBoostInt128> getScaledBoostInt128(unsigned index)
1665 {
1666 assert(isValid());
1667 return outRow->getScaledBoostInt128(index);
1668 }
1669#endif
1670
1674 std::optional<float> getFloat(unsigned index)
1675 {
1676 assert(isValid());
1677 return outRow->getFloat(index);
1678 }
1679
1683 std::optional<double> getDouble(unsigned index)
1684 {
1685 assert(isValid());
1686 return outRow->getDouble(index);
1687 }
1688
1692 std::optional<OpaqueDecFloat16> getOpaqueDecFloat16(unsigned index)
1693 {
1694 assert(isValid());
1695 return outRow->getOpaqueDecFloat16(index);
1696 }
1697
1698#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
1702 std::optional<BoostDecFloat16> getBoostDecFloat16(unsigned index)
1703 {
1704 assert(isValid());
1705 return outRow->getBoostDecFloat16(index);
1706 }
1707#endif
1708
1709#if FB_CPP_USE_BOOST_DECIMAL != 0
1713 std::optional<BoostDecimal32> getBoostDecimal32(unsigned index)
1714 {
1715 assert(isValid());
1716 return outRow->getBoostDecimal32(index);
1717 }
1718
1722 std::optional<BoostDecimal64> getBoostDecimal64(unsigned index)
1723 {
1724 assert(isValid());
1725 return outRow->getBoostDecimal64(index);
1726 }
1727#endif
1728
1732 std::optional<OpaqueDecFloat34> getOpaqueDecFloat34(unsigned index)
1733 {
1734 assert(isValid());
1735 return outRow->getOpaqueDecFloat34(index);
1736 }
1737
1738#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
1742 std::optional<BoostDecFloat34> getBoostDecFloat34(unsigned index)
1743 {
1744 assert(isValid());
1745 return outRow->getBoostDecFloat34(index);
1746 }
1747#endif
1748
1749#if FB_CPP_USE_BOOST_DECIMAL != 0
1753 std::optional<BoostDecimal128> getBoostDecimal128(unsigned index)
1754 {
1755 assert(isValid());
1756 return outRow->getBoostDecimal128(index);
1757 }
1758#endif
1759
1763 std::optional<Date> getDate(unsigned index)
1764 {
1765 assert(isValid());
1766 return outRow->getDate(index);
1767 }
1768
1772 std::optional<OpaqueDate> getOpaqueDate(unsigned index)
1773 {
1774 assert(isValid());
1775 return outRow->getOpaqueDate(index);
1776 }
1777
1781 std::optional<Time> getTime(unsigned index)
1782 {
1783 assert(isValid());
1784 return outRow->getTime(index);
1785 }
1786
1790 std::optional<OpaqueTime> getOpaqueTime(unsigned index)
1791 {
1792 assert(isValid());
1793 return outRow->getOpaqueTime(index);
1794 }
1795
1799 std::optional<Timestamp> getTimestamp(unsigned index)
1800 {
1801 assert(isValid());
1802 return outRow->getTimestamp(index);
1803 }
1804
1808 std::optional<OpaqueTimestamp> getOpaqueTimestamp(unsigned index)
1809 {
1810 assert(isValid());
1811 return outRow->getOpaqueTimestamp(index);
1812 }
1813
1817 std::optional<TimeTz> getTimeTz(unsigned index)
1818 {
1819 assert(isValid());
1820 return outRow->getTimeTz(index);
1821 }
1822
1826 std::optional<OpaqueTimeTz> getOpaqueTimeTz(unsigned index)
1827 {
1828 assert(isValid());
1829 return outRow->getOpaqueTimeTz(index);
1830 }
1831
1835 std::optional<TimestampTz> getTimestampTz(unsigned index)
1836 {
1837 assert(isValid());
1838 return outRow->getTimestampTz(index);
1839 }
1840
1844 std::optional<OpaqueTimestampTz> getOpaqueTimestampTz(unsigned index)
1845 {
1846 assert(isValid());
1847 return outRow->getOpaqueTimestampTz(index);
1848 }
1849
1853 std::optional<BlobId> getBlobId(unsigned index)
1854 {
1855 assert(isValid());
1856 return outRow->getBlobId(index);
1857 }
1858
1862 std::optional<std::string> getString(unsigned index)
1863 {
1864 assert(isValid());
1865 return outRow->getString(index);
1866 }
1867
1871
1875 template <typename T>
1876 T get(unsigned index)
1877 {
1878 assert(isValid());
1879 return outRow->get<T>(index);
1880 }
1881
1889 template <Aggregate T>
1891 {
1892 assert(isValid());
1893 return outRow->get<T>();
1894 }
1895
1902 template <Aggregate T>
1903 void set(const T& value)
1904 {
1905 using namespace impl::reflection;
1906
1907 constexpr std::size_t N = fieldCountV<T>;
1908
1909 if (N != inDescriptors.size())
1910 {
1911 throw FbCppException("Struct field count (" + std::to_string(N) +
1912 ") does not match input parameter count (" + std::to_string(inDescriptors.size()) + ")");
1913 }
1914
1915 setStruct(value, std::make_index_sequence<N>{});
1916 }
1917
1925 template <TupleLike T>
1927 {
1928 assert(isValid());
1929 return outRow->get<T>();
1930 }
1931
1938 template <TupleLike T>
1939 void set(const T& value)
1940 {
1941 constexpr std::size_t N = std::tuple_size_v<T>;
1942
1943 if (N != inDescriptors.size())
1944 {
1945 throw FbCppException("Tuple element count (" + std::to_string(N) +
1946 ") does not match input parameter count (" + std::to_string(inDescriptors.size()) + ")");
1947 }
1948
1949 setTuple(value, std::make_index_sequence<N>{});
1950 }
1951
1960 template <VariantLike V>
1961 V get(unsigned index)
1962 {
1963 assert(isValid());
1964 return outRow->get<V>(index);
1965 }
1966
1973 template <VariantLike V>
1974 void set(unsigned index, const V& value)
1975 {
1976 using namespace impl::reflection;
1977
1978 static_assert(variantAlternativesSupportedV<V>,
1979 "Variant contains unsupported types. All variant alternatives must be types supported by fb-cpp "
1980 "(e.g., std::int32_t, std::string, Date, ScaledOpaqueInt128, etc.). Check VariantTypeTraits.h for the "
1981 "complete list of supported types.");
1982
1983 std::visit(
1984 [this, index](const auto& v)
1985 {
1986 using T = std::decay_t<decltype(v)>;
1987
1988 if constexpr (std::is_same_v<T, std::monostate>)
1989 setNull(index);
1990 else
1991 set(index, v);
1992 },
1993 value);
1994 }
1995
1996 private:
2000 const Descriptor& getInDescriptor(unsigned index)
2001 {
2002 if (index >= inDescriptors.size())
2003 throw std::out_of_range("index out of range");
2004
2005 return inDescriptors[index];
2006 }
2007
2011 template <typename T, std::size_t... Is>
2012 void setStruct(const T& value, std::index_sequence<Is...>)
2013 {
2014 using namespace impl::reflection;
2015
2016 const auto tuple = toTupleRef(value);
2017 (set(static_cast<unsigned>(Is), std::get<Is>(tuple)), ...);
2018 }
2019
2023 template <typename T, std::size_t... Is>
2024 void setTuple(const T& value, std::index_sequence<Is...>)
2025 {
2026 (set(static_cast<unsigned>(Is), std::get<Is>(value)), ...);
2027 }
2028
2029#if FB_CPP_USE_BOOST_DECIMAL != 0
2030 template <typename T>
2031 void setDecimalNumber(unsigned index, T value, std::optional<int>& descriptorScale, const char* typeName)
2032 {
2033 const auto& descriptor = getInDescriptor(index);
2034 auto* const message = inMessage.data();
2035 const auto descriptorData = &message[descriptor.offset];
2036
2037 switch (descriptor.adjustedType)
2038 {
2039 case DescriptorAdjustedType::INT16:
2040 *reinterpret_cast<std::int16_t*>(descriptorData) =
2041 numericConverter.numberToNumber<std::int16_t>(value, descriptorScale.value());
2042 break;
2043
2044 case DescriptorAdjustedType::INT32:
2045 *reinterpret_cast<std::int32_t*>(descriptorData) =
2046 numericConverter.numberToNumber<std::int32_t>(value, descriptorScale.value());
2047 break;
2048
2049 case DescriptorAdjustedType::INT64:
2050 *reinterpret_cast<std::int64_t*>(descriptorData) =
2051 numericConverter.numberToNumber<std::int64_t>(value, descriptorScale.value());
2052 break;
2053
2054#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
2055 case DescriptorAdjustedType::INT128:
2056 {
2057 const auto int128Value =
2058 numericConverter.numberToNumber<BoostInt128>(value, descriptorScale.value());
2059 *reinterpret_cast<OpaqueInt128*>(descriptorData) =
2060 numericConverter.boostInt128ToOpaqueInt128(&statusWrapper, int128Value);
2061 break;
2062 }
2063#endif
2064
2065 case DescriptorAdjustedType::FLOAT:
2066 *reinterpret_cast<float*>(descriptorData) = numericConverter.numberToNumber<float>(value);
2067 break;
2068
2069 case DescriptorAdjustedType::DOUBLE:
2070 *reinterpret_cast<double*>(descriptorData) = numericConverter.numberToNumber<double>(value);
2071 break;
2072
2073 case DescriptorAdjustedType::DECFLOAT16:
2074 {
2075 const auto decimalValue = numericConverter.numberToNumber<BoostDecimal64>(value);
2076 *reinterpret_cast<OpaqueDecFloat16*>(descriptorData) =
2077 numericConverter.boostDecimal64ToOpaqueDecFloat16(&statusWrapper, decimalValue);
2078 break;
2079 }
2080
2081 case DescriptorAdjustedType::DECFLOAT34:
2082 {
2083 const auto decimalValue = numericConverter.numberToNumber<BoostDecimal128>(value);
2084 *reinterpret_cast<OpaqueDecFloat34*>(descriptorData) =
2085 numericConverter.boostDecimal128ToOpaqueDecFloat34(&statusWrapper, decimalValue);
2086 break;
2087 }
2088
2089 default:
2090 throwInvalidType(typeName, descriptor.adjustedType);
2091 }
2092 }
2093#endif
2094
2098 template <typename T>
2099 void setNumber(unsigned index, DescriptorAdjustedType valueType, T value, int scale, const char* typeName)
2100 {
2101 assert(isValid());
2102
2103 const auto& descriptor = getInDescriptor(index);
2104 auto* const message = inMessage.data();
2105
2106 const auto descriptorData = &message[descriptor.offset];
2107 std::optional<int> descriptorScale{descriptor.scale};
2108
2109#if FB_CPP_USE_BOOST_DECIMAL != 0
2110 if constexpr (std::is_same_v<T, BoostDecimal32> || std::is_same_v<T, BoostDecimal64> ||
2111 std::is_same_v<T, BoostDecimal128>)
2112 {
2113 setDecimalNumber(index, value, descriptorScale, typeName);
2114 *reinterpret_cast<std::int16_t*>(&message[descriptor.nullOffset]) = FB_FALSE;
2115 return;
2116 }
2117#endif
2118
2119 Descriptor valueDescriptor;
2120 valueDescriptor.adjustedType = valueType;
2121 valueDescriptor.scale = scale;
2122
2123 const auto valueAddress = reinterpret_cast<const std::byte*>(&value);
2124
2125 switch (descriptor.adjustedType)
2126 {
2127 case DescriptorAdjustedType::INT16:
2128 *reinterpret_cast<std::int16_t*>(descriptorData) =
2129 convertNumber<std::int16_t>(valueDescriptor, valueAddress, descriptorScale, "std::int16_t");
2130 break;
2131
2132 case DescriptorAdjustedType::INT32:
2133 *reinterpret_cast<std::int32_t*>(descriptorData) =
2134 convertNumber<std::int32_t>(valueDescriptor, valueAddress, descriptorScale, "std::int32_t");
2135 break;
2136
2137 case DescriptorAdjustedType::INT64:
2138 *reinterpret_cast<std::int64_t*>(descriptorData) =
2139 convertNumber<std::int64_t>(valueDescriptor, valueAddress, descriptorScale, "std::int64_t");
2140 break;
2141
2142#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
2143 case DescriptorAdjustedType::INT128:
2144 {
2145 const auto boostInt128 =
2146 convertNumber<BoostInt128>(valueDescriptor, valueAddress, descriptorScale, "BoostInt128");
2147 *reinterpret_cast<OpaqueInt128*>(descriptorData) =
2148 numericConverter.boostInt128ToOpaqueInt128(&statusWrapper, boostInt128);
2149 break;
2150 }
2151#endif
2152
2153 case DescriptorAdjustedType::FLOAT:
2154 *reinterpret_cast<float*>(descriptorData) =
2155 convertNumber<float>(valueDescriptor, valueAddress, descriptorScale, "float");
2156 break;
2157
2158 case DescriptorAdjustedType::DOUBLE:
2159 *reinterpret_cast<double*>(descriptorData) =
2160 convertNumber<double>(valueDescriptor, valueAddress, descriptorScale, "double");
2161 break;
2162
2163#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
2164 case DescriptorAdjustedType::DECFLOAT16:
2165 {
2166 const auto boostDecFloat16 = convertNumber<BoostDecFloat16>(
2167 valueDescriptor, valueAddress, descriptorScale, "BoostDecFloat16");
2168 *reinterpret_cast<OpaqueDecFloat16*>(descriptorData) =
2169 numericConverter.boostDecFloat16ToOpaqueDecFloat16(&statusWrapper, boostDecFloat16);
2170 break;
2171 }
2172
2173 case DescriptorAdjustedType::DECFLOAT34:
2174 {
2175 const auto boostDecFloat34 = convertNumber<BoostDecFloat34>(
2176 valueDescriptor, valueAddress, descriptorScale, "BoostDecFloat34");
2177 *reinterpret_cast<OpaqueDecFloat34*>(descriptorData) =
2178 numericConverter.boostDecFloat34ToOpaqueDecFloat34(&statusWrapper, boostDecFloat34);
2179 break;
2180 }
2181#endif
2182
2183 default:
2184 throwInvalidType(typeName, descriptor.adjustedType);
2185 }
2186
2187 *reinterpret_cast<std::int16_t*>(&message[descriptor.nullOffset]) = FB_FALSE;
2188 }
2189
2190 [[noreturn]] static void throwInvalidType(const char* actualType, DescriptorAdjustedType descriptorType)
2191 {
2192 throw FbCppException("Invalid type: actual type " + std::string(actualType) + ", descriptor type " +
2193 std::to_string(static_cast<unsigned>(descriptorType)));
2194 }
2195
2196 template <typename T>
2197 T convertNumber(
2198 const Descriptor& descriptor, const std::byte* data, std::optional<int>& toScale, const char* toTypeName)
2199 {
2200 if (!toScale.has_value())
2201 {
2202 switch (descriptor.adjustedType)
2203 {
2204 case DescriptorAdjustedType::DECFLOAT16:
2205 case DescriptorAdjustedType::DECFLOAT34:
2206 case DescriptorAdjustedType::FLOAT:
2207 case DescriptorAdjustedType::DOUBLE:
2208 throwInvalidType(toTypeName, descriptor.adjustedType);
2209
2210 default:
2211 break;
2212 }
2213
2214 toScale = descriptor.scale;
2215 }
2216
2217 switch (descriptor.adjustedType)
2218 {
2219 case DescriptorAdjustedType::INT16:
2220 return numericConverter.numberToNumber<T>(
2221 ScaledInt16{*reinterpret_cast<const std::int16_t*>(data), descriptor.scale}, toScale.value());
2222 break;
2223
2224 case DescriptorAdjustedType::INT32:
2225 return numericConverter.numberToNumber<T>(
2226 ScaledInt32{*reinterpret_cast<const std::int32_t*>(data), descriptor.scale}, toScale.value());
2227
2228 case DescriptorAdjustedType::INT64:
2229 return numericConverter.numberToNumber<T>(
2230 ScaledInt64{*reinterpret_cast<const std::int64_t*>(data), descriptor.scale}, toScale.value());
2231
2232#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
2233 case DescriptorAdjustedType::INT128:
2234 return numericConverter.numberToNumber<T>(
2235 ScaledBoostInt128{*reinterpret_cast<const BoostInt128*>(data), descriptor.scale},
2236 toScale.value());
2237
2238 case DescriptorAdjustedType::DECFLOAT16:
2239 return numericConverter.numberToNumber<T>(
2240 *reinterpret_cast<const BoostDecFloat16*>(data), toScale.value());
2241
2242 case DescriptorAdjustedType::DECFLOAT34:
2243 return numericConverter.numberToNumber<T>(
2244 *reinterpret_cast<const BoostDecFloat34*>(data), toScale.value());
2245#endif
2246
2247 case DescriptorAdjustedType::FLOAT:
2248 return numericConverter.numberToNumber<T>(*reinterpret_cast<const float*>(data), toScale.value());
2249 break;
2250
2251 case DescriptorAdjustedType::DOUBLE:
2252 return numericConverter.numberToNumber<T>(*reinterpret_cast<const double*>(data), toScale.value());
2253 break;
2254
2255 default:
2256 throwInvalidType(toTypeName, descriptor.adjustedType);
2257 }
2258 }
2259
2260 private:
2261 Client& getClient() noexcept;
2262
2263 private:
2264 Attachment* attachment;
2265 impl::StatusWrapper statusWrapper;
2266 impl::CalendarConverter calendarConverter;
2267 impl::NumericConverter numericConverter;
2268 FbRef<fb::IStatement> statementHandle;
2269 FbRef<fb::IResultSet> resultSetHandle;
2270 FbRef<fb::IMessageMetadata> inMetadata;
2271 std::vector<Descriptor> inDescriptors;
2272 std::vector<std::byte> inMessage;
2273 FbRef<fb::IMessageMetadata> outMetadata;
2274 std::vector<Descriptor> outDescriptors;
2275 std::vector<std::byte> outMessage;
2276 std::unique_ptr<Row> outRow;
2277 StatementType type;
2278 unsigned cursorFlags = 0;
2279 };
2280
2285
2286 template <>
2287 inline std::optional<bool> Statement::get<std::optional<bool>>(unsigned index)
2288 {
2289 return getBool(index);
2290 }
2291
2292 template <>
2293 inline std::optional<BlobId> Statement::get<std::optional<BlobId>>(unsigned index)
2294 {
2295 return getBlobId(index);
2296 }
2297
2298 template <>
2299 inline std::optional<std::int16_t> Statement::get<std::optional<std::int16_t>>(unsigned index)
2300 {
2301 return getInt16(index);
2302 }
2303
2304 template <>
2305 inline std::optional<ScaledInt16> Statement::get<std::optional<ScaledInt16>>(unsigned index)
2306 {
2307 return getScaledInt16(index);
2308 }
2309
2310 template <>
2311 inline std::optional<std::int32_t> Statement::get<std::optional<std::int32_t>>(unsigned index)
2312 {
2313 return getInt32(index);
2314 }
2315
2316 template <>
2317 inline std::optional<ScaledInt32> Statement::get<std::optional<ScaledInt32>>(unsigned index)
2318 {
2319 return getScaledInt32(index);
2320 }
2321
2322 template <>
2323 inline std::optional<std::int64_t> Statement::get<std::optional<std::int64_t>>(unsigned index)
2324 {
2325 return getInt64(index);
2326 }
2327
2328 template <>
2329 inline std::optional<ScaledInt64> Statement::get<std::optional<ScaledInt64>>(unsigned index)
2330 {
2331 return getScaledInt64(index);
2332 }
2333
2334 template <>
2335 inline std::optional<ScaledOpaqueInt128> Statement::get<std::optional<ScaledOpaqueInt128>>(unsigned index)
2336 {
2337 return getScaledOpaqueInt128(index);
2338 }
2339
2340#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
2341 template <>
2342 inline std::optional<BoostInt128> Statement::get<std::optional<BoostInt128>>(unsigned index)
2343 {
2344 return getBoostInt128(index);
2345 }
2346
2347 template <>
2348 inline std::optional<ScaledBoostInt128> Statement::get<std::optional<ScaledBoostInt128>>(unsigned index)
2349 {
2350 return getScaledBoostInt128(index);
2351 }
2352#endif
2353
2354 template <>
2355 inline std::optional<float> Statement::get<std::optional<float>>(unsigned index)
2356 {
2357 return getFloat(index);
2358 }
2359
2360 template <>
2361 inline std::optional<double> Statement::get<std::optional<double>>(unsigned index)
2362 {
2363 return getDouble(index);
2364 }
2365
2366 template <>
2367 inline std::optional<OpaqueDecFloat16> Statement::get<std::optional<OpaqueDecFloat16>>(unsigned index)
2368 {
2369 return getOpaqueDecFloat16(index);
2370 }
2371
2372#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
2373 template <>
2374 inline std::optional<BoostDecFloat16> Statement::get<std::optional<BoostDecFloat16>>(unsigned index)
2375 {
2376 return getBoostDecFloat16(index);
2377 }
2378#endif
2379
2380#if FB_CPP_USE_BOOST_DECIMAL != 0
2381 template <>
2382 inline std::optional<BoostDecimal32> Statement::get<std::optional<BoostDecimal32>>(unsigned index)
2383 {
2384 return getBoostDecimal32(index);
2385 }
2386
2387 template <>
2388 inline std::optional<BoostDecimal64> Statement::get<std::optional<BoostDecimal64>>(unsigned index)
2389 {
2390 return getBoostDecimal64(index);
2391 }
2392#endif
2393
2394 template <>
2395 inline std::optional<OpaqueDecFloat34> Statement::get<std::optional<OpaqueDecFloat34>>(unsigned index)
2396 {
2397 return getOpaqueDecFloat34(index);
2398 }
2399
2400#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
2401 template <>
2402 inline std::optional<BoostDecFloat34> Statement::get<std::optional<BoostDecFloat34>>(unsigned index)
2403 {
2404 return getBoostDecFloat34(index);
2405 }
2406#endif
2407
2408#if FB_CPP_USE_BOOST_DECIMAL != 0
2409 template <>
2410 inline std::optional<BoostDecimal128> Statement::get<std::optional<BoostDecimal128>>(unsigned index)
2411 {
2412 return getBoostDecimal128(index);
2413 }
2414#endif
2415
2416 template <>
2417 inline std::optional<Date> Statement::get<std::optional<Date>>(unsigned index)
2418 {
2419 return getDate(index);
2420 }
2421
2422 template <>
2423 inline std::optional<OpaqueDate> Statement::get<std::optional<OpaqueDate>>(unsigned index)
2424 {
2425 return getOpaqueDate(index);
2426 }
2427
2428 template <>
2429 inline std::optional<Time> Statement::get<std::optional<Time>>(unsigned index)
2430 {
2431 return getTime(index);
2432 }
2433
2434 template <>
2435 inline std::optional<OpaqueTime> Statement::get<std::optional<OpaqueTime>>(unsigned index)
2436 {
2437 return getOpaqueTime(index);
2438 }
2439
2440 template <>
2441 inline std::optional<OpaqueTimestamp> Statement::get<std::optional<OpaqueTimestamp>>(unsigned index)
2442 {
2443 return getOpaqueTimestamp(index);
2444 }
2445
2446 template <>
2447 inline std::optional<Timestamp> Statement::get<std::optional<Timestamp>>(unsigned index)
2448 {
2449 return getTimestamp(index);
2450 }
2451
2452 template <>
2453 inline std::optional<TimeTz> Statement::get<std::optional<TimeTz>>(unsigned index)
2454 {
2455 return getTimeTz(index);
2456 }
2457
2458 template <>
2459 inline std::optional<OpaqueTimeTz> Statement::get<std::optional<OpaqueTimeTz>>(unsigned index)
2460 {
2461 return getOpaqueTimeTz(index);
2462 }
2463
2464 template <>
2465 inline std::optional<TimestampTz> Statement::get<std::optional<TimestampTz>>(unsigned index)
2466 {
2467 return getTimestampTz(index);
2468 }
2469
2470 template <>
2471 inline std::optional<OpaqueTimestampTz> Statement::get<std::optional<OpaqueTimestampTz>>(unsigned index)
2472 {
2473 return getOpaqueTimestampTz(index);
2474 }
2475
2476 template <>
2477 inline std::optional<std::string> Statement::get<std::optional<std::string>>(unsigned index)
2478 {
2479 return getString(index);
2480 }
2481
2485} // namespace fbcpp
2486
2487
2488#endif // FBCPP_STATEMENT_H
Represents a connection to a Firebird database.
Definition Attachment.h:219
Represents a Firebird blob identifier.
Definition Blob.h:53
Exception thrown when a Firebird database operation fails.
Definition Exception.h:248
Base exception class for all fb-cpp exceptions.
Definition Exception.h:231
Reference-counted smart pointer for Firebird objects using addRef/release semantics.
Definition SmartPtrs.h:70
Represents options used when preparing a Statement.
Prepares, executes, and fetches SQL statements against a Firebird attachment.
Definition Statement.h:143
void set(unsigned index, OpaqueInt128 value)
Convenience overload that binds a Firebird 128-bit integer.
Definition Statement.h:1351
void setScaledInt16(unsigned index, std::optional< ScaledInt16 > optValue)
Binds a scaled 16-bit signed integer value or null.
Definition Statement.h:440
V get(unsigned index)
Retrieves a column value as a user-defined variant type.
Definition Statement.h:1961
void setNull(unsigned index)
Marks the specified parameter as null.
Definition Statement.h:381
void setScaledBoostInt128(unsigned index, std::optional< ScaledBoostInt128 > optValue)
Binds a scaled 128-bit integer value expressed with Boost.Multiprecision or null.
Definition Statement.h:598
std::optional< OpaqueTime > getOpaqueTime(unsigned index)
Reads a raw time-of-day column in Firebird's representation.
Definition Statement.h:1790
std::optional< OpaqueDecFloat34 > getOpaqueDecFloat34(unsigned index)
Reads a Firebird 34-digit decimal floating-point column.
Definition Statement.h:1732
std::vector< std::byte > & getOutputMessage() noexcept
Provides direct access to the raw output message buffer.
Definition Statement.h:257
void setDate(unsigned index, std::optional< Date > optValue)
Binds a date value or null.
Definition Statement.h:780
const std::vector< Descriptor > & getInputDescriptors() noexcept
Provides cached descriptors for each input column.
Definition Statement.h:283
void set(unsigned index, BoostDecimal64 value)
Convenience overload that binds a Boost.Decimal 16-digit decimal floating-point value.
Definition Statement.h:1428
const std::vector< Descriptor > & getOutputDescriptors() noexcept
Provides cached descriptors for each output column.
Definition Statement.h:291
bool isValid() noexcept
Returns whether the Statement object is valid.
Definition Statement.h:207
StatementType getType() noexcept
Returns the type classification reported by the server.
Definition Statement.h:265
void set(unsigned index, BoostDecFloat16 value)
Convenience overload that binds a Boost 16-digit decimal floating-point value.
Definition Statement.h:1410
std::optional< TimeTz > getTimeTz(unsigned index)
Reads a time-of-day column with timezone.
Definition Statement.h:1817
void setTime(unsigned index, std::optional< Time > optValue)
Binds a time-of-day value without timezone or null.
Definition Statement.h:841
void set(unsigned index, std::string_view value)
Convenience overload that binds a textual value.
Definition Statement.h:1545
std::optional< BoostDecFloat34 > getBoostDecFloat34(unsigned index)
Reads a Boost-based 34-digit decimal floating-point column.
Definition Statement.h:1742
void setBlobId(unsigned index, std::optional< BlobId > optValue)
Binds a blob identifier to the specified parameter or null.
Definition Statement.h:1242
void setInt16(unsigned index, std::optional< std::int16_t > optValue)
Binds a 16-bit signed integer value or null.
Definition Statement.h:426
void setString(unsigned index, std::optional< std::string_view > optValue)
Binds a textual parameter or null, performing direct conversions where supported.
Definition Statement.h:1085
void set(unsigned index, std::int32_t value)
Convenience overload that binds a 32-bit signed integer.
Definition Statement.h:1319
std::optional< Time > getTime(unsigned index)
Reads a time-of-day column without timezone.
Definition Statement.h:1781
void set(unsigned index, ScaledOpaqueInt128 value)
Convenience overload that binds a scaled Firebird 128-bit integer.
Definition Statement.h:1359
std::optional< Date > getDate(unsigned index)
Reads a date column.
Definition Statement.h:1763
FbRef< fb::IResultSet > getResultSetHandle() noexcept
Provides access to the underlying Firebird currently open result set handle, if any.
Definition Statement.h:225
bool isNull(unsigned index)
Reports whether the most recently fetched row has a null at the given column.
Definition Statement.h:1573
void set(unsigned index, double value)
Convenience overload that binds a double precision floating-point value.
Definition Statement.h:1393
void clearParameters()
Marks all bound parameters as null values.
Definition Statement.h:367
void set(unsigned index, ScaledInt64 value)
Convenience overload that binds a scaled 64-bit signed integer.
Definition Statement.h:1343
std::optional< OpaqueDate > getOpaqueDate(unsigned index)
Reads a raw date column in Firebird's representation.
Definition Statement.h:1772
T get()
Retrieves all output columns into a user-defined aggregate struct.
Definition Statement.h:1890
void setScaledInt32(unsigned index, std::optional< ScaledInt32 > optValue)
Binds a scaled 32-bit signed integer value or null.
Definition Statement.h:469
void set(unsigned index, std::int64_t value)
Convenience overload that binds a 64-bit signed integer.
Definition Statement.h:1335
void setTimestampTz(unsigned index, std::optional< TimestampTz > optValue)
Binds a timestamp value with timezone or null.
Definition Statement.h:1024
std::optional< std::int64_t > getInt64(unsigned index)
Reads a 64-bit signed integer column.
Definition Statement.h:1627
FbRef< fb::IStatement > getStatementHandle() noexcept
Provides direct access to the underlying Firebird statement handle.
Definition Statement.h:216
void setBoostDecimal64(unsigned index, std::optional< BoostDecimal64 > optValue)
Binds a 16-digit decimal floating-point value using Boost.Decimal or null.
Definition Statement.h:703
std::optional< ScaledInt32 > getScaledInt32(unsigned index)
Reads a scaled 32-bit signed integer column.
Definition Statement.h:1618
void set(unsigned index, OpaqueTimestampTz value)
Convenience overload that binds a Firebird timestamp with timezone value.
Definition Statement.h:1537
void setOpaqueTime(unsigned index, std::optional< OpaqueTime > optValue)
Binds a raw time-of-day value in Firebird's representation or null.
Definition Statement.h:872
std::optional< float > getFloat(unsigned index)
Reads a single precision floating-point column.
Definition Statement.h:1674
std::optional< double > getDouble(unsigned index)
Reads a double precision floating-point column.
Definition Statement.h:1683
void set(unsigned index, BoostDecimal128 value)
Convenience overload that binds a Boost.Decimal 34-digit decimal floating-point value.
Definition Statement.h:1456
std::optional< OpaqueTimestampTz > getOpaqueTimestampTz(unsigned index)
Reads a raw timestamp-with-time-zone column in Firebird's representation.
Definition Statement.h:1844
std::optional< ScaledInt16 > getScaledInt16(unsigned index)
Reads a scaled 16-bit signed integer column.
Definition Statement.h:1600
std::optional< BlobId > getBlobId(unsigned index)
Reads a blob identifier column.
Definition Statement.h:1853
void setInt64(unsigned index, std::optional< std::int64_t > optValue)
Binds a 64-bit signed integer value or null.
Definition Statement.h:484
std::optional< ScaledOpaqueInt128 > getScaledOpaqueInt128(unsigned index)
Reads a Firebird scaled 128-bit integer column.
Definition Statement.h:1645
FbRef< fb::IMessageMetadata > getOutputMetadata() noexcept
Returns the metadata describing columns produced by the statement.
Definition Statement.h:249
void set(unsigned index, TimeTz value)
Convenience overload that binds a Firebird time with timezone value.
Definition Statement.h:1513
void setOpaqueDecFloat16(unsigned index, std::optional< OpaqueDecFloat16 > optValue)
Binds a 16-digit decimal floating-point value in Firebird's representation or null.
Definition Statement.h:642
void setOpaqueInt128(unsigned index, std::optional< OpaqueInt128 > optValue)
Binds a raw 128-bit integer value in Firebird's representation or null.
Definition Statement.h:513
std::optional< OpaqueTimeTz > getOpaqueTimeTz(unsigned index)
Reads a raw time-of-day column with timezone in Firebird's representation.
Definition Statement.h:1826
void setBoostInt128(unsigned index, std::optional< BoostInt128 > optValue)
Binds a 128-bit integer value expressed with Boost.Multiprecision or null.
Definition Statement.h:584
void setBoostDecimal128(unsigned index, std::optional< BoostDecimal128 > optValue)
Binds a 34-digit decimal floating-point value using Boost.Decimal or null.
Definition Statement.h:765
void set(unsigned index, Date value)
Convenience overload that binds a Firebird date value.
Definition Statement.h:1465
void set(unsigned index, Timestamp value)
Convenience overload that binds a Firebird timestamp value.
Definition Statement.h:1497
void setOpaqueTimeTz(unsigned index, std::optional< OpaqueTimeTz > optValue)
Binds a raw time-of-day value with timezone in Firebird's representation or null.
Definition Statement.h:994
void set(unsigned index, BoostDecimal32 value)
Convenience overload that binds a Boost.Decimal 7-digit decimal floating-point value.
Definition Statement.h:1420
void setTimestamp(unsigned index, std::optional< Timestamp > optValue)
Binds a timestamp value without timezone or null.
Definition Statement.h:902
std::optional< std::string > getString(unsigned index)
Reads a textual column, applying number-to-string conversions when needed.
Definition Statement.h:1862
std::optional< std::int32_t > getInt32(unsigned index)
Reads a 32-bit signed integer column.
Definition Statement.h:1609
void set(unsigned index, OpaqueDecFloat16 value)
Convenience overload that binds a Firebird 16-digit decimal floating-point value.
Definition Statement.h:1401
void setOpaqueTimestampTz(unsigned index, std::optional< OpaqueTimestampTz > optValue)
Binds a raw timestamp value with timezone in Firebird's representation or null.
Definition Statement.h:1055
FbRef< fb::IMessageMetadata > getInputMetadata() noexcept
Returns the metadata describing prepared input parameters.
Definition Statement.h:233
void setScaledOpaqueInt128(unsigned index, std::optional< ScaledOpaqueInt128 > optValue)
Binds a scaled 128-bit integer in Firebird's representation or null.
Definition Statement.h:543
~Statement() noexcept
Releases resources; ignores failures to keep destructor noexcept.
Definition Statement.h:174
void set(unsigned index, OpaqueTimeTz value)
Convenience overload that binds a Firebird time with timezone value.
Definition Statement.h:1521
void setBoostDecFloat16(unsigned index, std::optional< BoostDecFloat16 > optValue)
Binds a 16-digit decimal floating-point value using Boost.Multiprecision or null.
Definition Statement.h:673
std::optional< ScaledBoostInt128 > getScaledBoostInt128(unsigned index)
Reads a scaled Boost 128-bit integer column.
Definition Statement.h:1664
void set(unsigned index, BlobId value)
Convenience overload that binds a blob identifier.
Definition Statement.h:1279
void set(unsigned index, BoostDecFloat34 value)
Convenience overload that binds a Boost 34-digit decimal floating-point value.
Definition Statement.h:1446
void set(unsigned index, OpaqueDecFloat34 value)
Convenience overload that binds a Firebird 34-digit decimal floating-point value.
Definition Statement.h:1437
void set(unsigned index, Time value)
Convenience overload that binds a Firebird time value.
Definition Statement.h:1481
T get(unsigned index)
Retrieves a column using the most appropriate typed accessor specialization.
Definition Statement.h:1876
void set(unsigned index, ScaledInt16 value)
Convenience overload that binds a scaled 16-bit signed integer.
Definition Statement.h:1311
std::optional< BoostInt128 > getBoostInt128(unsigned index)
Reads a Boost 128-bit integer column.
Definition Statement.h:1655
std::optional< bool > getBool(unsigned index)
Reads a boolean column from the current row.
Definition Statement.h:1582
void setOpaqueDecFloat34(unsigned index, std::optional< OpaqueDecFloat34 > optValue)
Binds a 34-digit decimal floating-point value in Firebird's representation or null.
Definition Statement.h:718
void set(unsigned index, OpaqueTimestamp value)
Convenience overload that binds a Firebird timestamp value.
Definition Statement.h:1505
void setInt32(unsigned index, std::optional< std::int32_t > optValue)
Binds a 32-bit signed integer value or null.
Definition Statement.h:455
void set(unsigned index, std::optional< BlobId > value)
Convenience overload that binds an optional blob identifier.
Definition Statement.h:1287
void setBool(unsigned index, std::optional< bool > optValue)
Binds a boolean parameter value or null.
Definition Statement.h:396
void set(unsigned index, const V &value)
Sets a parameter from a variant value.
Definition Statement.h:1974
void set(unsigned index, TimestampTz value)
Convenience overload that binds a Firebird timestamp with timezone value.
Definition Statement.h:1529
void setDouble(unsigned index, std::optional< double > optValue)
Binds a double precision floating-point value or null.
Definition Statement.h:628
void set(unsigned index, OpaqueDate value)
Convenience overload that binds a Firebird date value.
Definition Statement.h:1473
void set(unsigned index, std::int16_t value)
Convenience overload that binds a 16-bit signed integer.
Definition Statement.h:1303
std::optional< BoostDecimal32 > getBoostDecimal32(unsigned index)
Reads a Boost.Decimal 7-digit decimal floating-point column.
Definition Statement.h:1713
void set(unsigned index, std::optional< T > value)
Convenience template that forwards optional values to specialized overloads.
Definition Statement.h:1554
std::optional< OpaqueTimestamp > getOpaqueTimestamp(unsigned index)
Reads a raw timestamp column in Firebird's representation.
Definition Statement.h:1808
void setScaledInt64(unsigned index, std::optional< ScaledInt64 > optValue)
Binds a scaled 64-bit signed integer value or null.
Definition Statement.h:498
Attachment & getAttachment() noexcept
Returns the Attachment object reference used to create this Statement.
Definition Statement.h:199
void set(unsigned index, std::nullopt_t)
Convenience overload that binds a null value.
Definition Statement.h:1271
void setFloat(unsigned index, std::optional< float > optValue)
Binds a single precision floating-point value or null.
Definition Statement.h:614
void setOpaqueDate(unsigned index, std::optional< OpaqueDate > optValue)
Binds a raw date value in Firebird's representation or null.
Definition Statement.h:811
std::optional< BoostDecimal64 > getBoostDecimal64(unsigned index)
Reads a Boost.Decimal 16-digit decimal floating-point column.
Definition Statement.h:1722
void set(unsigned index, OpaqueTime value)
Convenience overload that binds a Firebird time value.
Definition Statement.h:1489
void set(unsigned index, ScaledInt32 value)
Convenience overload that binds a scaled 32-bit signed integer.
Definition Statement.h:1327
std::optional< std::int16_t > getInt16(unsigned index)
Reads a 16-bit signed integer column.
Definition Statement.h:1591
void set(unsigned index, ScaledBoostInt128 value)
Convenience overload that binds a scaled Boost-provided 128-bit integer.
Definition Statement.h:1376
std::optional< TimestampTz > getTimestampTz(unsigned index)
Reads a timestamp-with-time-zone column.
Definition Statement.h:1835
void set(unsigned index, BoostInt128 value)
Convenience overload that binds a Boost-provided 128-bit integer.
Definition Statement.h:1368
std::vector< std::byte > & getInputMessage() noexcept
Provides direct access to the raw input message buffer.
Definition Statement.h:241
std::optional< OpaqueDecFloat16 > getOpaqueDecFloat16(unsigned index)
Reads a Firebird 16-digit decimal floating-point column.
Definition Statement.h:1692
std::optional< Timestamp > getTimestamp(unsigned index)
Reads a timestamp column without timezone.
Definition Statement.h:1799
std::optional< BoostDecFloat16 > getBoostDecFloat16(unsigned index)
Reads a Boost-based 16-digit decimal floating-point column.
Definition Statement.h:1702
void setTimeTz(unsigned index, std::optional< TimeTz > optValue)
Binds a time-of-day value with timezone or null.
Definition Statement.h:963
void setBoostDecimal32(unsigned index, std::optional< BoostDecimal32 > optValue)
Binds a 7-digit decimal floating-point value using Boost.Decimal or null.
Definition Statement.h:689
void setBoostDecFloat34(unsigned index, std::optional< BoostDecFloat34 > optValue)
Binds a 34-digit decimal floating-point value using Boost.Multiprecision or null.
Definition Statement.h:749
std::optional< ScaledInt64 > getScaledInt64(unsigned index)
Reads a scaled 64-bit signed integer column.
Definition Statement.h:1636
std::optional< BoostDecimal128 > getBoostDecimal128(unsigned index)
Reads a Boost.Decimal 34-digit decimal floating-point column.
Definition Statement.h:1753
void set(unsigned index, bool value)
Convenience overload that binds a boolean value.
Definition Statement.h:1295
void setOpaqueTimestamp(unsigned index, std::optional< OpaqueTimestamp > optValue)
Binds a raw timestamp value in Firebird's representation or null.
Definition Statement.h:933
void set(unsigned index, float value)
Convenience overload that binds a single precision floating-point value.
Definition Statement.h:1385
void set(const T &value)
Sets all input parameters from fields of a user-defined aggregate struct.
Definition Statement.h:1903
Represents a transaction in one or more Firebird databases.
fb-cpp namespace.
Definition Attachment.h:46
ScaledNumber< std::int64_t > ScaledInt64
Signed 64-bit scaled number.
Definition types.h:93
ScaledNumber< std::int32_t > ScaledInt32
Signed 32-bit scaled number.
Definition types.h:88
boost::multiprecision::number< boost::multiprecision::cpp_dec_float< 34 > > BoostDecFloat34
34-digit decimal floating point using Boost.Multiprecision.
Definition types.h:116
FB_DEC16 OpaqueDecFloat16
Opaque 16-digit decimal floating point exposed by the Firebird API.
Definition types.h:236
ScaledNumber< std::int16_t > ScaledInt16
Signed 16-bit scaled number.
Definition types.h:83
boost::multiprecision::number< boost::multiprecision::cpp_dec_float< 16 > > BoostDecFloat16
16-digit decimal floating point using Boost.Multiprecision.
Definition types.h:111
boost::decimal::decimal128_t BoostDecimal128
34-digit decimal floating point using Boost.Decimal.
Definition types.h:133
boost::decimal::decimal32_t BoostDecimal32
7-digit decimal floating point using Boost.Decimal.
Definition types.h:123
StatementType
Distinguishes the semantic category of the prepared SQL statement.
Definition Statement.h:80
@ SAVEPOINT
Statement manages a savepoint.
@ PUT_SEGMENT
Statement writes a blob segment - legacy feature.
@ UPDATE
Server classified the statement as an UPDATE.
@ COMMIT
Statement commits a transaction.
@ ROLLBACK
Statement rolls back a transaction.
@ EXEC_PROCEDURE
Statement executes a stored procedure.
@ DELETE
Server classified the statement as a DELETE.
@ DDL
Statement performs data definition operations.
@ GET_SEGMENT
Statement reads a blob segment - legacy feature.
@ INSERT
Server classified the statement as an INSERT.
@ SELECT
Server classified the statement as a SELECT.
@ SET_GENERATOR
Statement sets a generator (sequence) value.
@ START_TRANSACTION
Statement starts a new transaction.
@ SELECT_FOR_UPDATE
Cursor-based SELECT that allows updates.
FB_I128 OpaqueInt128
Opaque 128-bit integer exposed by the Firebird API.
Definition types.h:231
std::chrono::year_month_day Date
Firebird SQL calendar date.
Definition types.h:139
FB_DEC34 OpaqueDecFloat34
Opaque 34-digit decimal floating point exposed by the Firebird API.
Definition types.h:241
boost::multiprecision::int128_t BoostInt128
128-bit integer using Boost.Multiprecision.
Definition types.h:99
ScaledNumber< BoostInt128 > ScaledBoostInt128
Scaled 128-bit integer backed by Boost.Multiprecision.
Definition types.h:104
boost::decimal::decimal64_t BoostDecimal64
16-digit decimal floating point using Boost.Decimal.
Definition types.h:128
std::chrono::hh_mm_ss< std::chrono::microseconds > Time
Firebird SQL time-of-day with microsecond resolution.
Definition types.h:144
Describes a parameter or column.
Definition Descriptor.h:248
Wrapper for Firebird date values.
Definition types.h:252
Wrapper for Firebird time-with-time-zone values.
Definition types.h:294
Wrapper for Firebird time values.
Definition types.h:265
Wrapper for Firebird timestamp-with-time-zone values.
Definition types.h:310
Wrapper for Firebird timestamp values.
Definition types.h:278
Represents a numeric value with an explicit decimal scale.
Definition types.h:57
T value
Unscaled numeric value.
Definition types.h:72
Local time bound to a time zone.
Definition types.h:193
Timestamp bound to a time zone.
Definition types.h:214
Combined date and time with microsecond precision.
Definition types.h:150