25#ifndef FBCPP_IMPL_PARAMETER_SETTER_H
26#define FBCPP_IMPL_PARAMETER_SETTER_H
32#include "../CalendarConverter.h"
34#include "../Descriptor.h"
35#include "../Exception.h"
36#include "../NumericConverter.h"
37#include "../StructBinding.h"
39#include "../VariantTypeTraits.h"
58#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
59#include <boost/multiprecision/cpp_dec_float.hpp>
60#include <boost/multiprecision/cpp_int.hpp>
63#if FB_CPP_USE_BOOST_DECIMAL != 0
64#include <boost/decimal.hpp>
76 template <
typename Derived,
bool RequestMessageLayout>
87 void clearParameters()
91 for (
const auto& descriptor : descriptors())
93 if constexpr (RequestMessageLayout)
95 if (!descriptor.isNullable)
99 writeNullFlag(descriptor, FB_TRUE);
106 void setNull(
unsigned index)
110 const auto& descriptor = getDescriptor(index);
112 if constexpr (RequestMessageLayout)
114 if (!descriptor.isNullable)
115 throwNonNullable(index);
118 writeNullFlag(descriptor, FB_TRUE);
124 void setBool(
unsigned index, std::optional<bool> optValue)
127 [](std::byte* data,
bool value) { *data = value ? std::byte{1} : std::byte{0}; });
133 void setInt16(
unsigned index, std::optional<std::int16_t> optValue)
135 if (!optValue.has_value())
147 void setScaledInt16(
unsigned index, std::optional<ScaledInt16> optValue)
149 if (!optValue.has_value())
155 const auto& value = optValue.value();
162 void setInt32(
unsigned index, std::optional<std::int32_t> optValue)
164 if (!optValue.has_value())
176 void setScaledInt32(
unsigned index, std::optional<ScaledInt32> optValue)
178 if (!optValue.has_value())
184 const auto& value = optValue.value();
191 void setInt64(
unsigned index, std::optional<std::int64_t> optValue)
193 if (!optValue.has_value())
205 void setScaledInt64(
unsigned index, std::optional<ScaledInt64> optValue)
207 if (!optValue.has_value())
213 const auto& value = optValue.value();
220 void setOpaqueInt128(
unsigned index, std::optional<OpaqueInt128> optValue)
229 void setScaledOpaqueInt128(
unsigned index, std::optional<ScaledOpaqueInt128> optValue)
231 if (!optValue.has_value())
239 const auto& value = optValue.value();
240 const auto& descriptor = getDescriptor(index);
241 auto*
const data = message().data();
243 switch (descriptor.adjustedType)
246 if (value.scale == descriptor.scale)
247 *
reinterpret_cast<OpaqueInt128*
>(&data[descriptor.offset]) = value.value;
250 const auto valueString =
251 numericConverter().opaqueInt128ToString(&statusWrapper(), value.value, value.scale);
253 .getInt128Util(&statusWrapper())
254 ->fromString(&statusWrapper(), descriptor.scale, valueString.c_str(),
255 reinterpret_cast<OpaqueInt128*
>(&data[descriptor.offset]));
260 throwInvalidType(
"ScaledOpaqueInt128", descriptor.adjustedType);
263 writeNotNullFlag(descriptor);
266#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
270 void setBoostInt128(
unsigned index, std::optional<BoostInt128> optValue)
272 if (!optValue.has_value())
284 void setScaledBoostInt128(
unsigned index, std::optional<ScaledBoostInt128> optValue)
286 if (!optValue.has_value())
292 const auto& value = optValue.value();
300 void setFloat(
unsigned index, std::optional<float> optValue)
302 if (!optValue.has_value())
314 void setDouble(
unsigned index, std::optional<double> optValue)
316 if (!optValue.has_value())
328 void setOpaqueDecFloat16(
unsigned index, std::optional<OpaqueDecFloat16> optValue)
335#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
339 void setBoostDecFloat16(
unsigned index, std::optional<BoostDecFloat16> optValue)
341 if (!optValue.has_value())
351#if FB_CPP_USE_BOOST_DECIMAL != 0
355 void setBoostDecimal32(
unsigned index, std::optional<BoostDecimal32> optValue)
357 if (!optValue.has_value())
369 void setBoostDecimal64(
unsigned index, std::optional<BoostDecimal64> optValue)
371 if (!optValue.has_value())
384 void setOpaqueDecFloat34(
unsigned index, std::optional<OpaqueDecFloat34> optValue)
391#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
395 void setBoostDecFloat34(
unsigned index, std::optional<BoostDecFloat34> optValue)
397 if (!optValue.has_value())
407#if FB_CPP_USE_BOOST_DECIMAL != 0
411 void setBoostDecimal128(
unsigned index, std::optional<BoostDecimal128> optValue)
413 if (!optValue.has_value())
426 void setDate(
unsigned index, std::optional<Date> optValue)
429 { *
reinterpret_cast<OpaqueDate*
>(data) = calendarConverter().dateToOpaqueDate(value); });
435 void setOpaqueDate(
unsigned index, std::optional<OpaqueDate> optValue)
438 [](std::byte* data,
const OpaqueDate& value) { *
reinterpret_cast<OpaqueDate*
>(data) = value; });
444 void setTime(
unsigned index, std::optional<Time> optValue)
447 { *
reinterpret_cast<OpaqueTime*
>(data) = calendarConverter().timeToOpaqueTime(value); });
453 void setOpaqueTime(
unsigned index, std::optional<OpaqueTime> optValue)
456 [](std::byte* data,
const OpaqueTime& value) { *
reinterpret_cast<OpaqueTime*
>(data) = value; });
462 void setTimestamp(
unsigned index, std::optional<Timestamp> optValue)
465 [
this](std::byte* data,
const Timestamp& value)
466 { *
reinterpret_cast<OpaqueTimestamp*
>(data) = calendarConverter().timestampToOpaqueTimestamp(value); });
472 void setOpaqueTimestamp(
unsigned index, std::optional<OpaqueTimestamp> optValue)
475 [](std::byte* data,
const OpaqueTimestamp& value)
476 { *
reinterpret_cast<OpaqueTimestamp*
>(data) = value; });
482 void setTimeTz(
unsigned index, std::optional<TimeTz> optValue)
485 [
this](std::byte* data,
const TimeTz& value)
487 *
reinterpret_cast<OpaqueTimeTz*
>(data) =
488 calendarConverter().timeTzToOpaqueTimeTz(&statusWrapper(), value);
495 void setOpaqueTimeTz(
unsigned index, std::optional<OpaqueTimeTz> optValue)
498 [](std::byte* data,
const OpaqueTimeTz& value) { *
reinterpret_cast<OpaqueTimeTz*
>(data) = value; });
504 void setTimestampTz(
unsigned index, std::optional<TimestampTz> optValue)
507 [
this](std::byte* data,
const TimestampTz& value)
509 *
reinterpret_cast<OpaqueTimestampTz*
>(data) =
510 calendarConverter().timestampTzToOpaqueTimestampTz(&statusWrapper(), value);
517 void setOpaqueTimestampTz(
unsigned index, std::optional<OpaqueTimestampTz> optValue)
520 [](std::byte* data,
const OpaqueTimestampTz& value)
521 { *
reinterpret_cast<OpaqueTimestampTz*
>(data) = value; });
527 void setString(
unsigned index, std::optional<std::string_view> optValue)
529 if (!optValue.has_value())
537 auto& clientValue = client();
538 const auto value = optValue.value();
539 const auto& descriptor = getDescriptor(index);
540 auto*
const data = message().data();
541 const auto descriptorData = &data[descriptor.offset];
543 switch (descriptor.adjustedType)
546 data[descriptor.offset] = numericConverter().stringToBoolean(value);
553 std::string strValue(value);
556 if (
const auto dotPos = strValue.find_last_of(
'.'); dotPos != std::string_view::npos)
558 for (
auto pos = dotPos + 1; pos < strValue.size(); ++pos)
560 const char c = value[pos];
562 if (c <
'0' || c >
'9')
568 strValue.erase(dotPos, 1);
571 static_assert(
sizeof(
long long) ==
sizeof(std::int64_t));
572 std::int64_t intValue;
573 const auto convResult =
574 std::from_chars(strValue.data(), strValue.data() + strValue.size(), intValue);
575 if (convResult.ec != std::errc{} || convResult.ptr != strValue.data() + strValue.size())
576 numericConverter().throwConversionErrorFromString(strValue);
579 if (scale != descriptor.scale)
582 numericConverter().template numberToNumber<std::int64_t>(scaledValue, descriptor.scale);
583 scaledValue.scale = descriptor.scale;
586 setScaledInt64(index, scaledValue);
592 std::string strValue(value);
593 clientValue.getInt128Util(&statusWrapper())
594 ->fromString(&statusWrapper(), descriptor.scale, strValue.c_str(),
603#if defined(__APPLE__)
605 std::string valueString{value};
606 char* parseEnd =
nullptr;
607 doubleValue = std::strtod(valueString.c_str(), &parseEnd);
608 if (parseEnd != valueString.c_str() + valueString.size() || errno == ERANGE)
609 numericConverter().throwConversionErrorFromString(std::move(valueString));
611 const auto convResult = std::from_chars(value.data(), value.data() + value.size(), doubleValue);
612 if (convResult.ec != std::errc{} || convResult.ptr != value.data() + value.size())
613 numericConverter().throwConversionErrorFromString(std::string{value});
615 setDouble(index, doubleValue);
620 *
reinterpret_cast<OpaqueDate*
>(descriptorData) = calendarConverter().stringToOpaqueDate(value);
624 *
reinterpret_cast<OpaqueTime*
>(descriptorData) = calendarConverter().stringToOpaqueTime(value);
628 *
reinterpret_cast<OpaqueTimestamp*
>(descriptorData) =
629 calendarConverter().stringToOpaqueTimestamp(value);
633 *
reinterpret_cast<OpaqueTimeTz*
>(descriptorData) =
634 calendarConverter().stringToOpaqueTimeTz(&statusWrapper(), value);
638 *
reinterpret_cast<OpaqueTimestampTz*
>(descriptorData) =
639 calendarConverter().stringToOpaqueTimestampTz(&statusWrapper(), value);
644 std::string strValue{value};
645 clientValue.getDecFloat16Util(&statusWrapper())
647 &statusWrapper(), strValue.c_str(),
reinterpret_cast<OpaqueDecFloat16*
>(descriptorData));
653 std::string strValue{value};
654 clientValue.getDecFloat34Util(&statusWrapper())
656 &statusWrapper(), strValue.c_str(),
reinterpret_cast<OpaqueDecFloat34*
>(descriptorData));
661 if (value.length() > stringCapacity(descriptor))
663 static constexpr std::intptr_t STATUS_STRING_TRUNCATION[] = {
665 isc_string_truncation,
669 throw DatabaseException(clientValue, STATUS_STRING_TRUNCATION);
672 *
reinterpret_cast<std::uint16_t*
>(descriptorData) =
static_cast<std::uint16_t
>(value.length());
673 std::copy(value.begin(), value.end(),
674 reinterpret_cast<char*
>(&data[descriptor.offset +
sizeof(std::uint16_t)]));
678 throwInvalidType(
"std::string_view", descriptor.adjustedType);
681 writeNotNullFlag(descriptor);
687 void setBytes(
unsigned index, std::span<const std::byte> value)
691 const auto& descriptor = getDescriptor(index);
692 auto*
const data = message().data();
694 switch (descriptor.adjustedType)
697 if (value.size() > stringCapacity(descriptor))
699 static constexpr std::intptr_t STATUS_STRING_TRUNCATION[] = {
701 isc_string_truncation,
705 throw DatabaseException(client(), STATUS_STRING_TRUNCATION);
708 *
reinterpret_cast<std::uint16_t*
>(&data[descriptor.offset]) =
709 static_cast<std::uint16_t
>(value.size());
710 std::copy(value.begin(), value.end(), &data[descriptor.offset +
sizeof(std::uint16_t)]);
714 throwInvalidType(
"std::span<const std::byte>", descriptor.adjustedType);
717 writeNotNullFlag(descriptor);
723 void setBytes(
unsigned index,
const std::vector<std::byte>& value)
725 setBytes(index, std::span<const std::byte>{value});
731 void setBytes(
unsigned index, std::optional<std::vector<std::byte>> optValue)
733 if (!optValue.has_value())
739 setBytes(index, std::span<const std::byte>{optValue.value()});
745 void setBytes(
unsigned index, std::nullopt_t)
753 void setBlobId(
unsigned index, std::optional<BlobId> optValue)
756 [](std::byte* data,
const BlobId& value) { *
reinterpret_cast<ISC_QUAD*
>(data) = value.id; });
762 void setArrayId(
unsigned index, std::optional<ArrayId> optValue)
765 [](std::byte* data,
const ArrayId& value) { *
reinterpret_cast<ISC_QUAD*
>(data) = value.id; });
775 void set(
unsigned index, std::nullopt_t)
783 void set(
unsigned index, BlobId value)
785 setBlobId(index, value);
791 void set(
unsigned index, std::optional<BlobId> value)
793 setBlobId(index, value);
799 void set(
unsigned index, ArrayId value)
801 setArrayId(index, value);
807 void set(
unsigned index, std::optional<ArrayId> value)
809 setArrayId(index, value);
815 void set(
unsigned index,
bool value)
817 setBool(index, value);
823 void set(
unsigned index, std::int16_t value)
825 setInt16(index, value);
833 setScaledInt16(index, value);
839 void set(
unsigned index, std::int32_t value)
841 setInt32(index, value);
849 setScaledInt32(index, value);
855 void set(
unsigned index, std::int64_t value)
857 setInt64(index, value);
865 setScaledInt64(index, value);
873 setOpaqueInt128(index, value);
881 setScaledOpaqueInt128(index, value);
884#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
890 setBoostInt128(index, value);
898 setScaledBoostInt128(index, value);
905 void set(
unsigned index,
float value)
907 setFloat(index, value);
913 void set(
unsigned index,
double value)
915 setDouble(index, value);
923 setOpaqueDecFloat16(index, value);
926#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
932 setBoostDecFloat16(index, value);
936#if FB_CPP_USE_BOOST_DECIMAL != 0
942 setBoostDecimal32(index, value);
950 setBoostDecimal64(index, value);
959 setOpaqueDecFloat34(index, value);
962#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
968 setBoostDecFloat34(index, value);
972#if FB_CPP_USE_BOOST_DECIMAL != 0
978 setBoostDecimal128(index, value);
985 void set(
unsigned index,
Date value)
987 setDate(index, value);
993 void set(
unsigned index, OpaqueDate value)
995 setOpaqueDate(index, value);
1001 void set(
unsigned index,
Time value)
1003 setTime(index, value);
1009 void set(
unsigned index, OpaqueTime value)
1011 setOpaqueTime(index, value);
1017 void set(
unsigned index, Timestamp value)
1019 setTimestamp(index, value);
1025 void set(
unsigned index, OpaqueTimestamp value)
1027 setOpaqueTimestamp(index, value);
1033 void set(
unsigned index, TimeTz value)
1035 setTimeTz(index, value);
1041 void set(
unsigned index, OpaqueTimeTz value)
1043 setOpaqueTimeTz(index, value);
1049 void set(
unsigned index, TimestampTz value)
1051 setTimestampTz(index, value);
1057 void set(
unsigned index, OpaqueTimestampTz value)
1059 setOpaqueTimestampTz(index, value);
1065 void set(
unsigned index, std::string_view value)
1067 setString(index, value);
1073 void set(
unsigned index,
const std::vector<std::byte>& value)
1075 setBytes(index, value);
1081 void set(
unsigned index, std::span<const std::byte> value)
1083 setBytes(index, value);
1089 template <
typename T>
1090 void set(
unsigned index, std::optional<T> value)
1092 if (value.has_value())
1093 set(index, value.value());
1105 template <Aggregate T>
1106 void set(
const T& value)
1108 using namespace reflection;
1110 constexpr std::size_t N = fieldCountV<T>;
1112 if (N != descriptors().size())
1114 throw FbCppException(
"Struct field count (" + std::to_string(N) +
1115 ") does not match input parameter count (" + std::to_string(descriptors().size()) +
")");
1118 setStruct(value, std::make_index_sequence<N>{});
1124 template <TupleLike T>
1125 void set(
const T& value)
1127 constexpr std::size_t N = std::tuple_size_v<T>;
1129 if (N != descriptors().size())
1131 throw FbCppException(
"Tuple element count (" + std::to_string(N) +
1132 ") does not match input parameter count (" + std::to_string(descriptors().size()) +
")");
1135 setTuple(value, std::make_index_sequence<N>{});
1141 template <VariantLike V>
1142 void set(
unsigned index,
const V& value)
1144 using namespace reflection;
1146 static_assert(variantAlternativesSupportedV<V>,
1147 "Variant contains unsupported types. All variant alternatives must be types supported by fb-cpp "
1148 "(e.g., std::int32_t, std::string, Date, ScaledOpaqueInt128, etc.). Check VariantTypeTraits.h for "
1149 "the complete list of supported types.");
1152 [
this, index](
const auto& v)
1154 using T = std::decay_t<
decltype(v)>;
1156 if constexpr (std::is_same_v<T, std::monostate>)
1169 Derived& owner() noexcept
1171 return static_cast<Derived&
>(*this);
1174 const Derived& owner() const noexcept
1176 return static_cast<const Derived&
>(*this);
1179 const std::vector<Descriptor>& descriptors() const noexcept
1181 return owner().getSetterDescriptors();
1184 std::vector<std::byte>& message() noexcept
1186 return owner().getSetterMessage();
1189 Client& client() noexcept
1191 return owner().getSetterClient();
1194 impl::StatusWrapper& statusWrapper() noexcept
1196 return owner().statusWrapper;
1199 impl::NumericConverter& numericConverter() noexcept
1201 return owner().numericConverter;
1204 impl::CalendarConverter& calendarConverter() noexcept
1206 return owner().calendarConverter;
1209 void validateSetter() const noexcept
1211 owner().validateSetter();
1214 const Descriptor& getDescriptor(
unsigned index)
const
1216 if (index >= descriptors().size())
1217 throw std::out_of_range(
"index out of range");
1219 return descriptors()[index];
1222 template <
typename T,
typename Writer>
1224 const char* typeName, Writer writer)
1226 if (!optValue.has_value())
1234 const auto& descriptor = getDescriptor(index);
1236 if (descriptor.adjustedType != expectedType)
1237 throwInvalidType(typeName, descriptor.adjustedType);
1239 writer(&message()[descriptor.offset], optValue.value());
1240 writeNotNullFlag(descriptor);
1243#if FB_CPP_USE_BOOST_DECIMAL != 0
1244 template <
typename T>
1245 void setDecimalNumber(
unsigned index, T value, std::optional<int>& descriptorScale,
const char* typeName)
1247 const auto& descriptor = getDescriptor(index);
1248 auto*
const data = message().data();
1249 const auto descriptorData = &data[descriptor.offset];
1251 switch (descriptor.adjustedType)
1254 *
reinterpret_cast<std::int16_t*
>(descriptorData) =
1255 numericConverter().template numberToNumber<std::int16_t>(value, descriptorScale.value());
1259 *
reinterpret_cast<std::int32_t*
>(descriptorData) =
1260 numericConverter().template numberToNumber<std::int32_t>(value, descriptorScale.value());
1264 *
reinterpret_cast<std::int64_t*
>(descriptorData) =
1265 numericConverter().template numberToNumber<std::int64_t>(value, descriptorScale.value());
1268#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
1271 const auto int128Value =
1272 numericConverter().template numberToNumber<BoostInt128>(value, descriptorScale.value());
1274 numericConverter().boostInt128ToOpaqueInt128(&statusWrapper(), int128Value);
1280 *
reinterpret_cast<float*
>(descriptorData) =
1281 numericConverter().template numberToNumber<float>(value);
1285 *
reinterpret_cast<double*
>(descriptorData) =
1286 numericConverter().template numberToNumber<double>(value);
1291 const auto decimalValue = numericConverter().template numberToNumber<BoostDecimal64>(value);
1293 numericConverter().boostDecimal64ToOpaqueDecFloat16(&statusWrapper(), decimalValue);
1299 const auto decimalValue = numericConverter().template numberToNumber<BoostDecimal128>(value);
1301 numericConverter().boostDecimal128ToOpaqueDecFloat34(&statusWrapper(), decimalValue);
1306 throwInvalidType(typeName, descriptor.adjustedType);
1311 template <
typename T>
1312 void setNumber(
unsigned index,
DescriptorAdjustedType valueType, T value,
int scale,
const char* typeName)
1316 const auto& descriptor = getDescriptor(index);
1317 auto*
const data = message().data();
1318 const auto descriptorData = &data[descriptor.offset];
1319 std::optional<int> descriptorScale{descriptor.scale};
1321#if FB_CPP_USE_BOOST_DECIMAL != 0
1322 if constexpr (std::is_same_v<T, BoostDecimal32> || std::is_same_v<T, BoostDecimal64> ||
1323 std::is_same_v<T, BoostDecimal128>)
1325 setDecimalNumber(index, value, descriptorScale, typeName);
1326 writeNotNullFlag(descriptor);
1331 Descriptor valueDescriptor;
1332 valueDescriptor.adjustedType = valueType;
1333 valueDescriptor.scale = scale;
1335 const auto valueAddress =
reinterpret_cast<const std::byte*
>(&value);
1337 switch (descriptor.adjustedType)
1340 *
reinterpret_cast<std::int16_t*
>(descriptorData) =
1341 convertNumber<std::int16_t>(valueDescriptor, valueAddress, descriptorScale,
"std::int16_t");
1345 *
reinterpret_cast<std::int32_t*
>(descriptorData) =
1346 convertNumber<std::int32_t>(valueDescriptor, valueAddress, descriptorScale,
"std::int32_t");
1350 *
reinterpret_cast<std::int64_t*
>(descriptorData) =
1351 convertNumber<std::int64_t>(valueDescriptor, valueAddress, descriptorScale,
"std::int64_t");
1354#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
1357 const auto boostInt128 =
1358 convertNumber<BoostInt128>(valueDescriptor, valueAddress, descriptorScale,
"BoostInt128");
1360 numericConverter().boostInt128ToOpaqueInt128(&statusWrapper(), boostInt128);
1366 *
reinterpret_cast<float*
>(descriptorData) =
1367 convertNumber<float>(valueDescriptor, valueAddress, descriptorScale,
"float");
1371 *
reinterpret_cast<double*
>(descriptorData) =
1372 convertNumber<double>(valueDescriptor, valueAddress, descriptorScale,
"double");
1375#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
1378 const auto boostDecFloat16 = convertNumber<BoostDecFloat16>(
1379 valueDescriptor, valueAddress, descriptorScale,
"BoostDecFloat16");
1381 numericConverter().boostDecFloat16ToOpaqueDecFloat16(&statusWrapper(), boostDecFloat16);
1387 const auto boostDecFloat34 = convertNumber<BoostDecFloat34>(
1388 valueDescriptor, valueAddress, descriptorScale,
"BoostDecFloat34");
1390 numericConverter().boostDecFloat34ToOpaqueDecFloat34(&statusWrapper(), boostDecFloat34);
1396 throwInvalidType(typeName, descriptor.adjustedType);
1399 writeNotNullFlag(descriptor);
1404 throw FbCppException(
"Invalid type: actual type " + std::string(actualType) +
", descriptor type " +
1405 std::to_string(
static_cast<unsigned>(descriptorType)));
1408 [[noreturn]]
static void throwNonNullable(
unsigned index)
1410 throw FbCppException(
"Field " + std::to_string(index) +
" is not nullable");
1413 void writeNullFlag(
const Descriptor& descriptor, std::int16_t value)
1415 if constexpr (!RequestMessageLayout)
1417 *
reinterpret_cast<std::int16_t*
>(&message()[descriptor.nullOffset]) = value;
1419 else if (descriptor.isNullable)
1420 *
reinterpret_cast<std::int16_t*
>(&message()[descriptor.nullOffset]) = value;
1423 void writeNotNullFlag(
const Descriptor& descriptor)
1425 writeNullFlag(descriptor, FB_FALSE);
1428 unsigned stringCapacity(
const Descriptor& descriptor)
const noexcept
1430 if constexpr (RequestMessageLayout)
1431 return descriptor.length -
sizeof(std::uint16_t);
1433 return descriptor.length;
1436 template <
typename T, std::size_t... Is>
1437 void setStruct(
const T& value, std::index_sequence<Is...>)
1439 using namespace reflection;
1441 const auto tuple = toTupleRef(value);
1442 (set(
static_cast<unsigned>(Is), std::get<Is>(tuple)), ...);
1445 template <
typename T, std::size_t... Is>
1446 void setTuple(
const T& value, std::index_sequence<Is...>)
1448 (set(
static_cast<unsigned>(Is), std::get<Is>(value)), ...);
1451 template <
typename T>
1453 const Descriptor& descriptor,
const std::byte* data, std::optional<int>& toScale,
const char* toTypeName)
1455 if (!toScale.has_value())
1457 switch (descriptor.adjustedType)
1463 throwInvalidType(toTypeName, descriptor.adjustedType);
1469 toScale = descriptor.scale;
1472 switch (descriptor.adjustedType)
1475 return numericConverter().template numberToNumber<T>(
1476 ScaledInt16{*
reinterpret_cast<const std::int16_t*
>(data), descriptor.scale}, toScale.value());
1479 return numericConverter().template numberToNumber<T>(
1480 ScaledInt32{*
reinterpret_cast<const std::int32_t*
>(data), descriptor.scale}, toScale.value());
1483 return numericConverter().template numberToNumber<T>(
1484 ScaledInt64{*
reinterpret_cast<const std::int64_t*
>(data), descriptor.scale}, toScale.value());
1486#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
1488 return numericConverter().template numberToNumber<T>(
1493 return numericConverter().template numberToNumber<T>(
1497 return numericConverter().template numberToNumber<T>(
1502 return numericConverter().template numberToNumber<T>(
1503 *
reinterpret_cast<const float*
>(data), toScale.value());
1506 return numericConverter().template numberToNumber<T>(
1507 *
reinterpret_cast<const double*
>(data), toScale.value());
1510 throwInvalidType(toTypeName, descriptor.adjustedType);
ScaledNumber< OpaqueInt128 > ScaledOpaqueInt128
Scaled Firebird opaque 128-bit integer.
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.
DescriptorAdjustedType
Descriptor adjusted type.
@ 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.
@ ARRAY
Array value represented by an array identifier.
@ FLOAT
Single-precision floating point.
@ DOUBLE
Double-precision floating point.
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.