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-api.h"
30#include "types.h"
31#include "Blob.h"
32#include "Attachment.h"
33#include "Client.h"
34#include "Row.h"
35#include "NumericConverter.h"
36#include "CalendarConverter.h"
37#include "Descriptor.h"
38#include "SmartPtrs.h"
39#include "Exception.h"
40#include "StructBinding.h"
41#include "VariantTypeTraits.h"
42#include <charconv>
43#include <cerrno>
44#include <cstdlib>
45#include <limits>
46#include <memory>
47#include <optional>
48#include <stdexcept>
49#include <string>
50#include <string_view>
51#include <type_traits>
52#include <vector>
53#include <cassert>
54#include <cmath>
55#include <cstddef>
56#include <cstdint>
57
58#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
59#include <boost/multiprecision/cpp_int.hpp>
60#include <boost/multiprecision/cpp_dec_float.hpp>
61#endif
62
66namespace fbcpp
67{
68 class Transaction;
69
73 enum class CursorType
74 {
79
84 };
85
89 class StatementOptions final
90 {
91 public:
96 {
97 return prefetchLegacyPlan;
98 }
99
106 {
107 prefetchLegacyPlan = value;
108 return *this;
109 }
110
114 bool getPrefetchPlan() const
115 {
116 return prefetchPlan;
117 }
118
125 {
126 prefetchPlan = value;
127 return *this;
128 }
129
133 const std::optional<std::string>& getCursorName() const
134 {
135 return cursorName;
136 }
137
143 StatementOptions& setCursorName(const std::string& value)
144 {
145 cursorName = value;
146 return *this;
147 }
148
153 {
154 return cursorType;
155 }
156
163 {
164 cursorType = value;
165 return *this;
166 }
167
171 unsigned getDialect() const
172 {
173 return dialect;
174 }
175
182 {
183 dialect = value;
184 return *this;
185 }
186
187 private:
188 bool prefetchLegacyPlan = false;
189 bool prefetchPlan = false;
190 std::optional<std::string> cursorName;
192 unsigned dialect = SQL_DIALECT_CURRENT;
193 };
194
198 enum class StatementType : unsigned
199 {
203 SELECT = isc_info_sql_stmt_select,
207 INSERT = isc_info_sql_stmt_insert,
211 UPDATE = isc_info_sql_stmt_update,
215 DELETE = isc_info_sql_stmt_delete,
219 DDL = isc_info_sql_stmt_ddl,
223 GET_SEGMENT = isc_info_sql_stmt_get_segment,
227 PUT_SEGMENT = isc_info_sql_stmt_put_segment,
231 EXEC_PROCEDURE = isc_info_sql_stmt_exec_procedure,
235 START_TRANSACTION = isc_info_sql_stmt_start_trans,
239 COMMIT = isc_info_sql_stmt_commit,
243 ROLLBACK = isc_info_sql_stmt_rollback,
247 SELECT_FOR_UPDATE = isc_info_sql_stmt_select_for_upd,
251 SET_GENERATOR = isc_info_sql_stmt_set_generator,
255 SAVEPOINT = isc_info_sql_stmt_savepoint,
256 };
257
261 class Statement final
262 {
263 public:
271 explicit Statement(Attachment& attachment, Transaction& transaction, std::string_view sql,
272 const StatementOptions& options = {});
273
277 Statement(Statement&& o) noexcept
278 : attachment{o.attachment},
279 statusWrapper{std::move(o.statusWrapper)},
280 calendarConverter{std::move(o.calendarConverter)},
281 numericConverter{std::move(o.numericConverter)},
282 statementHandle{std::move(o.statementHandle)},
283 resultSetHandle{std::move(o.resultSetHandle)},
284 inMetadata{std::move(o.inMetadata)},
285 inDescriptors{std::move(o.inDescriptors)},
286 inMessage{std::move(o.inMessage)},
287 outMetadata{std::move(o.outMetadata)},
288 outDescriptors{std::move(o.outDescriptors)},
289 outMessage{std::move(o.outMessage)},
290 outRow{std::make_unique<Row>(attachment->getClient(), outDescriptors, std::span{outMessage})},
291 type{o.type},
292 cursorFlags{o.cursorFlags}
293 {
294 o.outRow.reset();
295 }
296
304 {
305 if (this != &o)
306 {
307 attachment = o.attachment;
308 statusWrapper = std::move(o.statusWrapper);
309 calendarConverter = std::move(o.calendarConverter);
310 numericConverter = std::move(o.numericConverter);
311 statementHandle = std::move(o.statementHandle);
312 resultSetHandle = std::move(o.resultSetHandle);
313 inMetadata = std::move(o.inMetadata);
314 inDescriptors = std::move(o.inDescriptors);
315 inMessage = std::move(o.inMessage);
316 outMetadata = std::move(o.outMetadata);
317 outDescriptors = std::move(o.outDescriptors);
318 outMessage = std::move(o.outMessage);
319 outRow = std::make_unique<Row>(attachment->getClient(), outDescriptors, std::span{outMessage});
320 type = o.type;
321 cursorFlags = o.cursorFlags;
322
323 o.outRow.reset();
324 }
325
326 return *this;
327 }
328
329 Statement(const Statement&) = delete;
330 Statement& operator=(const Statement&) = delete;
331
335 ~Statement() noexcept
336 {
337 if (isValid())
338 {
339 try
340 {
341 free();
342 }
343 catch (...)
344 {
345 // swallow
346 }
347 }
348 }
349
350 public:
356
361 {
362 return *attachment;
363 }
364
368 bool isValid() noexcept
369 {
370 return statementHandle != nullptr;
371 }
372
378 {
379 return statementHandle;
380 }
381
387 {
388 return resultSetHandle;
389 }
390
395 {
396 return inMetadata;
397 }
398
402 std::vector<std::byte>& getInputMessage() noexcept
403 {
404 return inMessage;
405 }
406
411 {
412 return outMetadata;
413 }
414
418 std::vector<std::byte>& getOutputMessage() noexcept
419 {
420 return outMessage;
421 }
422
427 {
428 return type;
429 }
430
434
440
444 const std::vector<Descriptor>& getInputDescriptors() noexcept
445 {
446 return inDescriptors;
447 }
448
452 const std::vector<Descriptor>& getOutputDescriptors() noexcept
453 {
454 return outDescriptors;
455 }
456
460
464 void free();
465
469 std::string getLegacyPlan();
470
474 std::string getPlan();
475
481 bool execute(Transaction& transaction);
482
486
490 bool fetchNext();
491
495 bool fetchPrior();
496
500 bool fetchFirst();
501
505 bool fetchLast();
506
510 bool fetchAbsolute(unsigned position);
511
515 bool fetchRelative(int offset);
516
520
524
529 {
530 assert(isValid());
531
532 const auto message = inMessage.data();
533
534 for (const auto& descriptor : inDescriptors)
535 *reinterpret_cast<std::int16_t*>(&message[descriptor.nullOffset]) = FB_TRUE;
536 }
537
542 void setNull(unsigned index)
543 {
544 assert(isValid());
545
546 const auto& descriptor = getInDescriptor(index);
547 const auto message = inMessage.data();
548
549 *reinterpret_cast<std::int16_t*>(&message[descriptor.nullOffset]) = FB_TRUE;
550 }
551
557 void setBool(unsigned index, std::optional<bool> optValue)
558 {
559 if (!optValue.has_value())
560 {
561 setNull(index);
562 return;
563 }
564
565 assert(isValid());
566
567 const auto& value = optValue.value();
568 const auto& descriptor = getInDescriptor(index);
569 const auto message = inMessage.data();
570
571 switch (descriptor.adjustedType)
572 {
574 message[descriptor.offset] = value ? std::byte{1} : std::byte{0};
575 break;
576
577 default:
578 throwInvalidType("bool", descriptor.adjustedType);
579 }
580
581 *reinterpret_cast<std::int16_t*>(&message[descriptor.nullOffset]) = FB_FALSE;
582 }
583
587 void setInt16(unsigned index, std::optional<std::int16_t> optValue)
588 {
589 if (!optValue.has_value())
590 {
591 setNull(index);
592 return;
593 }
594
595 setNumber(index, DescriptorAdjustedType::INT16, optValue.value(), 0, "std::int16_t");
596 }
597
601 void setScaledInt16(unsigned index, std::optional<ScaledInt16> optValue)
602 {
603 if (!optValue.has_value())
604 {
605 setNull(index);
606 return;
607 }
608
609 const auto& value = optValue.value();
610 setNumber(index, DescriptorAdjustedType::INT16, value.value, value.scale, "ScaledInt16");
611 }
612
616 void setInt32(unsigned index, std::optional<std::int32_t> optValue)
617 {
618 if (!optValue.has_value())
619 {
620 setNull(index);
621 return;
622 }
623
624 setNumber(index, DescriptorAdjustedType::INT32, optValue.value(), 0, "std::int32_t");
625 }
626
630 void setScaledInt32(unsigned index, std::optional<ScaledInt32> optValue)
631 {
632 if (!optValue.has_value())
633 {
634 setNull(index);
635 return;
636 }
637
638 const auto& value = optValue.value();
639 setNumber(index, DescriptorAdjustedType::INT32, value.value, value.scale, "ScaledInt32");
640 }
641
645 void setInt64(unsigned index, std::optional<std::int64_t> optValue)
646 {
647 if (!optValue.has_value())
648 {
649 setNull(index);
650 return;
651 }
652
653 setNumber(index, DescriptorAdjustedType::INT64, optValue.value(), 0, "std::int64_t");
654 }
655
659 void setScaledInt64(unsigned index, std::optional<ScaledInt64> optValue)
660 {
661 if (!optValue.has_value())
662 {
663 setNull(index);
664 return;
665 }
666
667 const auto& value = optValue.value();
668 setNumber(index, DescriptorAdjustedType::INT64, value.value, value.scale, "ScaledInt64");
669 }
670
674 void setOpaqueInt128(unsigned index, std::optional<OpaqueInt128> optValue)
675 {
676 if (!optValue.has_value())
677 {
678 setNull(index);
679 return;
680 }
681
682 assert(isValid());
683
684 const auto& value = optValue.value();
685 const auto& descriptor = getInDescriptor(index);
686 const auto message = inMessage.data();
687
688 switch (descriptor.adjustedType)
689 {
691 *reinterpret_cast<OpaqueInt128*>(&message[descriptor.offset]) = value;
692 break;
693
694 default:
695 throwInvalidType("OpaqueInt128", descriptor.adjustedType);
696 }
697
698 *reinterpret_cast<std::int16_t*>(&message[descriptor.nullOffset]) = FB_FALSE;
699 }
700
701#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
705 void setBoostInt128(unsigned index, std::optional<BoostInt128> optValue)
706 {
707 if (!optValue.has_value())
708 {
709 setNull(index);
710 return;
711 }
712
713 setNumber(index, DescriptorAdjustedType::INT128, optValue.value(), 0, "BoostInt128");
714 }
715
719 void setScaledBoostInt128(unsigned index, std::optional<ScaledBoostInt128> optValue)
720 {
721 if (!optValue.has_value())
722 {
723 setNull(index);
724 return;
725 }
726
727 const auto& value = optValue.value();
728 setNumber(index, DescriptorAdjustedType::INT128, value.value, value.scale, "ScaledBoostInt128");
729 }
730#endif
731
735 void setFloat(unsigned index, std::optional<float> optValue)
736 {
737 if (!optValue.has_value())
738 {
739 setNull(index);
740 return;
741 }
742
743 setNumber(index, DescriptorAdjustedType::FLOAT, optValue.value(), 0, "float");
744 }
745
749 void setDouble(unsigned index, std::optional<double> optValue)
750 {
751 if (!optValue.has_value())
752 {
753 setNull(index);
754 return;
755 }
756
757 setNumber(index, DescriptorAdjustedType::DOUBLE, optValue.value(), 0, "double");
758 }
759
763 void setOpaqueDecFloat16(unsigned index, std::optional<OpaqueDecFloat16> optValue)
764 {
765 if (!optValue.has_value())
766 {
767 setNull(index);
768 return;
769 }
770
771 assert(isValid());
772
773 const auto& value = optValue.value();
774 const auto& descriptor = getInDescriptor(index);
775 const auto message = inMessage.data();
776
777 switch (descriptor.adjustedType)
778 {
780 *reinterpret_cast<OpaqueDecFloat16*>(&message[descriptor.offset]) = value;
781 break;
782
783 default:
784 throwInvalidType("OpaqueDecFloat16", descriptor.adjustedType);
785 }
786
787 *reinterpret_cast<std::int16_t*>(&message[descriptor.nullOffset]) = FB_FALSE;
788 }
789
790#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
794 void setBoostDecFloat16(unsigned index, std::optional<BoostDecFloat16> optValue)
795 {
796 if (!optValue.has_value())
797 {
798 setNull(index);
799 return;
800 }
801
802 setNumber(index, DescriptorAdjustedType::DECFLOAT16, optValue.value(), 0, "BoostDecFloat16");
803 }
804#endif
805
809 void setOpaqueDecFloat34(unsigned index, std::optional<OpaqueDecFloat34> optValue)
810 {
811 if (!optValue.has_value())
812 {
813 setNull(index);
814 return;
815 }
816
817 assert(isValid());
818
819 const auto& value = optValue.value();
820 const auto& descriptor = getInDescriptor(index);
821 const auto message = inMessage.data();
822
823 switch (descriptor.adjustedType)
824 {
826 *reinterpret_cast<OpaqueDecFloat34*>(&message[descriptor.offset]) = value;
827 break;
828
829 default:
830 throwInvalidType("OpaqueDecFloat34", descriptor.adjustedType);
831 }
832
833 *reinterpret_cast<std::int16_t*>(&message[descriptor.nullOffset]) = FB_FALSE;
834 }
835
836#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
840 void setBoostDecFloat34(unsigned index, std::optional<BoostDecFloat34> optValue)
841 {
842 if (!optValue.has_value())
843 {
844 setNull(index);
845 return;
846 }
847
848 setNumber(index, DescriptorAdjustedType::DECFLOAT34, optValue.value(), 0, "BoostDecFloat34");
849 }
850#endif
851
855 void setDate(unsigned index, std::optional<Date> optValue)
856 {
857 if (!optValue.has_value())
858 {
859 setNull(index);
860 return;
861 }
862
863 assert(isValid());
864
865 const auto& value = optValue.value();
866 const auto& descriptor = getInDescriptor(index);
867 const auto message = inMessage.data();
868
869 switch (descriptor.adjustedType)
870 {
872 *reinterpret_cast<OpaqueDate*>(&message[descriptor.offset]) =
873 calendarConverter.dateToOpaqueDate(value);
874 break;
875
876 default:
877 throwInvalidType("Date", descriptor.adjustedType);
878 }
879
880 *reinterpret_cast<std::int16_t*>(&message[descriptor.nullOffset]) = FB_FALSE;
881 }
882
886 void setOpaqueDate(unsigned index, std::optional<OpaqueDate> optValue)
887 {
888 if (!optValue.has_value())
889 {
890 setNull(index);
891 return;
892 }
893
894 assert(isValid());
895
896 const auto& value = optValue.value();
897 const auto& descriptor = getInDescriptor(index);
898 const auto message = inMessage.data();
899
900 switch (descriptor.adjustedType)
901 {
903 *reinterpret_cast<OpaqueDate*>(&message[descriptor.offset]) = value;
904 break;
905
906 default:
907 throwInvalidType("OpaqueDate", descriptor.adjustedType);
908 }
909
910 *reinterpret_cast<std::int16_t*>(&message[descriptor.nullOffset]) = FB_FALSE;
911 }
912
916 void setTime(unsigned index, std::optional<Time> optValue)
917 {
918 if (!optValue.has_value())
919 {
920 setNull(index);
921 return;
922 }
923
924 assert(isValid());
925
926 const auto& value = optValue.value();
927 const auto& descriptor = getInDescriptor(index);
928 const auto message = inMessage.data();
929
930 switch (descriptor.adjustedType)
931 {
933 *reinterpret_cast<OpaqueTime*>(&message[descriptor.offset]) =
934 calendarConverter.timeToOpaqueTime(value);
935 break;
936
937 default:
938 throwInvalidType("Time", descriptor.adjustedType);
939 }
940
941 *reinterpret_cast<std::int16_t*>(&message[descriptor.nullOffset]) = FB_FALSE;
942 }
943
947 void setOpaqueTime(unsigned index, std::optional<OpaqueTime> optValue)
948 {
949 if (!optValue.has_value())
950 {
951 setNull(index);
952 return;
953 }
954
955 assert(isValid());
956
957 const auto& value = optValue.value();
958 const auto& descriptor = getInDescriptor(index);
959 const auto message = inMessage.data();
960
961 switch (descriptor.adjustedType)
962 {
964 *reinterpret_cast<OpaqueTime*>(&message[descriptor.offset]) = value;
965 break;
966
967 default:
968 throwInvalidType("OpaqueTime", descriptor.adjustedType);
969 }
970
971 *reinterpret_cast<std::int16_t*>(&message[descriptor.nullOffset]) = FB_FALSE;
972 }
973
977 void setTimestamp(unsigned index, std::optional<Timestamp> optValue)
978 {
979 if (!optValue.has_value())
980 {
981 setNull(index);
982 return;
983 }
984
985 assert(isValid());
986
987 const auto& value = optValue.value();
988 const auto& descriptor = getInDescriptor(index);
989 const auto message = inMessage.data();
990
991 switch (descriptor.adjustedType)
992 {
994 *reinterpret_cast<OpaqueTimestamp*>(&message[descriptor.offset]) =
995 calendarConverter.timestampToOpaqueTimestamp(value);
996 break;
997
998 default:
999 throwInvalidType("Timestamp", descriptor.adjustedType);
1000 }
1001
1002 *reinterpret_cast<std::int16_t*>(&message[descriptor.nullOffset]) = FB_FALSE;
1003 }
1004
1008 void setOpaqueTimestamp(unsigned index, std::optional<OpaqueTimestamp> optValue)
1009 {
1010 if (!optValue.has_value())
1011 {
1012 setNull(index);
1013 return;
1014 }
1015
1016 assert(isValid());
1017
1018 const auto& value = optValue.value();
1019 const auto& descriptor = getInDescriptor(index);
1020 const auto message = inMessage.data();
1021
1022 switch (descriptor.adjustedType)
1023 {
1025 *reinterpret_cast<OpaqueTimestamp*>(&message[descriptor.offset]) = value;
1026 break;
1027
1028 default:
1029 throwInvalidType("OpaqueTimestamp", descriptor.adjustedType);
1030 }
1031
1032 *reinterpret_cast<std::int16_t*>(&message[descriptor.nullOffset]) = FB_FALSE;
1033 }
1034
1038 void setTimeTz(unsigned index, std::optional<TimeTz> optValue)
1039 {
1040 if (!optValue.has_value())
1041 {
1042 setNull(index);
1043 return;
1044 }
1045
1046 assert(isValid());
1047
1048 const auto& value = optValue.value();
1049 const auto& descriptor = getInDescriptor(index);
1050 auto* const message = inMessage.data();
1051
1052 switch (descriptor.adjustedType)
1053 {
1055 *reinterpret_cast<OpaqueTimeTz*>(&message[descriptor.offset]) =
1056 calendarConverter.timeTzToOpaqueTimeTz(&statusWrapper, value);
1057 break;
1058
1059 default:
1060 throwInvalidType("TimeTz", descriptor.adjustedType);
1061 }
1062
1063 *reinterpret_cast<std::int16_t*>(&message[descriptor.nullOffset]) = FB_FALSE;
1064 }
1065
1069 void setOpaqueTimeTz(unsigned index, std::optional<OpaqueTimeTz> optValue)
1070 {
1071 if (!optValue.has_value())
1072 {
1073 setNull(index);
1074 return;
1075 }
1076
1077 assert(isValid());
1078
1079 const auto& value = optValue.value();
1080 const auto& descriptor = getInDescriptor(index);
1081 auto* const message = inMessage.data();
1082
1083 switch (descriptor.adjustedType)
1084 {
1086 *reinterpret_cast<OpaqueTimeTz*>(&message[descriptor.offset]) = value;
1087 break;
1088
1089 default:
1090 throwInvalidType("OpaqueTimeTz", descriptor.adjustedType);
1091 }
1092
1093 *reinterpret_cast<std::int16_t*>(&message[descriptor.nullOffset]) = FB_FALSE;
1094 }
1095
1099 void setTimestampTz(unsigned index, std::optional<TimestampTz> optValue)
1100 {
1101 if (!optValue.has_value())
1102 {
1103 setNull(index);
1104 return;
1105 }
1106
1107 assert(isValid());
1108
1109 const auto& value = optValue.value();
1110 const auto& descriptor = getInDescriptor(index);
1111 auto* const message = inMessage.data();
1112
1113 switch (descriptor.adjustedType)
1114 {
1116 *reinterpret_cast<OpaqueTimestampTz*>(&message[descriptor.offset]) =
1117 calendarConverter.timestampTzToOpaqueTimestampTz(&statusWrapper, value);
1118 break;
1119
1120 default:
1121 throwInvalidType("TimestampTz", descriptor.adjustedType);
1122 }
1123
1124 *reinterpret_cast<std::int16_t*>(&message[descriptor.nullOffset]) = FB_FALSE;
1125 }
1126
1130 void setOpaqueTimestampTz(unsigned index, std::optional<OpaqueTimestampTz> optValue)
1131 {
1132 if (!optValue.has_value())
1133 {
1134 setNull(index);
1135 return;
1136 }
1137
1138 assert(isValid());
1139
1140 const auto& value = optValue.value();
1141 const auto& descriptor = getInDescriptor(index);
1142 auto* const message = inMessage.data();
1143
1144 switch (descriptor.adjustedType)
1145 {
1147 *reinterpret_cast<OpaqueTimestampTz*>(&message[descriptor.offset]) = value;
1148 break;
1149
1150 default:
1151 throwInvalidType("OpaqueTimestampTz", descriptor.adjustedType);
1152 }
1153
1154 *reinterpret_cast<std::int16_t*>(&message[descriptor.nullOffset]) = FB_FALSE;
1155 }
1156
1160 void setString(unsigned index, std::optional<std::string_view> optValue)
1161 {
1162 if (!optValue.has_value())
1163 {
1164 setNull(index);
1165 return;
1166 }
1167
1168 assert(isValid());
1169
1170 auto& client = attachment->getClient();
1171 const auto value = optValue.value();
1172 const auto& descriptor = getInDescriptor(index);
1173 const auto message = inMessage.data();
1174 const auto data = &message[descriptor.offset];
1175
1176 switch (descriptor.adjustedType)
1177 {
1179 message[descriptor.offset] = numericConverter.stringToBoolean(value);
1180 break;
1181
1185 {
1186 std::string strValue(value);
1187 int scale = 0;
1188
1189 if (const auto dotPos = strValue.find_last_of('.'); dotPos != std::string_view::npos)
1190 {
1191 for (auto pos = dotPos + 1; pos < strValue.size(); ++pos)
1192 {
1193 const char c = value[pos];
1194
1195 if (c < '0' || c > '9')
1196 break;
1197
1198 --scale;
1199 }
1200
1201 strValue.erase(dotPos, 1);
1202 }
1203
1204 static_assert(sizeof(long long) == sizeof(std::int64_t));
1205 std::int64_t intValue;
1206 const auto convResult =
1207 std::from_chars(strValue.data(), strValue.data() + strValue.size(), intValue);
1208 if (convResult.ec != std::errc{} || convResult.ptr != strValue.data() + strValue.size())
1209 numericConverter.throwConversionErrorFromString(strValue);
1210 auto scaledValue = ScaledInt64{intValue, scale};
1211
1212 if (scale != descriptor.scale)
1213 {
1214 scaledValue.value =
1215 numericConverter.numberToNumber<std::int64_t>(scaledValue, descriptor.scale);
1216 scaledValue.scale = descriptor.scale;
1217 }
1218
1219 setScaledInt64(index, scaledValue);
1220 return;
1221 }
1222
1224 {
1225 std::string strValue(value);
1226 client.getInt128Util(&statusWrapper)
1227 ->fromString(
1228 &statusWrapper, descriptor.scale, strValue.c_str(), reinterpret_cast<OpaqueInt128*>(data));
1229 break;
1230 }
1231
1234 {
1235 double doubleValue;
1236#if defined(__APPLE__)
1237 errno = 0;
1238 std::string valueString{value};
1239 char* parseEnd = nullptr;
1240 doubleValue = std::strtod(valueString.c_str(), &parseEnd);
1241 if (parseEnd != valueString.c_str() + valueString.size() || errno == ERANGE)
1242 numericConverter.throwConversionErrorFromString(std::move(valueString));
1243#else
1244 const auto convResult = std::from_chars(value.data(), value.data() + value.size(), doubleValue);
1245 if (convResult.ec != std::errc{} || convResult.ptr != value.data() + value.size())
1246 numericConverter.throwConversionErrorFromString(std::string{value});
1247#endif
1248 setDouble(index, doubleValue);
1249 return;
1250 }
1251
1253 *reinterpret_cast<OpaqueDate*>(data) = calendarConverter.stringToOpaqueDate(value);
1254 break;
1255
1257 *reinterpret_cast<OpaqueTime*>(data) = calendarConverter.stringToOpaqueTime(value);
1258 break;
1259
1261 *reinterpret_cast<OpaqueTimestamp*>(data) = calendarConverter.stringToOpaqueTimestamp(value);
1262 break;
1263
1265 *reinterpret_cast<OpaqueTimeTz*>(data) =
1266 calendarConverter.stringToOpaqueTimeTz(&statusWrapper, value);
1267 break;
1268
1270 *reinterpret_cast<OpaqueTimestampTz*>(data) =
1271 calendarConverter.stringToOpaqueTimestampTz(&statusWrapper, value);
1272 break;
1273
1274#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
1276 {
1277 std::string strValue{value};
1278 client.getDecFloat16Util(&statusWrapper)
1279 ->fromString(&statusWrapper, strValue.c_str(), reinterpret_cast<OpaqueDecFloat16*>(data));
1280 break;
1281 }
1282
1284 {
1285 std::string strValue{value};
1286 client.getDecFloat34Util(&statusWrapper)
1287 ->fromString(&statusWrapper, strValue.c_str(), reinterpret_cast<OpaqueDecFloat34*>(data));
1288 break;
1289 }
1290#endif
1291
1293 if (value.length() > descriptor.length)
1294 {
1295 static constexpr std::intptr_t STATUS_STRING_TRUNCATION[] = {
1296 isc_arith_except,
1297 isc_string_truncation,
1298 isc_arg_end,
1299 };
1300
1301 throw DatabaseException(client, STATUS_STRING_TRUNCATION);
1302 }
1303
1304 *reinterpret_cast<std::uint16_t*>(data) = static_cast<std::uint16_t>(value.length());
1305 std::copy(value.begin(), value.end(),
1306 reinterpret_cast<char*>(&message[descriptor.offset + sizeof(std::uint16_t)]));
1307 break;
1308
1309 default:
1310 throwInvalidType("std::string_view", descriptor.adjustedType);
1311 }
1312
1313 *reinterpret_cast<std::int16_t*>(&message[descriptor.nullOffset]) = FB_FALSE;
1314 }
1315
1319 void setBlobId(unsigned index, std::optional<BlobId> optValue)
1320 {
1321 if (!optValue.has_value())
1322 {
1323 setNull(index);
1324 return;
1325 }
1326
1327 assert(isValid());
1328
1329 const auto& value = optValue.value();
1330 const auto& descriptor = getInDescriptor(index);
1331 auto* const message = inMessage.data();
1332
1333 switch (descriptor.adjustedType)
1334 {
1336 *reinterpret_cast<ISC_QUAD*>(&message[descriptor.offset]) = value.id;
1337 break;
1338
1339 default:
1340 throwInvalidType("BlobId", descriptor.adjustedType);
1341 }
1342
1343 *reinterpret_cast<std::int16_t*>(&message[descriptor.nullOffset]) = FB_FALSE;
1344 }
1345
1348 void set(unsigned index, std::nullopt_t)
1349 {
1350 setNull(index);
1351 }
1352
1356 void set(unsigned index, BlobId value)
1357 {
1358 setBlobId(index, value);
1359 }
1360
1364 void set(unsigned index, std::optional<BlobId> value)
1365 {
1366 setBlobId(index, value);
1367 }
1368
1372 void set(unsigned index, bool value)
1373 {
1374 setBool(index, value);
1375 }
1376
1380 void set(unsigned index, std::int16_t value)
1381 {
1382 setInt16(index, value);
1383 }
1384
1388 void set(unsigned index, ScaledInt16 value)
1389 {
1390 setScaledInt16(index, value);
1391 }
1392
1396 void set(unsigned index, std::int32_t value)
1397 {
1398 setInt32(index, value);
1399 }
1400
1404 void set(unsigned index, ScaledInt32 value)
1405 {
1406 setScaledInt32(index, value);
1407 }
1408
1412 void set(unsigned index, std::int64_t value)
1413 {
1414 setInt64(index, value);
1415 }
1416
1420 void set(unsigned index, ScaledInt64 value)
1421 {
1422 setScaledInt64(index, value);
1423 }
1424
1428 void set(unsigned index, OpaqueInt128 value)
1429 {
1430 setOpaqueInt128(index, value);
1431 }
1432
1433#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
1437 void set(unsigned index, BoostInt128 value)
1438 {
1439 setBoostInt128(index, value);
1440 }
1441
1445 void set(unsigned index, ScaledBoostInt128 value)
1446 {
1447 setScaledBoostInt128(index, value);
1448 }
1449#endif
1450
1454 void set(unsigned index, float value)
1455 {
1456 setFloat(index, value);
1457 }
1458
1462 void set(unsigned index, double value)
1463 {
1464 setDouble(index, value);
1465 }
1466
1470 void set(unsigned index, OpaqueDecFloat16 value)
1471 {
1472 setOpaqueDecFloat16(index, value);
1473 }
1474
1475#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
1479 void set(unsigned index, BoostDecFloat16 value)
1480 {
1481 setBoostDecFloat16(index, value);
1482 }
1483#endif
1484
1488 void set(unsigned index, OpaqueDecFloat34 value)
1489 {
1490 setOpaqueDecFloat34(index, value);
1491 }
1492
1493#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
1497 void set(unsigned index, BoostDecFloat34 value)
1498 {
1499 setBoostDecFloat34(index, value);
1500 }
1501#endif
1502
1506 void set(unsigned index, Date value)
1507 {
1508 setDate(index, value);
1509 }
1510
1514 void set(unsigned index, OpaqueDate value)
1515 {
1516 setOpaqueDate(index, value);
1517 }
1518
1522 void set(unsigned index, Time value)
1523 {
1524 setTime(index, value);
1525 }
1526
1530 void set(unsigned index, OpaqueTime value)
1531 {
1532 setOpaqueTime(index, value);
1533 }
1534
1538 void set(unsigned index, Timestamp value)
1539 {
1540 setTimestamp(index, value);
1541 }
1542
1546 void set(unsigned index, OpaqueTimestamp value)
1547 {
1548 setOpaqueTimestamp(index, value);
1549 }
1550
1554 void set(unsigned index, TimeTz value)
1555 {
1556 setTimeTz(index, value);
1557 }
1558
1562 void set(unsigned index, OpaqueTimeTz value)
1563 {
1564 setOpaqueTimeTz(index, value);
1565 }
1566
1570 void set(unsigned index, TimestampTz value)
1571 {
1572 setTimestampTz(index, value);
1573 }
1574
1578 void set(unsigned index, OpaqueTimestampTz value)
1579 {
1580 setOpaqueTimestampTz(index, value);
1581 }
1582
1586 void set(unsigned index, std::string_view value)
1587 {
1588 setString(index, value);
1589 }
1590
1594 template <typename T>
1595 void set(unsigned index, std::optional<T> value)
1596 {
1597 if (value.has_value())
1598 set(index, value.value());
1599 else
1600 setNull(index);
1601 }
1602
1606
1610
1614 bool isNull(unsigned index)
1615 {
1616 assert(isValid());
1617 return outRow->isNull(index);
1618 }
1619
1623 std::optional<bool> getBool(unsigned index)
1624 {
1625 assert(isValid());
1626 return outRow->getBool(index);
1627 }
1628
1632 std::optional<std::int16_t> getInt16(unsigned index)
1633 {
1634 assert(isValid());
1635 return outRow->getInt16(index);
1636 }
1637
1641 std::optional<ScaledInt16> getScaledInt16(unsigned index)
1642 {
1643 assert(isValid());
1644 return outRow->getScaledInt16(index);
1645 }
1646
1650 std::optional<std::int32_t> getInt32(unsigned index)
1651 {
1652 assert(isValid());
1653 return outRow->getInt32(index);
1654 }
1655
1659 std::optional<ScaledInt32> getScaledInt32(unsigned index)
1660 {
1661 assert(isValid());
1662 return outRow->getScaledInt32(index);
1663 }
1664
1668 std::optional<std::int64_t> getInt64(unsigned index)
1669 {
1670 assert(isValid());
1671 return outRow->getInt64(index);
1672 }
1673
1677 std::optional<ScaledInt64> getScaledInt64(unsigned index)
1678 {
1679 assert(isValid());
1680 return outRow->getScaledInt64(index);
1681 }
1682
1686 std::optional<ScaledOpaqueInt128> getScaledOpaqueInt128(unsigned index)
1687 {
1688 assert(isValid());
1689 return outRow->getScaledOpaqueInt128(index);
1690 }
1691
1692#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
1696 std::optional<BoostInt128> getBoostInt128(unsigned index)
1697 {
1698 assert(isValid());
1699 return outRow->getBoostInt128(index);
1700 }
1701
1705 std::optional<ScaledBoostInt128> getScaledBoostInt128(unsigned index)
1706 {
1707 assert(isValid());
1708 return outRow->getScaledBoostInt128(index);
1709 }
1710#endif
1711
1715 std::optional<float> getFloat(unsigned index)
1716 {
1717 assert(isValid());
1718 return outRow->getFloat(index);
1719 }
1720
1724 std::optional<double> getDouble(unsigned index)
1725 {
1726 assert(isValid());
1727 return outRow->getDouble(index);
1728 }
1729
1733 std::optional<OpaqueDecFloat16> getOpaqueDecFloat16(unsigned index)
1734 {
1735 assert(isValid());
1736 return outRow->getOpaqueDecFloat16(index);
1737 }
1738
1739#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
1743 std::optional<BoostDecFloat16> getBoostDecFloat16(unsigned index)
1744 {
1745 assert(isValid());
1746 return outRow->getBoostDecFloat16(index);
1747 }
1748#endif
1749
1753 std::optional<OpaqueDecFloat34> getOpaqueDecFloat34(unsigned index)
1754 {
1755 assert(isValid());
1756 return outRow->getOpaqueDecFloat34(index);
1757 }
1758
1759#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
1763 std::optional<BoostDecFloat34> getBoostDecFloat34(unsigned index)
1764 {
1765 assert(isValid());
1766 return outRow->getBoostDecFloat34(index);
1767 }
1768#endif
1769
1773 std::optional<Date> getDate(unsigned index)
1774 {
1775 assert(isValid());
1776 return outRow->getDate(index);
1777 }
1778
1782 std::optional<OpaqueDate> getOpaqueDate(unsigned index)
1783 {
1784 assert(isValid());
1785 return outRow->getOpaqueDate(index);
1786 }
1787
1791 std::optional<Time> getTime(unsigned index)
1792 {
1793 assert(isValid());
1794 return outRow->getTime(index);
1795 }
1796
1800 std::optional<OpaqueTime> getOpaqueTime(unsigned index)
1801 {
1802 assert(isValid());
1803 return outRow->getOpaqueTime(index);
1804 }
1805
1809 std::optional<Timestamp> getTimestamp(unsigned index)
1810 {
1811 assert(isValid());
1812 return outRow->getTimestamp(index);
1813 }
1814
1818 std::optional<OpaqueTimestamp> getOpaqueTimestamp(unsigned index)
1819 {
1820 assert(isValid());
1821 return outRow->getOpaqueTimestamp(index);
1822 }
1823
1827 std::optional<TimeTz> getTimeTz(unsigned index)
1828 {
1829 assert(isValid());
1830 return outRow->getTimeTz(index);
1831 }
1832
1836 std::optional<OpaqueTimeTz> getOpaqueTimeTz(unsigned index)
1837 {
1838 assert(isValid());
1839 return outRow->getOpaqueTimeTz(index);
1840 }
1841
1845 std::optional<TimestampTz> getTimestampTz(unsigned index)
1846 {
1847 assert(isValid());
1848 return outRow->getTimestampTz(index);
1849 }
1850
1854 std::optional<OpaqueTimestampTz> getOpaqueTimestampTz(unsigned index)
1855 {
1856 assert(isValid());
1857 return outRow->getOpaqueTimestampTz(index);
1858 }
1859
1863 std::optional<BlobId> getBlobId(unsigned index)
1864 {
1865 assert(isValid());
1866 return outRow->getBlobId(index);
1867 }
1868
1872 std::optional<std::string> getString(unsigned index)
1873 {
1874 assert(isValid());
1875 return outRow->getString(index);
1876 }
1877
1881
1885 template <typename T>
1886 T get(unsigned index)
1887 {
1888 assert(isValid());
1889 return outRow->get<T>(index);
1890 }
1891
1899 template <Aggregate T>
1901 {
1902 assert(isValid());
1903 return outRow->get<T>();
1904 }
1905
1912 template <Aggregate T>
1913 void set(const T& value)
1914 {
1915 using namespace impl::reflection;
1916
1917 constexpr std::size_t N = fieldCountV<T>;
1918
1919 if (N != inDescriptors.size())
1920 {
1921 throw FbCppException("Struct field count (" + std::to_string(N) +
1922 ") does not match input parameter count (" + std::to_string(inDescriptors.size()) + ")");
1923 }
1924
1925 setStruct(value, std::make_index_sequence<N>{});
1926 }
1927
1935 template <TupleLike T>
1937 {
1938 assert(isValid());
1939 return outRow->get<T>();
1940 }
1941
1948 template <TupleLike T>
1949 void set(const T& value)
1950 {
1951 constexpr std::size_t N = std::tuple_size_v<T>;
1952
1953 if (N != inDescriptors.size())
1954 {
1955 throw FbCppException("Tuple element count (" + std::to_string(N) +
1956 ") does not match input parameter count (" + std::to_string(inDescriptors.size()) + ")");
1957 }
1958
1959 setTuple(value, std::make_index_sequence<N>{});
1960 }
1961
1970 template <VariantLike V>
1971 V get(unsigned index)
1972 {
1973 assert(isValid());
1974 return outRow->get<V>(index);
1975 }
1976
1983 template <VariantLike V>
1984 void set(unsigned index, const V& value)
1985 {
1986 using namespace impl::reflection;
1987
1988 static_assert(variantAlternativesSupportedV<V>,
1989 "Variant contains unsupported types. All variant alternatives must be types supported by fb-cpp "
1990 "(e.g., std::int32_t, std::string, Date, ScaledOpaqueInt128, etc.). Check VariantTypeTraits.h for the "
1991 "complete list of supported types.");
1992
1993 std::visit(
1994 [this, index](const auto& v)
1995 {
1996 using T = std::decay_t<decltype(v)>;
1997
1998 if constexpr (std::is_same_v<T, std::monostate>)
1999 setNull(index);
2000 else
2001 set(index, v);
2002 },
2003 value);
2004 }
2005
2006 private:
2010 const Descriptor& getInDescriptor(unsigned index)
2011 {
2012 if (index >= inDescriptors.size())
2013 throw std::out_of_range("index out of range");
2014
2015 return inDescriptors[index];
2016 }
2017
2021 template <typename T, std::size_t... Is>
2022 void setStruct(const T& value, std::index_sequence<Is...>)
2023 {
2024 using namespace impl::reflection;
2025
2026 const auto tuple = toTupleRef(value);
2027 (set(static_cast<unsigned>(Is), std::get<Is>(tuple)), ...);
2028 }
2029
2033 template <typename T, std::size_t... Is>
2034 void setTuple(const T& value, std::index_sequence<Is...>)
2035 {
2036 (set(static_cast<unsigned>(Is), std::get<Is>(value)), ...);
2037 }
2038
2042 template <typename T>
2043 void setNumber(unsigned index, DescriptorAdjustedType valueType, T value, int scale, const char* typeName)
2044 {
2045 assert(isValid());
2046
2047 const auto& descriptor = getInDescriptor(index);
2048 auto* const message = inMessage.data();
2049
2050 const auto descriptorData = &message[descriptor.offset];
2051 std::optional<int> descriptorScale{descriptor.scale};
2052
2053 Descriptor valueDescriptor;
2054 valueDescriptor.adjustedType = valueType;
2055 valueDescriptor.scale = scale;
2056
2057 const auto valueAddress = reinterpret_cast<const std::byte*>(&value);
2058
2059 switch (descriptor.adjustedType)
2060 {
2062 *reinterpret_cast<std::int16_t*>(descriptorData) =
2063 convertNumber<std::int16_t>(valueDescriptor, valueAddress, descriptorScale, "std::int16_t");
2064 break;
2065
2067 *reinterpret_cast<std::int32_t*>(descriptorData) =
2068 convertNumber<std::int32_t>(valueDescriptor, valueAddress, descriptorScale, "std::int32_t");
2069 break;
2070
2072 *reinterpret_cast<std::int64_t*>(descriptorData) =
2073 convertNumber<std::int64_t>(valueDescriptor, valueAddress, descriptorScale, "std::int64_t");
2074 break;
2075
2076#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
2078 {
2079 const auto boostInt128 =
2080 convertNumber<BoostInt128>(valueDescriptor, valueAddress, descriptorScale, "BoostInt128");
2081 *reinterpret_cast<OpaqueInt128*>(descriptorData) =
2082 numericConverter.boostInt128ToOpaqueInt128(boostInt128);
2083 break;
2084 }
2085#endif
2086
2088 *reinterpret_cast<float*>(descriptorData) =
2089 convertNumber<float>(valueDescriptor, valueAddress, descriptorScale, "float");
2090 break;
2091
2093 *reinterpret_cast<double*>(descriptorData) =
2094 convertNumber<double>(valueDescriptor, valueAddress, descriptorScale, "double");
2095 break;
2096
2097#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
2099 {
2100 const auto boostDecFloat16 = convertNumber<BoostDecFloat16>(
2101 valueDescriptor, valueAddress, descriptorScale, "BoostDecFloat16");
2102 *reinterpret_cast<OpaqueDecFloat16*>(descriptorData) =
2103 numericConverter.boostDecFloat16ToOpaqueDecFloat16(&statusWrapper, boostDecFloat16);
2104 break;
2105 }
2106
2108 {
2109 const auto boostDecFloat34 = convertNumber<BoostDecFloat34>(
2110 valueDescriptor, valueAddress, descriptorScale, "BoostDecFloat34");
2111 *reinterpret_cast<OpaqueDecFloat34*>(descriptorData) =
2112 numericConverter.boostDecFloat34ToOpaqueDecFloat34(&statusWrapper, boostDecFloat34);
2113 break;
2114 }
2115#endif
2116
2117 default:
2118 throwInvalidType(typeName, descriptor.adjustedType);
2119 }
2120
2121 *reinterpret_cast<std::int16_t*>(&message[descriptor.nullOffset]) = FB_FALSE;
2122 }
2123
2124 [[noreturn]] static void throwInvalidType(const char* actualType, DescriptorAdjustedType descriptorType)
2125 {
2126 throw FbCppException("Invalid type: actual type " + std::string(actualType) + ", descriptor type " +
2127 std::to_string(static_cast<unsigned>(descriptorType)));
2128 }
2129
2130 template <typename T>
2131 T convertNumber(
2132 const Descriptor& descriptor, const std::byte* data, std::optional<int>& toScale, const char* toTypeName)
2133 {
2134 if (!toScale.has_value())
2135 {
2136 switch (descriptor.adjustedType)
2137 {
2142 throwInvalidType(toTypeName, descriptor.adjustedType);
2143
2144 default:
2145 break;
2146 }
2147
2148 toScale = descriptor.scale;
2149 }
2150
2151 switch (descriptor.adjustedType)
2152 {
2154 return numericConverter.numberToNumber<T>(
2155 ScaledInt16{*reinterpret_cast<const std::int16_t*>(data), descriptor.scale}, toScale.value());
2156 break;
2157
2159 return numericConverter.numberToNumber<T>(
2160 ScaledInt32{*reinterpret_cast<const std::int32_t*>(data), descriptor.scale}, toScale.value());
2161
2163 return numericConverter.numberToNumber<T>(
2164 ScaledInt64{*reinterpret_cast<const std::int64_t*>(data), descriptor.scale}, toScale.value());
2165
2166#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
2168 return numericConverter.numberToNumber<T>(
2169 ScaledBoostInt128{*reinterpret_cast<const BoostInt128*>(data), descriptor.scale},
2170 toScale.value());
2171
2173 return numericConverter.numberToNumber<T>(
2174 *reinterpret_cast<const BoostDecFloat16*>(data), toScale.value());
2175
2177 return numericConverter.numberToNumber<T>(
2178 *reinterpret_cast<const BoostDecFloat34*>(data), toScale.value());
2179#endif
2180
2182 return numericConverter.numberToNumber<T>(*reinterpret_cast<const float*>(data), toScale.value());
2183 break;
2184
2186 return numericConverter.numberToNumber<T>(*reinterpret_cast<const double*>(data), toScale.value());
2187 break;
2188
2189 default:
2190 throwInvalidType(toTypeName, descriptor.adjustedType);
2191 }
2192 }
2193
2194 private:
2195 Attachment* attachment;
2196 impl::StatusWrapper statusWrapper;
2197 impl::CalendarConverter calendarConverter;
2198 impl::NumericConverter numericConverter;
2199 FbRef<fb::IStatement> statementHandle;
2200 FbRef<fb::IResultSet> resultSetHandle;
2201 FbRef<fb::IMessageMetadata> inMetadata;
2202 std::vector<Descriptor> inDescriptors;
2203 std::vector<std::byte> inMessage;
2204 FbRef<fb::IMessageMetadata> outMetadata;
2205 std::vector<Descriptor> outDescriptors;
2206 std::vector<std::byte> outMessage;
2207 std::unique_ptr<Row> outRow;
2208 StatementType type;
2209 unsigned cursorFlags = 0;
2210 };
2211
2216
2217 template <>
2218 inline std::optional<bool> Statement::get<std::optional<bool>>(unsigned index)
2219 {
2220 return getBool(index);
2221 }
2222
2223 template <>
2224 inline std::optional<BlobId> Statement::get<std::optional<BlobId>>(unsigned index)
2225 {
2226 return getBlobId(index);
2227 }
2228
2229 template <>
2230 inline std::optional<std::int16_t> Statement::get<std::optional<std::int16_t>>(unsigned index)
2231 {
2232 return getInt16(index);
2233 }
2234
2235 template <>
2236 inline std::optional<ScaledInt16> Statement::get<std::optional<ScaledInt16>>(unsigned index)
2237 {
2238 return getScaledInt16(index);
2239 }
2240
2241 template <>
2242 inline std::optional<std::int32_t> Statement::get<std::optional<std::int32_t>>(unsigned index)
2243 {
2244 return getInt32(index);
2245 }
2246
2247 template <>
2248 inline std::optional<ScaledInt32> Statement::get<std::optional<ScaledInt32>>(unsigned index)
2249 {
2250 return getScaledInt32(index);
2251 }
2252
2253 template <>
2254 inline std::optional<std::int64_t> Statement::get<std::optional<std::int64_t>>(unsigned index)
2255 {
2256 return getInt64(index);
2257 }
2258
2259 template <>
2260 inline std::optional<ScaledInt64> Statement::get<std::optional<ScaledInt64>>(unsigned index)
2261 {
2262 return getScaledInt64(index);
2263 }
2264
2265 template <>
2266 inline std::optional<ScaledOpaqueInt128> Statement::get<std::optional<ScaledOpaqueInt128>>(unsigned index)
2267 {
2268 return getScaledOpaqueInt128(index);
2269 }
2270
2271#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
2272 template <>
2273 inline std::optional<BoostInt128> Statement::get<std::optional<BoostInt128>>(unsigned index)
2274 {
2275 return getBoostInt128(index);
2276 }
2277
2278 template <>
2279 inline std::optional<ScaledBoostInt128> Statement::get<std::optional<ScaledBoostInt128>>(unsigned index)
2280 {
2281 return getScaledBoostInt128(index);
2282 }
2283#endif
2284
2285 template <>
2286 inline std::optional<float> Statement::get<std::optional<float>>(unsigned index)
2287 {
2288 return getFloat(index);
2289 }
2290
2291 template <>
2292 inline std::optional<double> Statement::get<std::optional<double>>(unsigned index)
2293 {
2294 return getDouble(index);
2295 }
2296
2297 template <>
2298 inline std::optional<OpaqueDecFloat16> Statement::get<std::optional<OpaqueDecFloat16>>(unsigned index)
2299 {
2300 return getOpaqueDecFloat16(index);
2301 }
2302
2303#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
2304 template <>
2305 inline std::optional<BoostDecFloat16> Statement::get<std::optional<BoostDecFloat16>>(unsigned index)
2306 {
2307 return getBoostDecFloat16(index);
2308 }
2309#endif
2310
2311 template <>
2312 inline std::optional<OpaqueDecFloat34> Statement::get<std::optional<OpaqueDecFloat34>>(unsigned index)
2313 {
2314 return getOpaqueDecFloat34(index);
2315 }
2316
2317#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
2318 template <>
2319 inline std::optional<BoostDecFloat34> Statement::get<std::optional<BoostDecFloat34>>(unsigned index)
2320 {
2321 return getBoostDecFloat34(index);
2322 }
2323#endif
2324
2325 template <>
2326 inline std::optional<Date> Statement::get<std::optional<Date>>(unsigned index)
2327 {
2328 return getDate(index);
2329 }
2330
2331 template <>
2332 inline std::optional<OpaqueDate> Statement::get<std::optional<OpaqueDate>>(unsigned index)
2333 {
2334 return getOpaqueDate(index);
2335 }
2336
2337 template <>
2338 inline std::optional<Time> Statement::get<std::optional<Time>>(unsigned index)
2339 {
2340 return getTime(index);
2341 }
2342
2343 template <>
2344 inline std::optional<OpaqueTime> Statement::get<std::optional<OpaqueTime>>(unsigned index)
2345 {
2346 return getOpaqueTime(index);
2347 }
2348
2349 template <>
2350 inline std::optional<OpaqueTimestamp> Statement::get<std::optional<OpaqueTimestamp>>(unsigned index)
2351 {
2352 return getOpaqueTimestamp(index);
2353 }
2354
2355 template <>
2356 inline std::optional<Timestamp> Statement::get<std::optional<Timestamp>>(unsigned index)
2357 {
2358 return getTimestamp(index);
2359 }
2360
2361 template <>
2362 inline std::optional<TimeTz> Statement::get<std::optional<TimeTz>>(unsigned index)
2363 {
2364 return getTimeTz(index);
2365 }
2366
2367 template <>
2368 inline std::optional<OpaqueTimeTz> Statement::get<std::optional<OpaqueTimeTz>>(unsigned index)
2369 {
2370 return getOpaqueTimeTz(index);
2371 }
2372
2373 template <>
2374 inline std::optional<TimestampTz> Statement::get<std::optional<TimestampTz>>(unsigned index)
2375 {
2376 return getTimestampTz(index);
2377 }
2378
2379 template <>
2380 inline std::optional<OpaqueTimestampTz> Statement::get<std::optional<OpaqueTimestampTz>>(unsigned index)
2381 {
2382 return getOpaqueTimestampTz(index);
2383 }
2384
2385 template <>
2386 inline std::optional<std::string> Statement::get<std::optional<std::string>>(unsigned index)
2387 {
2388 return getString(index);
2389 }
2390
2394} // namespace fbcpp
2395
2396
2397#endif // FBCPP_STATEMENT_H
Represents a connection to a Firebird database.
Definition Attachment.h:213
Client & getClient() noexcept
Returns the Client object reference used to create this Attachment object.
Definition Attachment.h:281
Represents a Firebird blob identifier.
Definition Blob.h:52
Exception thrown when a Firebird database operation fails.
Definition Exception.h:247
Base exception class for all fb-cpp exceptions.
Definition Exception.h:230
Reference-counted smart pointer for Firebird objects using addRef/release semantics.
Definition SmartPtrs.h:70
Represents options used when preparing a Statement.
Definition Statement.h:90
const std::optional< std::string > & getCursorName() const
Returns the cursor name to be set for the statement.
Definition Statement.h:133
unsigned getDialect() const
Returns the SQL dialect used when preparing the statement.
Definition Statement.h:171
StatementOptions & setDialect(unsigned value)
Sets the SQL dialect used when preparing the statement.
Definition Statement.h:181
StatementOptions & setCursorType(CursorType value)
Sets the cursor type used when opening a result set.
Definition Statement.h:162
StatementOptions & setPrefetchLegacyPlan(bool value)
Enables or disables prefetching of the legacy textual plan at prepare time.
Definition Statement.h:105
bool getPrefetchPlan() const
Reports whether the structured plan should be prefetched during prepare.
Definition Statement.h:114
StatementOptions & setCursorName(const std::string &value)
Sets the cursor name for the statement.
Definition Statement.h:143
StatementOptions & setPrefetchPlan(bool value)
Enables or disables prefetching of the structured plan at prepare time.
Definition Statement.h:124
bool getPrefetchLegacyPlan() const
Reports whether the legacy textual plan should be prefetched during prepare.
Definition Statement.h:95
CursorType getCursorType() const
Returns the cursor type to be used when opening a result set.
Definition Statement.h:152
Prepares, executes, and fetches SQL statements against a Firebird attachment.
Definition Statement.h:262
void set(unsigned index, OpaqueInt128 value)
Convenience overload that binds a Firebird 128-bit integer.
Definition Statement.h:1428
Statement & operator=(Statement &&o) noexcept
Transfers ownership of another prepared statement into this one.
Definition Statement.h:303
void setScaledInt16(unsigned index, std::optional< ScaledInt16 > optValue)
Binds a scaled 16-bit signed integer value or null.
Definition Statement.h:601
V get(unsigned index)
Retrieves a column value as a user-defined variant type.
Definition Statement.h:1971
bool fetchAbsolute(unsigned position)
Positions the cursor on the given absolute row number.
void setNull(unsigned index)
Marks the specified parameter as null.
Definition Statement.h:542
bool fetchRelative(int offset)
Moves the cursor by the requested relative offset.
void setScaledBoostInt128(unsigned index, std::optional< ScaledBoostInt128 > optValue)
Binds a scaled 128-bit integer value expressed with Boost.Multiprecision or null.
Definition Statement.h:719
std::optional< OpaqueTime > getOpaqueTime(unsigned index)
Reads a raw time-of-day column in Firebird's representation.
Definition Statement.h:1800
std::optional< OpaqueDecFloat34 > getOpaqueDecFloat34(unsigned index)
Reads a Firebird 34-digit decimal floating-point column.
Definition Statement.h:1753
std::vector< std::byte > & getOutputMessage() noexcept
Provides direct access to the raw output message buffer.
Definition Statement.h:418
void setDate(unsigned index, std::optional< Date > optValue)
Binds a date value or null.
Definition Statement.h:855
std::string getLegacyPlan()
Retrieves the textual legacy plan if the server produced one.
const std::vector< Descriptor > & getInputDescriptors() noexcept
Provides cached descriptors for each input column.
Definition Statement.h:444
void free()
Releases the prepared handle and any associated result set.
const std::vector< Descriptor > & getOutputDescriptors() noexcept
Provides cached descriptors for each output column.
Definition Statement.h:452
bool isValid() noexcept
Returns whether the Statement object is valid.
Definition Statement.h:368
StatementType getType() noexcept
Returns the type classification reported by the server.
Definition Statement.h:426
void set(unsigned index, BoostDecFloat16 value)
Convenience overload that binds a Boost 16-digit decimal floating-point value.
Definition Statement.h:1479
std::optional< TimeTz > getTimeTz(unsigned index)
Reads a time-of-day column with timezone.
Definition Statement.h:1827
void setTime(unsigned index, std::optional< Time > optValue)
Binds a time-of-day value without timezone or null.
Definition Statement.h:916
void set(unsigned index, std::string_view value)
Convenience overload that binds a textual value.
Definition Statement.h:1586
std::optional< BoostDecFloat34 > getBoostDecFloat34(unsigned index)
Reads a Boost-based 34-digit decimal floating-point column.
Definition Statement.h:1763
void setBlobId(unsigned index, std::optional< BlobId > optValue)
Binds a blob identifier to the specified parameter or null.
Definition Statement.h:1319
void setInt16(unsigned index, std::optional< std::int16_t > optValue)
Binds a 16-bit signed integer value or null.
Definition Statement.h:587
void setString(unsigned index, std::optional< std::string_view > optValue)
Binds a textual parameter or null, performing direct conversions where supported.
Definition Statement.h:1160
void set(unsigned index, std::int32_t value)
Convenience overload that binds a 32-bit signed integer.
Definition Statement.h:1396
std::optional< Time > getTime(unsigned index)
Reads a time-of-day column without timezone.
Definition Statement.h:1791
std::optional< Date > getDate(unsigned index)
Reads a date column.
Definition Statement.h:1773
FbRef< fb::IResultSet > getResultSetHandle() noexcept
Provides access to the underlying Firebird currently open result set handle, if any.
Definition Statement.h:386
bool isNull(unsigned index)
Reports whether the most recently fetched row has a null at the given column.
Definition Statement.h:1614
void set(unsigned index, double value)
Convenience overload that binds a double precision floating-point value.
Definition Statement.h:1462
void clearParameters()
Marks all bound parameters as null values.
Definition Statement.h:528
void set(unsigned index, ScaledInt64 value)
Convenience overload that binds a scaled 64-bit signed integer.
Definition Statement.h:1420
std::optional< OpaqueDate > getOpaqueDate(unsigned index)
Reads a raw date column in Firebird's representation.
Definition Statement.h:1782
T get()
Retrieves all output columns into a user-defined aggregate struct.
Definition Statement.h:1900
void setScaledInt32(unsigned index, std::optional< ScaledInt32 > optValue)
Binds a scaled 32-bit signed integer value or null.
Definition Statement.h:630
void set(unsigned index, std::int64_t value)
Convenience overload that binds a 64-bit signed integer.
Definition Statement.h:1412
void setTimestampTz(unsigned index, std::optional< TimestampTz > optValue)
Binds a timestamp value with timezone or null.
Definition Statement.h:1099
std::optional< std::int64_t > getInt64(unsigned index)
Reads a 64-bit signed integer column.
Definition Statement.h:1668
FbRef< fb::IStatement > getStatementHandle() noexcept
Provides direct access to the underlying Firebird statement handle.
Definition Statement.h:377
std::optional< ScaledInt32 > getScaledInt32(unsigned index)
Reads a scaled 32-bit signed integer column.
Definition Statement.h:1659
void set(unsigned index, OpaqueTimestampTz value)
Convenience overload that binds a Firebird timestamp with timezone value.
Definition Statement.h:1578
void setOpaqueTime(unsigned index, std::optional< OpaqueTime > optValue)
Binds a raw time-of-day value in Firebird's representation or null.
Definition Statement.h:947
std::optional< float > getFloat(unsigned index)
Reads a single precision floating-point column.
Definition Statement.h:1715
std::optional< double > getDouble(unsigned index)
Reads a double precision floating-point column.
Definition Statement.h:1724
std::optional< OpaqueTimestampTz > getOpaqueTimestampTz(unsigned index)
Reads a raw timestamp-with-time-zone column in Firebird's representation.
Definition Statement.h:1854
std::optional< ScaledInt16 > getScaledInt16(unsigned index)
Reads a scaled 16-bit signed integer column.
Definition Statement.h:1641
std::optional< BlobId > getBlobId(unsigned index)
Reads a blob identifier column.
Definition Statement.h:1863
Statement(Statement &&o) noexcept
Transfers ownership of an existing prepared statement.
Definition Statement.h:277
void setInt64(unsigned index, std::optional< std::int64_t > optValue)
Binds a 64-bit signed integer value or null.
Definition Statement.h:645
std::optional< ScaledOpaqueInt128 > getScaledOpaqueInt128(unsigned index)
Reads a Firebird scaled 128-bit integer column.
Definition Statement.h:1686
FbRef< fb::IMessageMetadata > getOutputMetadata() noexcept
Returns the metadata describing columns produced by the statement.
Definition Statement.h:410
void set(unsigned index, TimeTz value)
Convenience overload that binds a Firebird time with timezone value.
Definition Statement.h:1554
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:763
void setOpaqueInt128(unsigned index, std::optional< OpaqueInt128 > optValue)
Binds a raw 128-bit integer value in Firebird's representation or null.
Definition Statement.h:674
std::optional< OpaqueTimeTz > getOpaqueTimeTz(unsigned index)
Reads a raw time-of-day column with timezone in Firebird's representation.
Definition Statement.h:1836
void setBoostInt128(unsigned index, std::optional< BoostInt128 > optValue)
Binds a 128-bit integer value expressed with Boost.Multiprecision or null.
Definition Statement.h:705
void set(unsigned index, Date value)
Convenience overload that binds a Firebird date value.
Definition Statement.h:1506
void set(unsigned index, Timestamp value)
Convenience overload that binds a Firebird timestamp value.
Definition Statement.h:1538
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:1069
void setTimestamp(unsigned index, std::optional< Timestamp > optValue)
Binds a timestamp value without timezone or null.
Definition Statement.h:977
std::optional< std::string > getString(unsigned index)
Reads a textual column, applying number-to-string conversions when needed.
Definition Statement.h:1872
std::optional< std::int32_t > getInt32(unsigned index)
Reads a 32-bit signed integer column.
Definition Statement.h:1650
void set(unsigned index, OpaqueDecFloat16 value)
Convenience overload that binds a Firebird 16-digit decimal floating-point value.
Definition Statement.h:1470
void setOpaqueTimestampTz(unsigned index, std::optional< OpaqueTimestampTz > optValue)
Binds a raw timestamp value with timezone in Firebird's representation or null.
Definition Statement.h:1130
FbRef< fb::IMessageMetadata > getInputMetadata() noexcept
Returns the metadata describing prepared input parameters.
Definition Statement.h:394
~Statement() noexcept
Releases resources; ignores failures to keep destructor noexcept.
Definition Statement.h:335
void set(unsigned index, OpaqueTimeTz value)
Convenience overload that binds a Firebird time with timezone value.
Definition Statement.h:1562
void setBoostDecFloat16(unsigned index, std::optional< BoostDecFloat16 > optValue)
Binds a 16-digit decimal floating-point value using Boost.Multiprecision or null.
Definition Statement.h:794
std::optional< ScaledBoostInt128 > getScaledBoostInt128(unsigned index)
Reads a scaled Boost 128-bit integer column.
Definition Statement.h:1705
std::string getPlan()
Retrieves the structured textual plan if the server produced one.
void set(unsigned index, BlobId value)
Convenience overload that binds a blob identifier.
Definition Statement.h:1356
void set(unsigned index, BoostDecFloat34 value)
Convenience overload that binds a Boost 34-digit decimal floating-point value.
Definition Statement.h:1497
bool fetchNext()
Fetches the next row in the current result set.
void set(unsigned index, OpaqueDecFloat34 value)
Convenience overload that binds a Firebird 34-digit decimal floating-point value.
Definition Statement.h:1488
void set(unsigned index, Time value)
Convenience overload that binds a Firebird time value.
Definition Statement.h:1522
T get(unsigned index)
Retrieves a column using the most appropriate typed accessor specialization.
Definition Statement.h:1886
void set(unsigned index, ScaledInt16 value)
Convenience overload that binds a scaled 16-bit signed integer.
Definition Statement.h:1388
std::optional< BoostInt128 > getBoostInt128(unsigned index)
Reads a Boost 128-bit integer column.
Definition Statement.h:1696
std::optional< bool > getBool(unsigned index)
Reads a boolean column from the current row.
Definition Statement.h:1623
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:809
void set(unsigned index, OpaqueTimestamp value)
Convenience overload that binds a Firebird timestamp value.
Definition Statement.h:1546
void setInt32(unsigned index, std::optional< std::int32_t > optValue)
Binds a 32-bit signed integer value or null.
Definition Statement.h:616
void set(unsigned index, std::optional< BlobId > value)
Convenience overload that binds an optional blob identifier.
Definition Statement.h:1364
void setBool(unsigned index, std::optional< bool > optValue)
Binds a boolean parameter value or null.
Definition Statement.h:557
void set(unsigned index, const V &value)
Sets a parameter from a variant value.
Definition Statement.h:1984
void set(unsigned index, TimestampTz value)
Convenience overload that binds a Firebird timestamp with timezone value.
Definition Statement.h:1570
void setDouble(unsigned index, std::optional< double > optValue)
Binds a double precision floating-point value or null.
Definition Statement.h:749
void set(unsigned index, OpaqueDate value)
Convenience overload that binds a Firebird date value.
Definition Statement.h:1514
void set(unsigned index, std::int16_t value)
Convenience overload that binds a 16-bit signed integer.
Definition Statement.h:1380
void set(unsigned index, std::optional< T > value)
Convenience template that forwards optional values to specialized overloads.
Definition Statement.h:1595
std::optional< OpaqueTimestamp > getOpaqueTimestamp(unsigned index)
Reads a raw timestamp column in Firebird's representation.
Definition Statement.h:1818
void setScaledInt64(unsigned index, std::optional< ScaledInt64 > optValue)
Binds a scaled 64-bit signed integer value or null.
Definition Statement.h:659
Attachment & getAttachment() noexcept
Returns the Attachment object reference used to create this Statement.
Definition Statement.h:360
void set(unsigned index, std::nullopt_t)
Convenience overload that binds a null value.
Definition Statement.h:1348
void setFloat(unsigned index, std::optional< float > optValue)
Binds a single precision floating-point value or null.
Definition Statement.h:735
void setOpaqueDate(unsigned index, std::optional< OpaqueDate > optValue)
Binds a raw date value in Firebird's representation or null.
Definition Statement.h:886
bool fetchLast()
Positions the cursor on the last row.
bool execute(Transaction &transaction)
Executes a prepared statement using the supplied transaction.
void set(unsigned index, OpaqueTime value)
Convenience overload that binds a Firebird time value.
Definition Statement.h:1530
void set(unsigned index, ScaledInt32 value)
Convenience overload that binds a scaled 32-bit signed integer.
Definition Statement.h:1404
bool fetchPrior()
Fetches the previous row in the current result set.
std::optional< std::int16_t > getInt16(unsigned index)
Reads a 16-bit signed integer column.
Definition Statement.h:1632
void set(unsigned index, ScaledBoostInt128 value)
Convenience overload that binds a scaled Boost-provided 128-bit integer.
Definition Statement.h:1445
bool fetchFirst()
Positions the cursor on the first row.
std::optional< TimestampTz > getTimestampTz(unsigned index)
Reads a timestamp-with-time-zone column.
Definition Statement.h:1845
void set(unsigned index, BoostInt128 value)
Convenience overload that binds a Boost-provided 128-bit integer.
Definition Statement.h:1437
std::vector< std::byte > & getInputMessage() noexcept
Provides direct access to the raw input message buffer.
Definition Statement.h:402
std::optional< OpaqueDecFloat16 > getOpaqueDecFloat16(unsigned index)
Reads a Firebird 16-digit decimal floating-point column.
Definition Statement.h:1733
std::optional< Timestamp > getTimestamp(unsigned index)
Reads a timestamp column without timezone.
Definition Statement.h:1809
std::optional< BoostDecFloat16 > getBoostDecFloat16(unsigned index)
Reads a Boost-based 16-digit decimal floating-point column.
Definition Statement.h:1743
void setTimeTz(unsigned index, std::optional< TimeTz > optValue)
Binds a time-of-day value with timezone or null.
Definition Statement.h:1038
void setBoostDecFloat34(unsigned index, std::optional< BoostDecFloat34 > optValue)
Binds a 34-digit decimal floating-point value using Boost.Multiprecision or null.
Definition Statement.h:840
std::optional< ScaledInt64 > getScaledInt64(unsigned index)
Reads a scaled 64-bit signed integer column.
Definition Statement.h:1677
void set(unsigned index, bool value)
Convenience overload that binds a boolean value.
Definition Statement.h:1372
void setOpaqueTimestamp(unsigned index, std::optional< OpaqueTimestamp > optValue)
Binds a raw timestamp value in Firebird's representation or null.
Definition Statement.h:1008
void set(unsigned index, float value)
Convenience overload that binds a single precision floating-point value.
Definition Statement.h:1454
void set(const T &value)
Sets all input parameters from fields of a user-defined aggregate struct.
Definition Statement.h:1913
Represents a transaction in one or more Firebird databases.
fb-cpp namespace.
Definition Attachment.h:42
CursorType
Selects the cursor type for a SELECT statement.
Definition Statement.h:74
@ FORWARD_ONLY
Forward-only traversal (default, more efficient for streaming).
@ SCROLLABLE
Allows bidirectional traversal and absolute/relative positioning.
ScaledNumber< std::int64_t > ScaledInt64
Signed 64-bit scaled number.
Definition types.h:79
ScaledNumber< std::int32_t > ScaledInt32
Signed 32-bit scaled number.
Definition types.h:74
boost::multiprecision::number< boost::multiprecision::cpp_dec_float< 34 > > BoostDecFloat34
34-digit decimal floating point using Boost.Multiprecision.
Definition types.h:102
FB_DEC16 OpaqueDecFloat16
Opaque 16-digit decimal floating point exposed by the Firebird API.
Definition types.h:205
ScaledNumber< std::int16_t > ScaledInt16
Signed 16-bit scaled number.
Definition types.h:69
boost::multiprecision::number< boost::multiprecision::cpp_dec_float< 16 > > BoostDecFloat16
16-digit decimal floating point using Boost.Multiprecision.
Definition types.h:97
DescriptorAdjustedType
Descriptor adjusted type.
Definition Descriptor.h:147
@ BLOB
Binary large object.
@ TIME
Time of day without time zone.
@ DECFLOAT34
34-digit decimal floating point.
@ INT64
64-bit signed integer.
@ TIME_TZ
Time of day with time zone.
@ DECFLOAT16
16-digit decimal floating point.
@ INT16
16-bit signed integer.
@ STRING
String type (variable-length).
@ INT32
32-bit signed integer.
@ TIMESTAMP
Timestamp without time zone.
@ TIMESTAMP_TZ
Timestamp with time zone.
@ INT128
128-bit signed integer.
@ FLOAT
Single-precision floating point.
@ DOUBLE
Double-precision floating point.
StatementType
Distinguishes the semantic category of the prepared SQL statement.
Definition Statement.h:199
@ 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:200
std::chrono::year_month_day Date
Firebird SQL calendar date.
Definition types.h:108
FB_DEC34 OpaqueDecFloat34
Opaque 34-digit decimal floating point exposed by the Firebird API.
Definition types.h:210
boost::multiprecision::int128_t BoostInt128
128-bit integer using Boost.Multiprecision.
Definition types.h:85
ScaledNumber< BoostInt128 > ScaledBoostInt128
Scaled 128-bit integer backed by Boost.Multiprecision.
Definition types.h:90
std::chrono::hh_mm_ss< std::chrono::microseconds > Time
Firebird SQL time-of-day with microsecond resolution.
Definition types.h:113
Describes a parameter or column.
Definition Descriptor.h:248
Wrapper for Firebird date values.
Definition types.h:221
Wrapper for Firebird time-with-time-zone values.
Definition types.h:263
Wrapper for Firebird time values.
Definition types.h:234
Wrapper for Firebird timestamp-with-time-zone values.
Definition types.h:279
Wrapper for Firebird timestamp values.
Definition types.h:247
Represents a numeric value with an explicit decimal scale.
Definition types.h:52
T value
Unscaled numeric value.
Definition types.h:58
Local time bound to a time zone.
Definition types.h:162
Timestamp bound to a time zone.
Definition types.h:183
Combined date and time with microsecond precision.
Definition types.h:119