25#ifndef FBCPP_STATEMENT_H
26#define FBCPP_STATEMENT_H
29#include "fb-cpp-export.h"
35#include "StatementOptions.h"
36#include "NumericConverter.h"
37#include "CalendarConverter.h"
38#include "Descriptor.h"
41#include "StructBinding.h"
42#include "VariantTypeTraits.h"
59#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
60#include <boost/multiprecision/cpp_int.hpp>
61#include <boost/multiprecision/cpp_dec_float.hpp>
64#if FB_CPP_USE_BOOST_DECIMAL != 0
65#include <boost/decimal.hpp>
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,
120 COMMIT = isc_info_sql_stmt_commit,
124 ROLLBACK = isc_info_sql_stmt_rollback,
209 return statementHandle !=
nullptr;
218 return statementHandle;
227 return resultSetHandle;
285 return inDescriptors;
293 return outDescriptors;
308 std::string getLegacyPlan();
313 std::string getPlan();
349 bool fetchAbsolute(
unsigned position);
354 bool fetchRelative(
int offset);
371 const auto message = inMessage.data();
373 for (
const auto& descriptor : inDescriptors)
374 *
reinterpret_cast<std::int16_t*
>(&message[descriptor.nullOffset]) = FB_TRUE;
385 const auto& descriptor = getInDescriptor(index);
386 const auto message = inMessage.data();
388 *
reinterpret_cast<std::int16_t*
>(&message[descriptor.nullOffset]) = FB_TRUE;
396 void setBool(
unsigned index, std::optional<bool> optValue)
398 if (!optValue.has_value())
406 const auto& value = optValue.value();
407 const auto& descriptor = getInDescriptor(index);
408 const auto message = inMessage.data();
410 switch (descriptor.adjustedType)
412 case DescriptorAdjustedType::BOOLEAN:
413 message[descriptor.offset] = value ? std::byte{1} : std::byte{0};
417 throwInvalidType(
"bool", descriptor.adjustedType);
420 *
reinterpret_cast<std::int16_t*
>(&message[descriptor.nullOffset]) = FB_FALSE;
426 void setInt16(
unsigned index, std::optional<std::int16_t> optValue)
428 if (!optValue.has_value())
434 setNumber(index, DescriptorAdjustedType::INT16, optValue.value(), 0,
"std::int16_t");
442 if (!optValue.has_value())
448 const auto& value = optValue.value();
449 setNumber(index, DescriptorAdjustedType::INT16, value.value, value.scale,
"ScaledInt16");
455 void setInt32(
unsigned index, std::optional<std::int32_t> optValue)
457 if (!optValue.has_value())
463 setNumber(index, DescriptorAdjustedType::INT32, optValue.value(), 0,
"std::int32_t");
471 if (!optValue.has_value())
477 const auto& value = optValue.value();
478 setNumber(index, DescriptorAdjustedType::INT32, value.value, value.scale,
"ScaledInt32");
484 void setInt64(
unsigned index, std::optional<std::int64_t> optValue)
486 if (!optValue.has_value())
492 setNumber(index, DescriptorAdjustedType::INT64, optValue.value(), 0,
"std::int64_t");
500 if (!optValue.has_value())
506 const auto& value = optValue.value();
507 setNumber(index, DescriptorAdjustedType::INT64, value.value, value.scale,
"ScaledInt64");
515 if (!optValue.has_value())
523 const auto& value = optValue.value();
524 const auto& descriptor = getInDescriptor(index);
525 const auto message = inMessage.data();
527 switch (descriptor.adjustedType)
529 case DescriptorAdjustedType::INT128:
530 *
reinterpret_cast<OpaqueInt128*
>(&message[descriptor.offset]) = value;
534 throwInvalidType(
"OpaqueInt128", descriptor.adjustedType);
537 *
reinterpret_cast<std::int16_t*
>(&message[descriptor.nullOffset]) = FB_FALSE;
545 if (!optValue.has_value())
553 const auto& value = optValue.value();
554 const auto& descriptor = getInDescriptor(index);
555 auto*
const message = inMessage.data();
557 switch (descriptor.adjustedType)
559 case DescriptorAdjustedType::INT128:
560 if (value.scale == descriptor.scale)
561 *
reinterpret_cast<OpaqueInt128*
>(&message[descriptor.offset]) = value.value;
564 const auto valueString =
565 numericConverter.opaqueInt128ToString(&statusWrapper, value.value, value.scale);
567 .getInt128Util(&statusWrapper)
568 ->fromString(&statusWrapper, descriptor.scale, valueString.c_str(),
569 reinterpret_cast<OpaqueInt128*
>(&message[descriptor.offset]));
574 throwInvalidType(
"ScaledOpaqueInt128", descriptor.adjustedType);
577 *
reinterpret_cast<std::int16_t*
>(&message[descriptor.nullOffset]) = FB_FALSE;
580#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
586 if (!optValue.has_value())
592 setNumber(index, DescriptorAdjustedType::INT128, optValue.value(), 0,
"BoostInt128");
600 if (!optValue.has_value())
606 const auto& value = optValue.value();
607 setNumber(index, DescriptorAdjustedType::INT128, value.value, value.scale,
"ScaledBoostInt128");
614 void setFloat(
unsigned index, std::optional<float> optValue)
616 if (!optValue.has_value())
622 setNumber(index, DescriptorAdjustedType::FLOAT, optValue.value(), 0,
"float");
628 void setDouble(
unsigned index, std::optional<double> optValue)
630 if (!optValue.has_value())
636 setNumber(index, DescriptorAdjustedType::DOUBLE, optValue.value(), 0,
"double");
644 if (!optValue.has_value())
652 const auto& value = optValue.value();
653 const auto& descriptor = getInDescriptor(index);
654 const auto message = inMessage.data();
656 switch (descriptor.adjustedType)
658 case DescriptorAdjustedType::DECFLOAT16:
663 throwInvalidType(
"OpaqueDecFloat16", descriptor.adjustedType);
666 *
reinterpret_cast<std::int16_t*
>(&message[descriptor.nullOffset]) = FB_FALSE;
669#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
675 if (!optValue.has_value())
681 setNumber(index, DescriptorAdjustedType::DECFLOAT16, optValue.value(), 0,
"BoostDecFloat16");
685#if FB_CPP_USE_BOOST_DECIMAL != 0
691 if (!optValue.has_value())
697 setNumber(index, DescriptorAdjustedType::DECFLOAT16, optValue.value(), 0,
"BoostDecimal32");
705 if (!optValue.has_value())
711 setNumber(index, DescriptorAdjustedType::DECFLOAT16, optValue.value(), 0,
"BoostDecimal64");
720 if (!optValue.has_value())
728 const auto& value = optValue.value();
729 const auto& descriptor = getInDescriptor(index);
730 const auto message = inMessage.data();
732 switch (descriptor.adjustedType)
734 case DescriptorAdjustedType::DECFLOAT34:
739 throwInvalidType(
"OpaqueDecFloat34", descriptor.adjustedType);
742 *
reinterpret_cast<std::int16_t*
>(&message[descriptor.nullOffset]) = FB_FALSE;
745#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
751 if (!optValue.has_value())
757 setNumber(index, DescriptorAdjustedType::DECFLOAT34, optValue.value(), 0,
"BoostDecFloat34");
761#if FB_CPP_USE_BOOST_DECIMAL != 0
767 if (!optValue.has_value())
773 setNumber(index, DescriptorAdjustedType::DECFLOAT34, optValue.value(), 0,
"BoostDecimal128");
780 void setDate(
unsigned index, std::optional<Date> optValue)
782 if (!optValue.has_value())
790 const auto& value = optValue.value();
791 const auto& descriptor = getInDescriptor(index);
792 const auto message = inMessage.data();
794 switch (descriptor.adjustedType)
796 case DescriptorAdjustedType::DATE:
797 *
reinterpret_cast<OpaqueDate*
>(&message[descriptor.offset]) =
798 calendarConverter.dateToOpaqueDate(value);
802 throwInvalidType(
"Date", descriptor.adjustedType);
805 *
reinterpret_cast<std::int16_t*
>(&message[descriptor.nullOffset]) = FB_FALSE;
813 if (!optValue.has_value())
821 const auto& value = optValue.value();
822 const auto& descriptor = getInDescriptor(index);
823 const auto message = inMessage.data();
825 switch (descriptor.adjustedType)
827 case DescriptorAdjustedType::DATE:
828 *
reinterpret_cast<OpaqueDate*
>(&message[descriptor.offset]) = value;
832 throwInvalidType(
"OpaqueDate", descriptor.adjustedType);
835 *
reinterpret_cast<std::int16_t*
>(&message[descriptor.nullOffset]) = FB_FALSE;
841 void setTime(
unsigned index, std::optional<Time> optValue)
843 if (!optValue.has_value())
851 const auto& value = optValue.value();
852 const auto& descriptor = getInDescriptor(index);
853 const auto message = inMessage.data();
855 switch (descriptor.adjustedType)
857 case DescriptorAdjustedType::TIME:
858 *
reinterpret_cast<OpaqueTime*
>(&message[descriptor.offset]) =
859 calendarConverter.timeToOpaqueTime(value);
863 throwInvalidType(
"Time", descriptor.adjustedType);
866 *
reinterpret_cast<std::int16_t*
>(&message[descriptor.nullOffset]) = FB_FALSE;
874 if (!optValue.has_value())
882 const auto& value = optValue.value();
883 const auto& descriptor = getInDescriptor(index);
884 const auto message = inMessage.data();
886 switch (descriptor.adjustedType)
888 case DescriptorAdjustedType::TIME:
889 *
reinterpret_cast<OpaqueTime*
>(&message[descriptor.offset]) = value;
893 throwInvalidType(
"OpaqueTime", descriptor.adjustedType);
896 *
reinterpret_cast<std::int16_t*
>(&message[descriptor.nullOffset]) = FB_FALSE;
904 if (!optValue.has_value())
912 const auto& value = optValue.value();
913 const auto& descriptor = getInDescriptor(index);
914 const auto message = inMessage.data();
916 switch (descriptor.adjustedType)
918 case DescriptorAdjustedType::TIMESTAMP:
920 calendarConverter.timestampToOpaqueTimestamp(value);
924 throwInvalidType(
"Timestamp", descriptor.adjustedType);
927 *
reinterpret_cast<std::int16_t*
>(&message[descriptor.nullOffset]) = FB_FALSE;
935 if (!optValue.has_value())
943 const auto& value = optValue.value();
944 const auto& descriptor = getInDescriptor(index);
945 const auto message = inMessage.data();
947 switch (descriptor.adjustedType)
949 case DescriptorAdjustedType::TIMESTAMP:
950 *
reinterpret_cast<OpaqueTimestamp*
>(&message[descriptor.offset]) = value;
954 throwInvalidType(
"OpaqueTimestamp", descriptor.adjustedType);
957 *
reinterpret_cast<std::int16_t*
>(&message[descriptor.nullOffset]) = FB_FALSE;
963 void setTimeTz(
unsigned index, std::optional<TimeTz> optValue)
965 if (!optValue.has_value())
973 const auto& value = optValue.value();
974 const auto& descriptor = getInDescriptor(index);
975 auto*
const message = inMessage.data();
977 switch (descriptor.adjustedType)
979 case DescriptorAdjustedType::TIME_TZ:
980 *
reinterpret_cast<OpaqueTimeTz*
>(&message[descriptor.offset]) =
981 calendarConverter.timeTzToOpaqueTimeTz(&statusWrapper, value);
985 throwInvalidType(
"TimeTz", descriptor.adjustedType);
988 *
reinterpret_cast<std::int16_t*
>(&message[descriptor.nullOffset]) = FB_FALSE;
996 if (!optValue.has_value())
1004 const auto& value = optValue.value();
1005 const auto& descriptor = getInDescriptor(index);
1006 auto*
const message = inMessage.data();
1008 switch (descriptor.adjustedType)
1010 case DescriptorAdjustedType::TIME_TZ:
1011 *
reinterpret_cast<OpaqueTimeTz*
>(&message[descriptor.offset]) = value;
1015 throwInvalidType(
"OpaqueTimeTz", descriptor.adjustedType);
1018 *
reinterpret_cast<std::int16_t*
>(&message[descriptor.nullOffset]) = FB_FALSE;
1026 if (!optValue.has_value())
1034 const auto& value = optValue.value();
1035 const auto& descriptor = getInDescriptor(index);
1036 auto*
const message = inMessage.data();
1038 switch (descriptor.adjustedType)
1040 case DescriptorAdjustedType::TIMESTAMP_TZ:
1042 calendarConverter.timestampTzToOpaqueTimestampTz(&statusWrapper, value);
1046 throwInvalidType(
"TimestampTz", descriptor.adjustedType);
1049 *
reinterpret_cast<std::int16_t*
>(&message[descriptor.nullOffset]) = FB_FALSE;
1057 if (!optValue.has_value())
1065 const auto& value = optValue.value();
1066 const auto& descriptor = getInDescriptor(index);
1067 auto*
const message = inMessage.data();
1069 switch (descriptor.adjustedType)
1071 case DescriptorAdjustedType::TIMESTAMP_TZ:
1076 throwInvalidType(
"OpaqueTimestampTz", descriptor.adjustedType);
1079 *
reinterpret_cast<std::int16_t*
>(&message[descriptor.nullOffset]) = FB_FALSE;
1085 void setString(
unsigned index, std::optional<std::string_view> optValue)
1087 if (!optValue.has_value())
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];
1101 switch (descriptor.adjustedType)
1103 case DescriptorAdjustedType::BOOLEAN:
1104 message[descriptor.offset] = numericConverter.stringToBoolean(value);
1107 case DescriptorAdjustedType::INT16:
1108 case DescriptorAdjustedType::INT32:
1109 case DescriptorAdjustedType::INT64:
1111 std::string strValue(value);
1114 if (
const auto dotPos = strValue.find_last_of(
'.'); dotPos != std::string_view::npos)
1116 for (
auto pos = dotPos + 1; pos < strValue.size(); ++pos)
1118 const char c = value[pos];
1120 if (c <
'0' || c >
'9')
1126 strValue.erase(dotPos, 1);
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);
1137 if (scale != descriptor.scale)
1140 numericConverter.numberToNumber<std::int64_t>(scaledValue, descriptor.scale);
1141 scaledValue.scale = descriptor.scale;
1144 setScaledInt64(index, scaledValue);
1148 case DescriptorAdjustedType::INT128:
1150 std::string strValue(value);
1151 client.getInt128Util(&statusWrapper)
1153 &statusWrapper, descriptor.scale, strValue.c_str(),
reinterpret_cast<OpaqueInt128*
>(data));
1157 case DescriptorAdjustedType::FLOAT:
1158 case DescriptorAdjustedType::DOUBLE:
1161#if defined(__APPLE__)
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));
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});
1173 setDouble(index, doubleValue);
1177 case DescriptorAdjustedType::DATE:
1178 *
reinterpret_cast<OpaqueDate*
>(data) = calendarConverter.stringToOpaqueDate(value);
1181 case DescriptorAdjustedType::TIME:
1182 *
reinterpret_cast<OpaqueTime*
>(data) = calendarConverter.stringToOpaqueTime(value);
1185 case DescriptorAdjustedType::TIMESTAMP:
1186 *
reinterpret_cast<OpaqueTimestamp*
>(data) = calendarConverter.stringToOpaqueTimestamp(value);
1189 case DescriptorAdjustedType::TIME_TZ:
1191 calendarConverter.stringToOpaqueTimeTz(&statusWrapper, value);
1194 case DescriptorAdjustedType::TIMESTAMP_TZ:
1196 calendarConverter.stringToOpaqueTimestampTz(&statusWrapper, value);
1199 case DescriptorAdjustedType::DECFLOAT16:
1201 std::string strValue{value};
1202 client.getDecFloat16Util(&statusWrapper)
1203 ->fromString(&statusWrapper, strValue.c_str(),
reinterpret_cast<OpaqueDecFloat16*
>(data));
1207 case DescriptorAdjustedType::DECFLOAT34:
1209 std::string strValue{value};
1210 client.getDecFloat34Util(&statusWrapper)
1211 ->fromString(&statusWrapper, strValue.c_str(),
reinterpret_cast<OpaqueDecFloat34*
>(data));
1215 case DescriptorAdjustedType::STRING:
1216 if (value.length() > descriptor.length)
1218 static constexpr std::intptr_t STATUS_STRING_TRUNCATION[] = {
1220 isc_string_truncation,
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)]));
1233 throwInvalidType(
"std::string_view", descriptor.adjustedType);
1236 *
reinterpret_cast<std::int16_t*
>(&message[descriptor.nullOffset]) = FB_FALSE;
1242 void setBlobId(
unsigned index, std::optional<BlobId> optValue)
1244 if (!optValue.has_value())
1252 const auto& value = optValue.value();
1253 const auto& descriptor = getInDescriptor(index);
1254 auto*
const message = inMessage.data();
1256 switch (descriptor.adjustedType)
1258 case DescriptorAdjustedType::BLOB:
1259 *
reinterpret_cast<ISC_QUAD*
>(&message[descriptor.offset]) = value.id;
1263 throwInvalidType(
"BlobId", descriptor.adjustedType);
1266 *
reinterpret_cast<std::int16_t*
>(&message[descriptor.nullOffset]) = FB_FALSE;
1271 void set(
unsigned index, std::nullopt_t)
1281 setBlobId(index, value);
1287 void set(
unsigned index, std::optional<BlobId> value)
1289 setBlobId(index, value);
1295 void set(
unsigned index,
bool value)
1297 setBool(index, value);
1303 void set(
unsigned index, std::int16_t value)
1305 setInt16(index, value);
1313 setScaledInt16(index, value);
1319 void set(
unsigned index, std::int32_t value)
1321 setInt32(index, value);
1329 setScaledInt32(index, value);
1335 void set(
unsigned index, std::int64_t value)
1337 setInt64(index, value);
1345 setScaledInt64(index, value);
1353 setOpaqueInt128(index, value);
1361 setScaledOpaqueInt128(index, value);
1364#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
1370 setBoostInt128(index, value);
1378 setScaledBoostInt128(index, value);
1385 void set(
unsigned index,
float value)
1387 setFloat(index, value);
1393 void set(
unsigned index,
double value)
1395 setDouble(index, value);
1403 setOpaqueDecFloat16(index, value);
1406#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
1412 setBoostDecFloat16(index, value);
1416#if FB_CPP_USE_BOOST_DECIMAL != 0
1422 setBoostDecimal32(index, value);
1430 setBoostDecimal64(index, value);
1439 setOpaqueDecFloat34(index, value);
1442#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
1448 setBoostDecFloat34(index, value);
1452#if FB_CPP_USE_BOOST_DECIMAL != 0
1458 setBoostDecimal128(index, value);
1467 setDate(index, value);
1475 setOpaqueDate(index, value);
1483 setTime(index, value);
1491 setOpaqueTime(index, value);
1499 setTimestamp(index, value);
1507 setOpaqueTimestamp(index, value);
1515 setTimeTz(index, value);
1523 setOpaqueTimeTz(index, value);
1531 setTimestampTz(index, value);
1539 setOpaqueTimestampTz(index, value);
1545 void set(
unsigned index, std::string_view value)
1547 setString(index, value);
1553 template <
typename T>
1554 void set(
unsigned index, std::optional<T> value)
1556 if (value.has_value())
1557 set(index, value.value());
1576 return outRow->isNull(index);
1585 return outRow->getBool(index);
1594 return outRow->getInt16(index);
1603 return outRow->getScaledInt16(index);
1612 return outRow->getInt32(index);
1621 return outRow->getScaledInt32(index);
1630 return outRow->getInt64(index);
1639 return outRow->getScaledInt64(index);
1648 return outRow->getScaledOpaqueInt128(index);
1651#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
1658 return outRow->getBoostInt128(index);
1667 return outRow->getScaledBoostInt128(index);
1677 return outRow->getFloat(index);
1686 return outRow->getDouble(index);
1695 return outRow->getOpaqueDecFloat16(index);
1698#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
1705 return outRow->getBoostDecFloat16(index);
1709#if FB_CPP_USE_BOOST_DECIMAL != 0
1716 return outRow->getBoostDecimal32(index);
1725 return outRow->getBoostDecimal64(index);
1735 return outRow->getOpaqueDecFloat34(index);
1738#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
1745 return outRow->getBoostDecFloat34(index);
1749#if FB_CPP_USE_BOOST_DECIMAL != 0
1756 return outRow->getBoostDecimal128(index);
1766 return outRow->getDate(index);
1775 return outRow->getOpaqueDate(index);
1784 return outRow->getTime(index);
1793 return outRow->getOpaqueTime(index);
1802 return outRow->getTimestamp(index);
1811 return outRow->getOpaqueTimestamp(index);
1820 return outRow->getTimeTz(index);
1829 return outRow->getOpaqueTimeTz(index);
1838 return outRow->getTimestampTz(index);
1847 return outRow->getOpaqueTimestampTz(index);
1856 return outRow->getBlobId(index);
1865 return outRow->getString(index);
1875 template <
typename T>
1879 return outRow->get<T>(index);
1889 template <Aggregate T>
1893 return outRow->get<T>();
1902 template <Aggregate T>
1905 using namespace impl::reflection;
1907 constexpr std::size_t N = fieldCountV<T>;
1909 if (N != inDescriptors.size())
1911 throw FbCppException(
"Struct field count (" + std::to_string(N) +
1912 ") does not match input parameter count (" + std::to_string(inDescriptors.size()) +
")");
1915 setStruct(value, std::make_index_sequence<N>{});
1925 template <TupleLike T>
1929 return outRow->get<T>();
1938 template <TupleLike T>
1941 constexpr std::size_t N = std::tuple_size_v<T>;
1943 if (N != inDescriptors.size())
1945 throw FbCppException(
"Tuple element count (" + std::to_string(N) +
1946 ") does not match input parameter count (" + std::to_string(inDescriptors.size()) +
")");
1949 setTuple(value, std::make_index_sequence<N>{});
1960 template <VariantLike V>
1964 return outRow->get<V>(index);
1973 template <VariantLike V>
1974 void set(
unsigned index,
const V& value)
1976 using namespace impl::reflection;
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.");
1984 [
this, index](
const auto& v)
1986 using T = std::decay_t<
decltype(v)>;
1988 if constexpr (std::is_same_v<T, std::monostate>)
2000 const Descriptor& getInDescriptor(
unsigned index)
2002 if (index >= inDescriptors.size())
2003 throw std::out_of_range(
"index out of range");
2005 return inDescriptors[index];
2011 template <
typename T, std::size_t... Is>
2012 void setStruct(
const T& value, std::index_sequence<Is...>)
2014 using namespace impl::reflection;
2016 const auto tuple = toTupleRef(value);
2017 (set(
static_cast<unsigned>(Is), std::get<Is>(tuple)), ...);
2023 template <
typename T, std::size_t... Is>
2024 void setTuple(
const T& value, std::index_sequence<Is...>)
2026 (set(
static_cast<unsigned>(Is), std::get<Is>(value)), ...);
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)
2033 const auto& descriptor = getInDescriptor(index);
2034 auto*
const message = inMessage.data();
2035 const auto descriptorData = &message[descriptor.offset];
2037 switch (descriptor.adjustedType)
2039 case DescriptorAdjustedType::INT16:
2040 *
reinterpret_cast<std::int16_t*
>(descriptorData) =
2041 numericConverter.numberToNumber<std::int16_t>(value, descriptorScale.value());
2044 case DescriptorAdjustedType::INT32:
2045 *
reinterpret_cast<std::int32_t*
>(descriptorData) =
2046 numericConverter.numberToNumber<std::int32_t>(value, descriptorScale.value());
2049 case DescriptorAdjustedType::INT64:
2050 *
reinterpret_cast<std::int64_t*
>(descriptorData) =
2051 numericConverter.numberToNumber<std::int64_t>(value, descriptorScale.value());
2054#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
2055 case DescriptorAdjustedType::INT128:
2057 const auto int128Value =
2058 numericConverter.numberToNumber<
BoostInt128>(value, descriptorScale.value());
2060 numericConverter.boostInt128ToOpaqueInt128(&statusWrapper, int128Value);
2065 case DescriptorAdjustedType::FLOAT:
2066 *
reinterpret_cast<float*
>(descriptorData) = numericConverter.numberToNumber<
float>(value);
2069 case DescriptorAdjustedType::DOUBLE:
2070 *
reinterpret_cast<double*
>(descriptorData) = numericConverter.numberToNumber<
double>(value);
2073 case DescriptorAdjustedType::DECFLOAT16:
2075 const auto decimalValue = numericConverter.numberToNumber<
BoostDecimal64>(value);
2077 numericConverter.boostDecimal64ToOpaqueDecFloat16(&statusWrapper, decimalValue);
2081 case DescriptorAdjustedType::DECFLOAT34:
2083 const auto decimalValue = numericConverter.numberToNumber<
BoostDecimal128>(value);
2085 numericConverter.boostDecimal128ToOpaqueDecFloat34(&statusWrapper, decimalValue);
2090 throwInvalidType(typeName, descriptor.adjustedType);
2098 template <
typename T>
2099 void setNumber(
unsigned index, DescriptorAdjustedType valueType, T value,
int scale,
const char* typeName)
2103 const auto& descriptor = getInDescriptor(index);
2104 auto*
const message = inMessage.data();
2106 const auto descriptorData = &message[descriptor.offset];
2107 std::optional<int> descriptorScale{descriptor.scale};
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>)
2113 setDecimalNumber(index, value, descriptorScale, typeName);
2114 *
reinterpret_cast<std::int16_t*
>(&message[descriptor.nullOffset]) = FB_FALSE;
2119 Descriptor valueDescriptor;
2120 valueDescriptor.adjustedType = valueType;
2121 valueDescriptor.scale = scale;
2123 const auto valueAddress =
reinterpret_cast<const std::byte*
>(&value);
2125 switch (descriptor.adjustedType)
2127 case DescriptorAdjustedType::INT16:
2128 *
reinterpret_cast<std::int16_t*
>(descriptorData) =
2129 convertNumber<std::int16_t>(valueDescriptor, valueAddress, descriptorScale,
"std::int16_t");
2132 case DescriptorAdjustedType::INT32:
2133 *
reinterpret_cast<std::int32_t*
>(descriptorData) =
2134 convertNumber<std::int32_t>(valueDescriptor, valueAddress, descriptorScale,
"std::int32_t");
2137 case DescriptorAdjustedType::INT64:
2138 *
reinterpret_cast<std::int64_t*
>(descriptorData) =
2139 convertNumber<std::int64_t>(valueDescriptor, valueAddress, descriptorScale,
"std::int64_t");
2142#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
2143 case DescriptorAdjustedType::INT128:
2145 const auto boostInt128 =
2146 convertNumber<BoostInt128>(valueDescriptor, valueAddress, descriptorScale,
"BoostInt128");
2148 numericConverter.boostInt128ToOpaqueInt128(&statusWrapper, boostInt128);
2153 case DescriptorAdjustedType::FLOAT:
2154 *
reinterpret_cast<float*
>(descriptorData) =
2155 convertNumber<float>(valueDescriptor, valueAddress, descriptorScale,
"float");
2158 case DescriptorAdjustedType::DOUBLE:
2159 *
reinterpret_cast<double*
>(descriptorData) =
2160 convertNumber<double>(valueDescriptor, valueAddress, descriptorScale,
"double");
2163#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
2164 case DescriptorAdjustedType::DECFLOAT16:
2166 const auto boostDecFloat16 = convertNumber<BoostDecFloat16>(
2167 valueDescriptor, valueAddress, descriptorScale,
"BoostDecFloat16");
2169 numericConverter.boostDecFloat16ToOpaqueDecFloat16(&statusWrapper, boostDecFloat16);
2173 case DescriptorAdjustedType::DECFLOAT34:
2175 const auto boostDecFloat34 = convertNumber<BoostDecFloat34>(
2176 valueDescriptor, valueAddress, descriptorScale,
"BoostDecFloat34");
2178 numericConverter.boostDecFloat34ToOpaqueDecFloat34(&statusWrapper, boostDecFloat34);
2184 throwInvalidType(typeName, descriptor.adjustedType);
2187 *
reinterpret_cast<std::int16_t*
>(&message[descriptor.nullOffset]) = FB_FALSE;
2190 [[noreturn]]
static void throwInvalidType(
const char* actualType, DescriptorAdjustedType descriptorType)
2192 throw FbCppException(
"Invalid type: actual type " + std::string(actualType) +
", descriptor type " +
2193 std::to_string(
static_cast<unsigned>(descriptorType)));
2196 template <
typename T>
2198 const Descriptor& descriptor,
const std::byte* data, std::optional<int>& toScale,
const char* toTypeName)
2200 if (!toScale.has_value())
2202 switch (descriptor.adjustedType)
2204 case DescriptorAdjustedType::DECFLOAT16:
2205 case DescriptorAdjustedType::DECFLOAT34:
2206 case DescriptorAdjustedType::FLOAT:
2207 case DescriptorAdjustedType::DOUBLE:
2208 throwInvalidType(toTypeName, descriptor.adjustedType);
2214 toScale = descriptor.scale;
2217 switch (descriptor.adjustedType)
2219 case DescriptorAdjustedType::INT16:
2220 return numericConverter.numberToNumber<T>(
2221 ScaledInt16{*
reinterpret_cast<const std::int16_t*
>(data), descriptor.scale}, toScale.value());
2224 case DescriptorAdjustedType::INT32:
2225 return numericConverter.numberToNumber<T>(
2226 ScaledInt32{*
reinterpret_cast<const std::int32_t*
>(data), descriptor.scale}, toScale.value());
2228 case DescriptorAdjustedType::INT64:
2229 return numericConverter.numberToNumber<T>(
2230 ScaledInt64{*
reinterpret_cast<const std::int64_t*
>(data), descriptor.scale}, toScale.value());
2232#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
2233 case DescriptorAdjustedType::INT128:
2234 return numericConverter.numberToNumber<T>(
2238 case DescriptorAdjustedType::DECFLOAT16:
2239 return numericConverter.numberToNumber<T>(
2242 case DescriptorAdjustedType::DECFLOAT34:
2243 return numericConverter.numberToNumber<T>(
2247 case DescriptorAdjustedType::FLOAT:
2248 return numericConverter.numberToNumber<T>(*
reinterpret_cast<const float*
>(data), toScale.value());
2251 case DescriptorAdjustedType::DOUBLE:
2252 return numericConverter.numberToNumber<T>(*
reinterpret_cast<const double*
>(data), toScale.value());
2256 throwInvalidType(toTypeName, descriptor.adjustedType);
2261 Client& getClient() noexcept;
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;
2278 unsigned cursorFlags = 0;
2287 inline std::optional<
bool> Statement::get<std::optional<
bool>>(
unsigned index)
2289 return getBool(index);
2293 inline std::optional<BlobId> Statement::get<std::optional<BlobId>>(
unsigned index)
2295 return getBlobId(index);
2299 inline std::optional<std::int16_t> Statement::get<std::optional<std::int16_t>>(
unsigned index)
2301 return getInt16(index);
2305 inline std::optional<ScaledInt16> Statement::get<std::optional<ScaledInt16>>(
unsigned index)
2307 return getScaledInt16(index);
2311 inline std::optional<std::int32_t> Statement::get<std::optional<std::int32_t>>(
unsigned index)
2313 return getInt32(index);
2317 inline std::optional<ScaledInt32> Statement::get<std::optional<ScaledInt32>>(
unsigned index)
2319 return getScaledInt32(index);
2323 inline std::optional<std::int64_t> Statement::get<std::optional<std::int64_t>>(
unsigned index)
2325 return getInt64(index);
2329 inline std::optional<ScaledInt64> Statement::get<std::optional<ScaledInt64>>(
unsigned index)
2331 return getScaledInt64(index);
2335 inline std::optional<ScaledOpaqueInt128> Statement::get<std::optional<ScaledOpaqueInt128>>(
unsigned index)
2337 return getScaledOpaqueInt128(index);
2340#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
2342 inline std::optional<BoostInt128> Statement::get<std::optional<BoostInt128>>(
unsigned index)
2344 return getBoostInt128(index);
2348 inline std::optional<ScaledBoostInt128> Statement::get<std::optional<ScaledBoostInt128>>(
unsigned index)
2350 return getScaledBoostInt128(index);
2355 inline std::optional<float> Statement::get<std::optional<float>>(
unsigned index)
2357 return getFloat(index);
2361 inline std::optional<double> Statement::get<std::optional<double>>(
unsigned index)
2363 return getDouble(index);
2367 inline std::optional<OpaqueDecFloat16> Statement::get<std::optional<OpaqueDecFloat16>>(
unsigned index)
2369 return getOpaqueDecFloat16(index);
2372#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
2374 inline std::optional<BoostDecFloat16> Statement::get<std::optional<BoostDecFloat16>>(
unsigned index)
2376 return getBoostDecFloat16(index);
2380#if FB_CPP_USE_BOOST_DECIMAL != 0
2382 inline std::optional<BoostDecimal32> Statement::get<std::optional<BoostDecimal32>>(
unsigned index)
2384 return getBoostDecimal32(index);
2388 inline std::optional<BoostDecimal64> Statement::get<std::optional<BoostDecimal64>>(
unsigned index)
2390 return getBoostDecimal64(index);
2395 inline std::optional<OpaqueDecFloat34> Statement::get<std::optional<OpaqueDecFloat34>>(
unsigned index)
2397 return getOpaqueDecFloat34(index);
2400#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
2402 inline std::optional<BoostDecFloat34> Statement::get<std::optional<BoostDecFloat34>>(
unsigned index)
2404 return getBoostDecFloat34(index);
2408#if FB_CPP_USE_BOOST_DECIMAL != 0
2410 inline std::optional<BoostDecimal128> Statement::get<std::optional<BoostDecimal128>>(
unsigned index)
2412 return getBoostDecimal128(index);
2417 inline std::optional<Date> Statement::get<std::optional<Date>>(
unsigned index)
2419 return getDate(index);
2423 inline std::optional<OpaqueDate> Statement::get<std::optional<OpaqueDate>>(
unsigned index)
2425 return getOpaqueDate(index);
2429 inline std::optional<Time> Statement::get<std::optional<Time>>(
unsigned index)
2431 return getTime(index);
2435 inline std::optional<OpaqueTime> Statement::get<std::optional<OpaqueTime>>(
unsigned index)
2437 return getOpaqueTime(index);
2441 inline std::optional<OpaqueTimestamp> Statement::get<std::optional<OpaqueTimestamp>>(
unsigned index)
2443 return getOpaqueTimestamp(index);
2447 inline std::optional<Timestamp> Statement::get<std::optional<Timestamp>>(
unsigned index)
2449 return getTimestamp(index);
2453 inline std::optional<TimeTz> Statement::get<std::optional<TimeTz>>(
unsigned index)
2455 return getTimeTz(index);
2459 inline std::optional<OpaqueTimeTz> Statement::get<std::optional<OpaqueTimeTz>>(
unsigned index)
2461 return getOpaqueTimeTz(index);
2465 inline std::optional<TimestampTz> Statement::get<std::optional<TimestampTz>>(
unsigned index)
2467 return getTimestampTz(index);
2471 inline std::optional<OpaqueTimestampTz> Statement::get<std::optional<OpaqueTimestampTz>>(
unsigned index)
2473 return getOpaqueTimestampTz(index);
2477 inline std::optional<std::string> Statement::get<std::optional<std::string>>(
unsigned index)
2479 return getString(index);
Represents a connection to a Firebird database.
Represents a Firebird blob identifier.
Exception thrown when a Firebird database operation fails.
Base exception class for all fb-cpp exceptions.
Reference-counted smart pointer for Firebird objects using addRef/release semantics.
Represents options used when preparing a Statement.
Prepares, executes, and fetches SQL statements against a Firebird attachment.
void set(unsigned index, OpaqueInt128 value)
Convenience overload that binds a Firebird 128-bit integer.
void setScaledInt16(unsigned index, std::optional< ScaledInt16 > optValue)
Binds a scaled 16-bit signed integer value or null.
V get(unsigned index)
Retrieves a column value as a user-defined variant type.
void setNull(unsigned index)
Marks the specified parameter as null.
void setScaledBoostInt128(unsigned index, std::optional< ScaledBoostInt128 > optValue)
Binds a scaled 128-bit integer value expressed with Boost.Multiprecision or null.
std::optional< OpaqueTime > getOpaqueTime(unsigned index)
Reads a raw time-of-day column in Firebird's representation.
std::optional< OpaqueDecFloat34 > getOpaqueDecFloat34(unsigned index)
Reads a Firebird 34-digit decimal floating-point column.
std::vector< std::byte > & getOutputMessage() noexcept
Provides direct access to the raw output message buffer.
void setDate(unsigned index, std::optional< Date > optValue)
Binds a date value or null.
const std::vector< Descriptor > & getInputDescriptors() noexcept
Provides cached descriptors for each input column.
void set(unsigned index, BoostDecimal64 value)
Convenience overload that binds a Boost.Decimal 16-digit decimal floating-point value.
const std::vector< Descriptor > & getOutputDescriptors() noexcept
Provides cached descriptors for each output column.
bool isValid() noexcept
Returns whether the Statement object is valid.
StatementType getType() noexcept
Returns the type classification reported by the server.
void set(unsigned index, BoostDecFloat16 value)
Convenience overload that binds a Boost 16-digit decimal floating-point value.
std::optional< TimeTz > getTimeTz(unsigned index)
Reads a time-of-day column with timezone.
void setTime(unsigned index, std::optional< Time > optValue)
Binds a time-of-day value without timezone or null.
void set(unsigned index, std::string_view value)
Convenience overload that binds a textual value.
std::optional< BoostDecFloat34 > getBoostDecFloat34(unsigned index)
Reads a Boost-based 34-digit decimal floating-point column.
void setBlobId(unsigned index, std::optional< BlobId > optValue)
Binds a blob identifier to the specified parameter or null.
void setInt16(unsigned index, std::optional< std::int16_t > optValue)
Binds a 16-bit signed integer value or null.
void setString(unsigned index, std::optional< std::string_view > optValue)
Binds a textual parameter or null, performing direct conversions where supported.
void set(unsigned index, std::int32_t value)
Convenience overload that binds a 32-bit signed integer.
std::optional< Time > getTime(unsigned index)
Reads a time-of-day column without timezone.
void set(unsigned index, ScaledOpaqueInt128 value)
Convenience overload that binds a scaled Firebird 128-bit integer.
std::optional< Date > getDate(unsigned index)
Reads a date column.
FbRef< fb::IResultSet > getResultSetHandle() noexcept
Provides access to the underlying Firebird currently open result set handle, if any.
bool isNull(unsigned index)
Reports whether the most recently fetched row has a null at the given column.
void set(unsigned index, double value)
Convenience overload that binds a double precision floating-point value.
void clearParameters()
Marks all bound parameters as null values.
void set(unsigned index, ScaledInt64 value)
Convenience overload that binds a scaled 64-bit signed integer.
std::optional< OpaqueDate > getOpaqueDate(unsigned index)
Reads a raw date column in Firebird's representation.
T get()
Retrieves all output columns into a user-defined aggregate struct.
void setScaledInt32(unsigned index, std::optional< ScaledInt32 > optValue)
Binds a scaled 32-bit signed integer value or null.
void set(unsigned index, std::int64_t value)
Convenience overload that binds a 64-bit signed integer.
void setTimestampTz(unsigned index, std::optional< TimestampTz > optValue)
Binds a timestamp value with timezone or null.
std::optional< std::int64_t > getInt64(unsigned index)
Reads a 64-bit signed integer column.
FbRef< fb::IStatement > getStatementHandle() noexcept
Provides direct access to the underlying Firebird statement handle.
void setBoostDecimal64(unsigned index, std::optional< BoostDecimal64 > optValue)
Binds a 16-digit decimal floating-point value using Boost.Decimal or null.
std::optional< ScaledInt32 > getScaledInt32(unsigned index)
Reads a scaled 32-bit signed integer column.
void set(unsigned index, OpaqueTimestampTz value)
Convenience overload that binds a Firebird timestamp with timezone value.
void setOpaqueTime(unsigned index, std::optional< OpaqueTime > optValue)
Binds a raw time-of-day value in Firebird's representation or null.
std::optional< float > getFloat(unsigned index)
Reads a single precision floating-point column.
std::optional< double > getDouble(unsigned index)
Reads a double precision floating-point column.
void set(unsigned index, BoostDecimal128 value)
Convenience overload that binds a Boost.Decimal 34-digit decimal floating-point value.
std::optional< OpaqueTimestampTz > getOpaqueTimestampTz(unsigned index)
Reads a raw timestamp-with-time-zone column in Firebird's representation.
std::optional< ScaledInt16 > getScaledInt16(unsigned index)
Reads a scaled 16-bit signed integer column.
std::optional< BlobId > getBlobId(unsigned index)
Reads a blob identifier column.
void setInt64(unsigned index, std::optional< std::int64_t > optValue)
Binds a 64-bit signed integer value or null.
std::optional< ScaledOpaqueInt128 > getScaledOpaqueInt128(unsigned index)
Reads a Firebird scaled 128-bit integer column.
FbRef< fb::IMessageMetadata > getOutputMetadata() noexcept
Returns the metadata describing columns produced by the statement.
void set(unsigned index, TimeTz value)
Convenience overload that binds a Firebird time with timezone value.
void setOpaqueDecFloat16(unsigned index, std::optional< OpaqueDecFloat16 > optValue)
Binds a 16-digit decimal floating-point value in Firebird's representation or null.
void setOpaqueInt128(unsigned index, std::optional< OpaqueInt128 > optValue)
Binds a raw 128-bit integer value in Firebird's representation or null.
std::optional< OpaqueTimeTz > getOpaqueTimeTz(unsigned index)
Reads a raw time-of-day column with timezone in Firebird's representation.
void setBoostInt128(unsigned index, std::optional< BoostInt128 > optValue)
Binds a 128-bit integer value expressed with Boost.Multiprecision or null.
void setBoostDecimal128(unsigned index, std::optional< BoostDecimal128 > optValue)
Binds a 34-digit decimal floating-point value using Boost.Decimal or null.
void set(unsigned index, Date value)
Convenience overload that binds a Firebird date value.
void set(unsigned index, Timestamp value)
Convenience overload that binds a Firebird timestamp value.
void setOpaqueTimeTz(unsigned index, std::optional< OpaqueTimeTz > optValue)
Binds a raw time-of-day value with timezone in Firebird's representation or null.
void set(unsigned index, BoostDecimal32 value)
Convenience overload that binds a Boost.Decimal 7-digit decimal floating-point value.
void setTimestamp(unsigned index, std::optional< Timestamp > optValue)
Binds a timestamp value without timezone or null.
std::optional< std::string > getString(unsigned index)
Reads a textual column, applying number-to-string conversions when needed.
std::optional< std::int32_t > getInt32(unsigned index)
Reads a 32-bit signed integer column.
void set(unsigned index, OpaqueDecFloat16 value)
Convenience overload that binds a Firebird 16-digit decimal floating-point value.
void setOpaqueTimestampTz(unsigned index, std::optional< OpaqueTimestampTz > optValue)
Binds a raw timestamp value with timezone in Firebird's representation or null.
FbRef< fb::IMessageMetadata > getInputMetadata() noexcept
Returns the metadata describing prepared input parameters.
void setScaledOpaqueInt128(unsigned index, std::optional< ScaledOpaqueInt128 > optValue)
Binds a scaled 128-bit integer in Firebird's representation or null.
~Statement() noexcept
Releases resources; ignores failures to keep destructor noexcept.
void set(unsigned index, OpaqueTimeTz value)
Convenience overload that binds a Firebird time with timezone value.
void setBoostDecFloat16(unsigned index, std::optional< BoostDecFloat16 > optValue)
Binds a 16-digit decimal floating-point value using Boost.Multiprecision or null.
std::optional< ScaledBoostInt128 > getScaledBoostInt128(unsigned index)
Reads a scaled Boost 128-bit integer column.
void set(unsigned index, BlobId value)
Convenience overload that binds a blob identifier.
void set(unsigned index, BoostDecFloat34 value)
Convenience overload that binds a Boost 34-digit decimal floating-point value.
void set(unsigned index, OpaqueDecFloat34 value)
Convenience overload that binds a Firebird 34-digit decimal floating-point value.
void set(unsigned index, Time value)
Convenience overload that binds a Firebird time value.
T get(unsigned index)
Retrieves a column using the most appropriate typed accessor specialization.
void set(unsigned index, ScaledInt16 value)
Convenience overload that binds a scaled 16-bit signed integer.
std::optional< BoostInt128 > getBoostInt128(unsigned index)
Reads a Boost 128-bit integer column.
std::optional< bool > getBool(unsigned index)
Reads a boolean column from the current row.
void setOpaqueDecFloat34(unsigned index, std::optional< OpaqueDecFloat34 > optValue)
Binds a 34-digit decimal floating-point value in Firebird's representation or null.
void set(unsigned index, OpaqueTimestamp value)
Convenience overload that binds a Firebird timestamp value.
void setInt32(unsigned index, std::optional< std::int32_t > optValue)
Binds a 32-bit signed integer value or null.
void set(unsigned index, std::optional< BlobId > value)
Convenience overload that binds an optional blob identifier.
void setBool(unsigned index, std::optional< bool > optValue)
Binds a boolean parameter value or null.
void set(unsigned index, const V &value)
Sets a parameter from a variant value.
void set(unsigned index, TimestampTz value)
Convenience overload that binds a Firebird timestamp with timezone value.
void setDouble(unsigned index, std::optional< double > optValue)
Binds a double precision floating-point value or null.
void set(unsigned index, OpaqueDate value)
Convenience overload that binds a Firebird date value.
void set(unsigned index, std::int16_t value)
Convenience overload that binds a 16-bit signed integer.
std::optional< BoostDecimal32 > getBoostDecimal32(unsigned index)
Reads a Boost.Decimal 7-digit decimal floating-point column.
void set(unsigned index, std::optional< T > value)
Convenience template that forwards optional values to specialized overloads.
std::optional< OpaqueTimestamp > getOpaqueTimestamp(unsigned index)
Reads a raw timestamp column in Firebird's representation.
void setScaledInt64(unsigned index, std::optional< ScaledInt64 > optValue)
Binds a scaled 64-bit signed integer value or null.
Attachment & getAttachment() noexcept
Returns the Attachment object reference used to create this Statement.
void set(unsigned index, std::nullopt_t)
Convenience overload that binds a null value.
void setFloat(unsigned index, std::optional< float > optValue)
Binds a single precision floating-point value or null.
void setOpaqueDate(unsigned index, std::optional< OpaqueDate > optValue)
Binds a raw date value in Firebird's representation or null.
std::optional< BoostDecimal64 > getBoostDecimal64(unsigned index)
Reads a Boost.Decimal 16-digit decimal floating-point column.
void set(unsigned index, OpaqueTime value)
Convenience overload that binds a Firebird time value.
void set(unsigned index, ScaledInt32 value)
Convenience overload that binds a scaled 32-bit signed integer.
std::optional< std::int16_t > getInt16(unsigned index)
Reads a 16-bit signed integer column.
void set(unsigned index, ScaledBoostInt128 value)
Convenience overload that binds a scaled Boost-provided 128-bit integer.
std::optional< TimestampTz > getTimestampTz(unsigned index)
Reads a timestamp-with-time-zone column.
void set(unsigned index, BoostInt128 value)
Convenience overload that binds a Boost-provided 128-bit integer.
std::vector< std::byte > & getInputMessage() noexcept
Provides direct access to the raw input message buffer.
std::optional< OpaqueDecFloat16 > getOpaqueDecFloat16(unsigned index)
Reads a Firebird 16-digit decimal floating-point column.
std::optional< Timestamp > getTimestamp(unsigned index)
Reads a timestamp column without timezone.
std::optional< BoostDecFloat16 > getBoostDecFloat16(unsigned index)
Reads a Boost-based 16-digit decimal floating-point column.
void setTimeTz(unsigned index, std::optional< TimeTz > optValue)
Binds a time-of-day value with timezone or null.
void setBoostDecimal32(unsigned index, std::optional< BoostDecimal32 > optValue)
Binds a 7-digit decimal floating-point value using Boost.Decimal or null.
void setBoostDecFloat34(unsigned index, std::optional< BoostDecFloat34 > optValue)
Binds a 34-digit decimal floating-point value using Boost.Multiprecision or null.
std::optional< ScaledInt64 > getScaledInt64(unsigned index)
Reads a scaled 64-bit signed integer column.
std::optional< BoostDecimal128 > getBoostDecimal128(unsigned index)
Reads a Boost.Decimal 34-digit decimal floating-point column.
void set(unsigned index, bool value)
Convenience overload that binds a boolean value.
void setOpaqueTimestamp(unsigned index, std::optional< OpaqueTimestamp > optValue)
Binds a raw timestamp value in Firebird's representation or null.
void set(unsigned index, float value)
Convenience overload that binds a single precision floating-point value.
void set(const T &value)
Sets all input parameters from fields of a user-defined aggregate struct.
Represents a transaction in one or more Firebird databases.
ScaledNumber< std::int64_t > ScaledInt64
Signed 64-bit scaled number.
ScaledNumber< std::int32_t > ScaledInt32
Signed 32-bit scaled number.
boost::multiprecision::number< boost::multiprecision::cpp_dec_float< 34 > > BoostDecFloat34
34-digit decimal floating point using Boost.Multiprecision.
FB_DEC16 OpaqueDecFloat16
Opaque 16-digit decimal floating point exposed by the Firebird API.
ScaledNumber< std::int16_t > ScaledInt16
Signed 16-bit scaled number.
boost::multiprecision::number< boost::multiprecision::cpp_dec_float< 16 > > BoostDecFloat16
16-digit decimal floating point using Boost.Multiprecision.
boost::decimal::decimal128_t BoostDecimal128
34-digit decimal floating point using Boost.Decimal.
boost::decimal::decimal32_t BoostDecimal32
7-digit decimal floating point using Boost.Decimal.
StatementType
Distinguishes the semantic category of the prepared SQL statement.
@ 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.
std::chrono::year_month_day Date
Firebird SQL calendar date.
FB_DEC34 OpaqueDecFloat34
Opaque 34-digit decimal floating point exposed by the Firebird API.
boost::multiprecision::int128_t BoostInt128
128-bit integer using Boost.Multiprecision.
ScaledNumber< BoostInt128 > ScaledBoostInt128
Scaled 128-bit integer backed by Boost.Multiprecision.
boost::decimal::decimal64_t BoostDecimal64
16-digit decimal floating point using Boost.Decimal.
std::chrono::hh_mm_ss< std::chrono::microseconds > Time
Firebird SQL time-of-day with microsecond resolution.
Describes a parameter or column.
Wrapper for Firebird date values.
Wrapper for Firebird time-with-time-zone values.
Wrapper for Firebird time values.
Wrapper for Firebird timestamp-with-time-zone values.
Wrapper for Firebird timestamp values.
Represents a numeric value with an explicit decimal scale.
T value
Unscaled numeric value.
Local time bound to a time zone.
Timestamp bound to a time zone.
Combined date and time with microsecond precision.