25#ifndef FBCPP_STATEMENT_H
26#define FBCPP_STATEMENT_H
32#include "Attachment.h"
34#include "NumericConverter.h"
35#include "CalendarConverter.h"
36#include "Descriptor.h"
55#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
56#include <boost/multiprecision/cpp_int.hpp>
57#include <boost/multiprecision/cpp_dec_float.hpp>
78 return prefetchLegacyPlan;
88 prefetchLegacyPlan = value;
107 prefetchPlan = value;
112 bool prefetchLegacyPlan =
false;
113 bool prefetchPlan =
false;
124 SELECT = isc_info_sql_stmt_select,
128 INSERT = isc_info_sql_stmt_insert,
132 UPDATE = isc_info_sql_stmt_update,
136 DELETE = isc_info_sql_stmt_delete,
140 DDL = isc_info_sql_stmt_ddl,
160 COMMIT = isc_info_sql_stmt_commit,
164 ROLLBACK = isc_info_sql_stmt_rollback,
199 : attachment{o.attachment},
200 status{std::move(o.status)},
201 statusWrapper{std::move(o.statusWrapper)},
202 calendarConverter{std::move(o.calendarConverter)},
203 numericConverter{std::move(o.numericConverter)},
204 statementHandle{std::move(o.statementHandle)},
205 resultSetHandle{std::move(o.resultSetHandle)},
206 inMetadata{std::move(o.inMetadata)},
207 inDescriptors{std::move(o.inDescriptors)},
208 inMessage{std::move(o.inMessage)},
209 outMetadata{std::move(o.outMetadata)},
210 outDescriptors{std::move(o.outDescriptors)},
211 outMessage{std::move(o.outMessage)},
216 Statement& operator=(Statement&&) =
delete;
218 Statement& operator=(
const Statement&) =
delete;
250 return statementHandle !=
nullptr;
259 return statementHandle;
268 return resultSetHandle;
310 return inDescriptors;
318 return outDescriptors;
396 const auto message = inMessage.data();
398 for (
const auto& descriptor : inDescriptors)
399 *
reinterpret_cast<std::int16_t*
>(&message[descriptor.nullOffset]) = FB_TRUE;
410 const auto& descriptor = getInDescriptor(index);
411 const auto message = inMessage.data();
413 *
reinterpret_cast<std::int16_t*
>(&message[descriptor.nullOffset]) = FB_TRUE;
421 void setBool(
unsigned index, std::optional<bool> optValue)
423 if (!optValue.has_value())
431 const auto& value = optValue.value();
432 const auto& descriptor = getInDescriptor(index);
433 const auto message = inMessage.data();
435 switch (descriptor.adjustedType)
437 case DescriptorAdjustedType::BOOLEAN:
438 message[descriptor.offset] = value ? std::byte{1} : std::byte{0};
442 throwInvalidType(
"bool", descriptor.adjustedType);
445 *
reinterpret_cast<std::int16_t*
>(&message[descriptor.nullOffset]) = FB_FALSE;
451 void setInt16(
unsigned index, std::optional<std::int16_t> optValue)
453 if (!optValue.has_value())
459 setNumber(index, DescriptorAdjustedType::INT16, optValue.value(), 0,
"std::int16_t");
467 if (!optValue.has_value())
473 const auto& value = optValue.value();
474 setNumber(index, DescriptorAdjustedType::INT16, value.value, value.scale,
"ScaledInt16");
480 void setInt32(
unsigned index, std::optional<std::int32_t> optValue)
482 if (!optValue.has_value())
488 setNumber(index, DescriptorAdjustedType::INT32, optValue.value(), 0,
"std::int32_t");
496 if (!optValue.has_value())
502 const auto& value = optValue.value();
503 setNumber(index, DescriptorAdjustedType::INT32, value.value, value.scale,
"ScaledInt32");
509 void setInt64(
unsigned index, std::optional<std::int64_t> optValue)
511 if (!optValue.has_value())
517 setNumber(index, DescriptorAdjustedType::INT64, optValue.value(), 0,
"std::int64_t");
525 if (!optValue.has_value())
531 const auto& value = optValue.value();
532 setNumber(index, DescriptorAdjustedType::INT64, value.value, value.scale,
"ScaledInt64");
540 if (!optValue.has_value())
548 const auto& value = optValue.value();
549 const auto& descriptor = getInDescriptor(index);
550 const auto message = inMessage.data();
552 switch (descriptor.adjustedType)
554 case DescriptorAdjustedType::INT128:
555 *
reinterpret_cast<OpaqueInt128*
>(&message[descriptor.offset]) = value;
559 throwInvalidType(
"OpaqueInt128", descriptor.adjustedType);
562 *
reinterpret_cast<std::int16_t*
>(&message[descriptor.nullOffset]) = FB_FALSE;
565#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
571 if (!optValue.has_value())
577 setNumber(index, DescriptorAdjustedType::INT128, optValue.value(), 0,
"BoostInt128");
585 if (!optValue.has_value())
591 const auto& value = optValue.value();
592 setNumber(index, DescriptorAdjustedType::INT128, value.value, value.scale,
"ScaledBoostInt128");
599 void setFloat(
unsigned index, std::optional<float> optValue)
601 if (!optValue.has_value())
607 setNumber(index, DescriptorAdjustedType::FLOAT, optValue.value(), 0,
"float");
613 void setDouble(
unsigned index, std::optional<double> optValue)
615 if (!optValue.has_value())
621 setNumber(index, DescriptorAdjustedType::DOUBLE, optValue.value(), 0,
"double");
629 if (!optValue.has_value())
637 const auto& value = optValue.value();
638 const auto& descriptor = getInDescriptor(index);
639 const auto message = inMessage.data();
641 switch (descriptor.adjustedType)
643 case DescriptorAdjustedType::DECFLOAT16:
648 throwInvalidType(
"OpaqueDecFloat16", descriptor.adjustedType);
651 *
reinterpret_cast<std::int16_t*
>(&message[descriptor.nullOffset]) = FB_FALSE;
654#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
660 if (!optValue.has_value())
666 setNumber(index, DescriptorAdjustedType::DECFLOAT16, optValue.value(), 0,
"BoostDecFloat16");
675 if (!optValue.has_value())
683 const auto& value = optValue.value();
684 const auto& descriptor = getInDescriptor(index);
685 const auto message = inMessage.data();
687 switch (descriptor.adjustedType)
689 case DescriptorAdjustedType::DECFLOAT34:
694 throwInvalidType(
"OpaqueDecFloat34", descriptor.adjustedType);
697 *
reinterpret_cast<std::int16_t*
>(&message[descriptor.nullOffset]) = FB_FALSE;
700#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
706 if (!optValue.has_value())
712 setNumber(index, DescriptorAdjustedType::DECFLOAT34, optValue.value(), 0,
"BoostDecFloat34");
719 void setDate(
unsigned index, std::optional<Date> optValue)
721 if (!optValue.has_value())
729 const auto& value = optValue.value();
730 const auto& descriptor = getInDescriptor(index);
731 const auto message = inMessage.data();
733 switch (descriptor.adjustedType)
735 case DescriptorAdjustedType::DATE:
736 *
reinterpret_cast<OpaqueDate*
>(&message[descriptor.offset]) =
737 calendarConverter.dateToOpaqueDate(value);
741 throwInvalidType(
"Date", descriptor.adjustedType);
744 *
reinterpret_cast<std::int16_t*
>(&message[descriptor.nullOffset]) = FB_FALSE;
752 if (!optValue.has_value())
760 const auto& value = optValue.value();
761 const auto& descriptor = getInDescriptor(index);
762 const auto message = inMessage.data();
764 switch (descriptor.adjustedType)
766 case DescriptorAdjustedType::DATE:
767 *
reinterpret_cast<OpaqueDate*
>(&message[descriptor.offset]) = value;
771 throwInvalidType(
"OpaqueDate", descriptor.adjustedType);
774 *
reinterpret_cast<std::int16_t*
>(&message[descriptor.nullOffset]) = FB_FALSE;
780 void setTime(
unsigned index, std::optional<Time> 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::TIME:
797 *
reinterpret_cast<OpaqueTime*
>(&message[descriptor.offset]) =
798 calendarConverter.timeToOpaqueTime(value);
802 throwInvalidType(
"Time", 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::TIME:
828 *
reinterpret_cast<OpaqueTime*
>(&message[descriptor.offset]) = value;
832 throwInvalidType(
"OpaqueTime", descriptor.adjustedType);
835 *
reinterpret_cast<std::int16_t*
>(&message[descriptor.nullOffset]) = FB_FALSE;
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::TIMESTAMP:
859 calendarConverter.timestampToOpaqueTimestamp(value);
863 throwInvalidType(
"Timestamp", 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::TIMESTAMP:
889 *
reinterpret_cast<OpaqueTimestamp*
>(&message[descriptor.offset]) = value;
893 throwInvalidType(
"OpaqueTimestamp", descriptor.adjustedType);
896 *
reinterpret_cast<std::int16_t*
>(&message[descriptor.nullOffset]) = FB_FALSE;
902 void setTimeTz(
unsigned index, std::optional<TimeTz> optValue)
904 if (!optValue.has_value())
912 const auto& value = optValue.value();
913 const auto& descriptor = getInDescriptor(index);
914 auto*
const message = inMessage.data();
916 switch (descriptor.adjustedType)
918 case DescriptorAdjustedType::TIME_TZ:
919 *
reinterpret_cast<OpaqueTimeTz*
>(&message[descriptor.offset]) =
920 calendarConverter.timeTzToOpaqueTimeTz(value);
924 throwInvalidType(
"TimeTz", 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 auto*
const message = inMessage.data();
947 switch (descriptor.adjustedType)
949 case DescriptorAdjustedType::TIME_TZ:
950 *
reinterpret_cast<OpaqueTimeTz*
>(&message[descriptor.offset]) = value;
954 throwInvalidType(
"OpaqueTimeTz", descriptor.adjustedType);
957 *
reinterpret_cast<std::int16_t*
>(&message[descriptor.nullOffset]) = FB_FALSE;
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::TIMESTAMP_TZ:
981 calendarConverter.timestampTzToOpaqueTimestampTz(value);
985 throwInvalidType(
"TimestampTz", 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::TIMESTAMP_TZ:
1015 throwInvalidType(
"OpaqueTimestampTz", descriptor.adjustedType);
1018 *
reinterpret_cast<std::int16_t*
>(&message[descriptor.nullOffset]) = FB_FALSE;
1024 void setString(
unsigned index, std::optional<std::string_view> optValue)
1026 if (!optValue.has_value())
1034 const auto value = optValue.value();
1035 const auto& descriptor = getInDescriptor(index);
1036 const auto message = inMessage.data();
1038 switch (descriptor.adjustedType)
1040 case DescriptorAdjustedType::BOOLEAN:
1041 message[descriptor.offset] = numericConverter.stringToBoolean(value);
1044 case DescriptorAdjustedType::INT16:
1045 case DescriptorAdjustedType::INT32:
1046 case DescriptorAdjustedType::INT64:
1048 std::string strValue(value);
1051 if (
const auto dotPos = strValue.find_last_of(
'.'); dotPos != std::string_view::npos)
1053 for (
auto pos = dotPos + 1; pos < strValue.size(); ++pos)
1055 const char c = value[pos];
1057 if (c <
'0' || c >
'9')
1063 strValue.erase(dotPos, 1);
1066 static_assert(
sizeof(
long long) ==
sizeof(std::int64_t));
1067 std::int64_t intValue;
1068 const auto convResult =
1069 std::from_chars(strValue.data(), strValue.data() + strValue.size(), intValue);
1070 if (convResult.ec != std::errc{} || convResult.ptr != strValue.data() + strValue.size())
1071 numericConverter.throwConversionErrorFromString(strValue);
1074 if (scale != descriptor.scale)
1077 numericConverter.numberToNumber<std::int64_t>(scaledValue, descriptor.scale);
1078 scaledValue.scale = descriptor.scale;
1085 case DescriptorAdjustedType::INT128:
1087 std::string strValue(value);
1090 ->fromString(&statusWrapper, descriptor.scale, strValue.c_str(),
1091 reinterpret_cast<OpaqueInt128*
>(&message[descriptor.offset]));
1095 case DescriptorAdjustedType::FLOAT:
1096 case DescriptorAdjustedType::DOUBLE:
1099#if defined(__APPLE__)
1101 std::string valueString{value};
1102 char* parseEnd =
nullptr;
1103 doubleValue = std::strtod(valueString.c_str(), &parseEnd);
1104 if (parseEnd != valueString.c_str() + valueString.size() || errno == ERANGE)
1105 numericConverter.throwConversionErrorFromString(std::move(valueString));
1107 const auto convResult = std::from_chars(value.data(), value.data() + value.size(), doubleValue);
1108 if (convResult.ec != std::errc{} || convResult.ptr != value.data() + value.size())
1109 numericConverter.throwConversionErrorFromString(std::string{value});
1115 case DescriptorAdjustedType::DATE:
1116 *
reinterpret_cast<OpaqueDate*
>(&message[descriptor.offset]) =
1117 calendarConverter.stringToOpaqueDate(value);
1120 case DescriptorAdjustedType::TIME:
1121 *
reinterpret_cast<OpaqueTime*
>(&message[descriptor.offset]) =
1122 calendarConverter.stringToOpaqueTime(value);
1125 case DescriptorAdjustedType::TIMESTAMP:
1127 calendarConverter.stringToOpaqueTimestamp(value);
1130 case DescriptorAdjustedType::TIME_TZ:
1131 *
reinterpret_cast<OpaqueTimeTz*
>(&message[descriptor.offset]) =
1132 calendarConverter.stringToOpaqueTimeTz(value);
1135 case DescriptorAdjustedType::TIMESTAMP_TZ:
1137 calendarConverter.stringToOpaqueTimestampTz(value);
1139#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
1141 case DescriptorAdjustedType::DECFLOAT16:
1142 case DescriptorAdjustedType::DECFLOAT34:
1149 numericConverter.throwConversionErrorFromString(std::string{value});
1154 case DescriptorAdjustedType::STRING:
1155 if (value.length() > descriptor.length)
1157 static constexpr std::intptr_t STATUS_STRING_TRUNCATION[] = {
1159 isc_string_truncation,
1166 *
reinterpret_cast<std::uint16_t*
>(&message[descriptor.offset]) =
1167 static_cast<std::uint16_t
>(value.length());
1168 std::copy(value.begin(), value.end(),
1169 reinterpret_cast<char*
>(&message[descriptor.offset +
sizeof(std::uint16_t)]));
1173 throwInvalidType(
"std::string_view", descriptor.adjustedType);
1176 *
reinterpret_cast<std::int16_t*
>(&message[descriptor.nullOffset]) = FB_FALSE;
1182 void setBlobId(
unsigned index, std::optional<BlobId> optValue)
1184 if (!optValue.has_value())
1192 const auto& value = optValue.value();
1193 const auto& descriptor = getInDescriptor(index);
1194 auto*
const message = inMessage.data();
1196 switch (descriptor.adjustedType)
1198 case DescriptorAdjustedType::BLOB:
1199 *
reinterpret_cast<ISC_QUAD*
>(&message[descriptor.offset]) = value.id;
1203 throwInvalidType(
"BlobId", descriptor.adjustedType);
1206 *
reinterpret_cast<std::int16_t*
>(&message[descriptor.nullOffset]) = FB_FALSE;
1211 void set(
unsigned index, std::nullopt_t)
1227 void set(
unsigned index, std::optional<BlobId> value)
1235 void set(
unsigned index,
bool value)
1243 void set(
unsigned index, std::int16_t value)
1259 void set(
unsigned index, std::int32_t value)
1275 void set(
unsigned index, std::int64_t value)
1296#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
1317 void set(
unsigned index,
float value)
1325 void set(
unsigned index,
double value)
1338#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
1356#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
1449 void set(
unsigned index, std::string_view value)
1457 template <
typename T>
1458 void set(
unsigned index, std::optional<T> value)
1460 if (value.has_value())
1461 set(index, value.value());
1481 const auto& descriptor = getOutDescriptor(index);
1482 const auto*
const message = outMessage.data();
1484 return *
reinterpret_cast<const std::int16_t*
>(&message[descriptor.nullOffset]) != FB_FALSE;
1494 const auto& descriptor = getOutDescriptor(index);
1495 const auto*
const message = outMessage.data();
1497 if (*
reinterpret_cast<const std::int16_t*
>(&message[descriptor.nullOffset]) != FB_FALSE)
1498 return std::nullopt;
1500 switch (descriptor.adjustedType)
1502 case DescriptorAdjustedType::BOOLEAN:
1503 return message[descriptor.offset] != std::byte{0};
1506 throwInvalidType(
"bool", descriptor.adjustedType);
1515 std::optional<int> scale{0};
1516 return getNumber<std::int16_t>(index, scale,
"std::int16_t");
1524 std::optional<int> scale;
1525 const auto value = getNumber<std::int16_t>(index, scale,
"ScaledInt16");
1526 return value.has_value() ? std::optional{
ScaledInt16{value.
value(), scale.value()}} : std::nullopt;
1534 std::optional<int> scale{0};
1535 return getNumber<std::int32_t>(index, scale,
"std::int32_t");
1543 std::optional<int> scale;
1544 const auto value = getNumber<std::int32_t>(index, scale,
"ScaledInt32");
1545 return value.has_value() ? std::optional{
ScaledInt32{value.
value(), scale.value()}} : std::nullopt;
1553 std::optional<int> scale{0};
1554 return getNumber<std::int64_t>(index, scale,
"std::int64_t");
1562 std::optional<int> scale;
1563 const auto value = getNumber<std::int64_t>(index, scale,
"ScaledInt64");
1564 return value.has_value() ? std::optional{
ScaledInt64{value.
value(), scale.value()}} : std::nullopt;
1574 const auto& descriptor = getOutDescriptor(index);
1575 const auto*
const message = outMessage.data();
1577 if (*
reinterpret_cast<const std::int16_t*
>(&message[descriptor.nullOffset]) != FB_FALSE)
1578 return std::nullopt;
1580 switch (descriptor.adjustedType)
1582 case DescriptorAdjustedType::INT128:
1588 throwInvalidType(
"OpaqueInt128", descriptor.adjustedType);
1592#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
1598 std::optional<int> scale{0};
1599 const auto value = getNumber<BoostInt128>(index, scale,
"BoostInt128");
1600 return value.has_value() ? std::optional{value.value()} : std::nullopt;
1608 std::optional<int> scale;
1609 const auto value = getNumber<BoostInt128>(index, scale,
"ScaledBoostInt128");
1610 return value.has_value() ? std::optional{
ScaledBoostInt128{value.
value(), scale.value()}} : std::nullopt;
1619 std::optional<int> scale{0};
1620 return getNumber<float>(index, scale,
"float");
1628 std::optional<int> scale{0};
1629 return getNumber<double>(index, scale,
"double");
1639 const auto& descriptor = getOutDescriptor(index);
1640 const auto*
const message = outMessage.data();
1642 if (*
reinterpret_cast<const std::int16_t*
>(&message[descriptor.nullOffset]) != FB_FALSE)
1643 return std::nullopt;
1645 switch (descriptor.adjustedType)
1647 case DescriptorAdjustedType::DECFLOAT16:
1651 throwInvalidType(
"OpaqueDecFloat16", descriptor.adjustedType);
1655#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
1661 std::optional<int> scale{0};
1662 return getNumber<BoostDecFloat16>(index, scale,
"BoostDecFloat16");
1673 const auto& descriptor = getOutDescriptor(index);
1674 const auto*
const message = outMessage.data();
1676 if (*
reinterpret_cast<const std::int16_t*
>(&message[descriptor.nullOffset]) != FB_FALSE)
1677 return std::nullopt;
1679 switch (descriptor.adjustedType)
1681 case DescriptorAdjustedType::DECFLOAT34:
1685 throwInvalidType(
"OpaqueDecFloat34", descriptor.adjustedType);
1689#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
1695 std::optional<int> scale{0};
1696 return getNumber<BoostDecFloat34>(index, scale,
"BoostDecFloat34");
1707 const auto& descriptor = getOutDescriptor(index);
1708 const auto*
const message = outMessage.data();
1710 if (*
reinterpret_cast<const std::int16_t*
>(&message[descriptor.nullOffset]) != FB_FALSE)
1711 return std::nullopt;
1713 switch (descriptor.adjustedType)
1715 case DescriptorAdjustedType::DATE:
1716 return calendarConverter.opaqueDateToDate(
1717 *
reinterpret_cast<const OpaqueDate*
>(&message[descriptor.offset]));
1720 throwInvalidType(
"Date", descriptor.adjustedType);
1731 const auto& descriptor = getOutDescriptor(index);
1732 const auto*
const message = outMessage.data();
1734 if (*
reinterpret_cast<const std::int16_t*
>(&message[descriptor.nullOffset]) != FB_FALSE)
1735 return std::nullopt;
1737 switch (descriptor.adjustedType)
1739 case DescriptorAdjustedType::DATE:
1743 throwInvalidType(
"OpaqueDate", descriptor.adjustedType);
1754 const auto& descriptor = getOutDescriptor(index);
1755 const auto*
const message = outMessage.data();
1757 if (*
reinterpret_cast<const std::int16_t*
>(&message[descriptor.nullOffset]) != FB_FALSE)
1758 return std::nullopt;
1760 switch (descriptor.adjustedType)
1762 case DescriptorAdjustedType::TIME:
1763 return calendarConverter.opaqueTimeToTime(
1764 *
reinterpret_cast<const OpaqueTime*
>(&message[descriptor.offset]));
1767 throwInvalidType(
"Time", descriptor.adjustedType);
1778 const auto& descriptor = getOutDescriptor(index);
1779 const auto*
const message = outMessage.data();
1781 if (*
reinterpret_cast<const std::int16_t*
>(&message[descriptor.nullOffset]) != FB_FALSE)
1782 return std::nullopt;
1784 switch (descriptor.adjustedType)
1786 case DescriptorAdjustedType::TIME:
1790 throwInvalidType(
"OpaqueTime", descriptor.adjustedType);
1801 const auto& descriptor = getOutDescriptor(index);
1802 const auto*
const message = outMessage.data();
1804 if (*
reinterpret_cast<const std::int16_t*
>(&message[descriptor.nullOffset]) != FB_FALSE)
1805 return std::nullopt;
1807 switch (descriptor.adjustedType)
1809 case DescriptorAdjustedType::TIMESTAMP:
1810 return calendarConverter.opaqueTimestampToTimestamp(
1811 *
reinterpret_cast<const OpaqueTimestamp*
>(&message[descriptor.offset]));
1814 throwInvalidType(
"Timestamp", descriptor.adjustedType);
1825 const auto& descriptor = getOutDescriptor(index);
1826 const auto*
const message = outMessage.data();
1828 if (*
reinterpret_cast<const std::int16_t*
>(&message[descriptor.nullOffset]) != FB_FALSE)
1829 return std::nullopt;
1831 switch (descriptor.adjustedType)
1833 case DescriptorAdjustedType::TIMESTAMP:
1837 throwInvalidType(
"OpaqueTimestamp", descriptor.adjustedType);
1848 const auto& descriptor = getOutDescriptor(index);
1849 const auto*
const message = outMessage.data();
1851 if (*
reinterpret_cast<const std::int16_t*
>(&message[descriptor.nullOffset]) != FB_FALSE)
1852 return std::nullopt;
1854 switch (descriptor.adjustedType)
1856 case DescriptorAdjustedType::TIME_TZ:
1857 return calendarConverter.opaqueTimeTzToTimeTz(
1858 *
reinterpret_cast<const OpaqueTimeTz*
>(&message[descriptor.offset]));
1861 throwInvalidType(
"TimeTz", descriptor.adjustedType);
1872 const auto& descriptor = getOutDescriptor(index);
1873 const auto*
const message = outMessage.data();
1875 if (*
reinterpret_cast<const std::int16_t*
>(&message[descriptor.nullOffset]) != FB_FALSE)
1876 return std::nullopt;
1878 switch (descriptor.adjustedType)
1880 case DescriptorAdjustedType::TIME_TZ:
1884 throwInvalidType(
"OpaqueTimeTz", descriptor.adjustedType);
1895 const auto& descriptor = getOutDescriptor(index);
1896 const auto*
const message = outMessage.data();
1898 if (*
reinterpret_cast<const std::int16_t*
>(&message[descriptor.nullOffset]) != FB_FALSE)
1899 return std::nullopt;
1901 switch (descriptor.adjustedType)
1903 case DescriptorAdjustedType::TIMESTAMP_TZ:
1904 return calendarConverter.opaqueTimestampTzToTimestampTz(
1908 throwInvalidType(
"TimestampTz", descriptor.adjustedType);
1919 const auto& descriptor = getOutDescriptor(index);
1920 const auto*
const message = outMessage.data();
1922 if (*
reinterpret_cast<const std::int16_t*
>(&message[descriptor.nullOffset]) != FB_FALSE)
1923 return std::nullopt;
1925 switch (descriptor.adjustedType)
1927 case DescriptorAdjustedType::TIMESTAMP_TZ:
1931 throwInvalidType(
"OpaqueTimestampTz", descriptor.adjustedType);
1942 const auto& descriptor = getOutDescriptor(index);
1943 const auto*
const message = outMessage.data();
1945 if (*
reinterpret_cast<const std::int16_t*
>(&message[descriptor.nullOffset]) != FB_FALSE)
1946 return std::nullopt;
1948 switch (descriptor.adjustedType)
1950 case DescriptorAdjustedType::BLOB:
1953 value.
id = *
reinterpret_cast<const ISC_QUAD*
>(&message[descriptor.offset]);
1958 throwInvalidType(
"BlobId", descriptor.adjustedType);
1969 const auto& descriptor = getOutDescriptor(index);
1970 const auto*
const message = outMessage.data();
1972 if (*
reinterpret_cast<const std::int16_t*
>(&message[descriptor.nullOffset]) != FB_FALSE)
1973 return std::nullopt;
1975 const auto data = &message[descriptor.offset];
1977 switch (descriptor.adjustedType)
1979 case DescriptorAdjustedType::BOOLEAN:
1980 return (message[descriptor.offset] != std::byte{0}) ? std::string{
"true"} : std::string{
"false"};
1982 case DescriptorAdjustedType::INT16:
1983 return numericConverter.numberToString(
1984 ScaledInt16{*
reinterpret_cast<const std::int16_t*
>(data), descriptor.
scale});
1986 case DescriptorAdjustedType::INT32:
1987 return numericConverter.numberToString(
1988 ScaledInt32{*
reinterpret_cast<const std::int32_t*
>(data), descriptor.
scale});
1990 case DescriptorAdjustedType::INT64:
1991 return numericConverter.numberToString(
1992 ScaledInt64{*
reinterpret_cast<const std::int64_t*
>(data), descriptor.
scale});
1994 case DescriptorAdjustedType::INT128:
1995 return numericConverter.opaqueInt128ToString(
1996 *
reinterpret_cast<const OpaqueInt128*
>(data), descriptor.scale);
1998 case DescriptorAdjustedType::FLOAT:
1999 return numericConverter.numberToString(*
reinterpret_cast<const float*
>(data));
2001 case DescriptorAdjustedType::DOUBLE:
2002 return numericConverter.numberToString(*
reinterpret_cast<const double*
>(data));
2004 case DescriptorAdjustedType::DATE:
2005 return calendarConverter.opaqueDateToString(*
reinterpret_cast<const OpaqueDate*
>(data));
2007 case DescriptorAdjustedType::TIME:
2008 return calendarConverter.opaqueTimeToString(*
reinterpret_cast<const OpaqueTime*
>(data));
2010 case DescriptorAdjustedType::TIMESTAMP:
2011 return calendarConverter.opaqueTimestampToString(*
reinterpret_cast<const OpaqueTimestamp*
>(data));
2013 case DescriptorAdjustedType::TIME_TZ:
2014 return calendarConverter.opaqueTimeTzToString(*
reinterpret_cast<const OpaqueTimeTz*
>(data));
2016 case DescriptorAdjustedType::TIMESTAMP_TZ:
2017 return calendarConverter.opaqueTimestampTzToString(
2020 case DescriptorAdjustedType::DECFLOAT16:
2021 return numericConverter.opaqueDecFloat16ToString(*
reinterpret_cast<const OpaqueDecFloat16*
>(data));
2023 case DescriptorAdjustedType::DECFLOAT34:
2024 return numericConverter.opaqueDecFloat34ToString(*
reinterpret_cast<const OpaqueDecFloat34*
>(data));
2026 case DescriptorAdjustedType::STRING:
2027 return std::string{
reinterpret_cast<const char*
>(data +
sizeof(std::uint16_t)),
2028 *
reinterpret_cast<const std::uint16_t*
>(data)};
2031 throwInvalidType(
"std::string", descriptor.adjustedType);
2042 template <
typename T>
2049 const Descriptor& getInDescriptor(
unsigned index)
2051 if (index >= inDescriptors.size())
2052 throw std::out_of_range(
"index out of range");
2054 return inDescriptors[index];
2060 const Descriptor& getOutDescriptor(
unsigned index)
2062 if (index >= outDescriptors.size())
2063 throw std::out_of_range(
"index out of range");
2065 return outDescriptors[index];
2071 template <
typename T>
2072 void setNumber(
unsigned index,
DescriptorAdjustedType valueType, T value,
int scale,
const char* typeName)
2076 const auto& descriptor = getInDescriptor(index);
2077 auto*
const message = inMessage.data();
2079 const auto descriptorData = &message[descriptor.offset];
2080 std::optional<int> descriptorScale{descriptor.scale};
2082 Descriptor valueDescriptor;
2083 valueDescriptor.adjustedType = valueType;
2084 valueDescriptor.scale = scale;
2086 const auto valueAddress =
reinterpret_cast<const std::byte*
>(&value);
2088 switch (descriptor.adjustedType)
2090 case DescriptorAdjustedType::INT16:
2091 *
reinterpret_cast<std::int16_t*
>(descriptorData) =
2092 convertNumber<std::int16_t>(valueDescriptor, valueAddress, descriptorScale,
"std::int16_t");
2095 case DescriptorAdjustedType::INT32:
2096 *
reinterpret_cast<std::int32_t*
>(descriptorData) =
2097 convertNumber<std::int32_t>(valueDescriptor, valueAddress, descriptorScale,
"std::int32_t");
2100 case DescriptorAdjustedType::INT64:
2101 *
reinterpret_cast<std::int64_t*
>(descriptorData) =
2102 convertNumber<std::int64_t>(valueDescriptor, valueAddress, descriptorScale,
"std::int64_t");
2105#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
2106 case DescriptorAdjustedType::INT128:
2108 const auto boostInt128 =
2109 convertNumber<BoostInt128>(valueDescriptor, valueAddress, descriptorScale,
"BoostInt128");
2111 numericConverter.boostInt128ToOpaqueInt128(boostInt128);
2116 case DescriptorAdjustedType::FLOAT:
2117 *
reinterpret_cast<float*
>(descriptorData) =
2118 convertNumber<float>(valueDescriptor, valueAddress, descriptorScale,
"float");
2121 case DescriptorAdjustedType::DOUBLE:
2122 *
reinterpret_cast<double*
>(descriptorData) =
2123 convertNumber<double>(valueDescriptor, valueAddress, descriptorScale,
"double");
2126#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
2127 case DescriptorAdjustedType::DECFLOAT16:
2129 const auto boostDecFloat16 = convertNumber<BoostDecFloat16>(
2130 valueDescriptor, valueAddress, descriptorScale,
"BoostDecFloat16");
2132 numericConverter.boostDecFloat16ToOpaqueDecFloat16(boostDecFloat16);
2136 case DescriptorAdjustedType::DECFLOAT34:
2138 const auto boostDecFloat34 = convertNumber<BoostDecFloat34>(
2139 valueDescriptor, valueAddress, descriptorScale,
"BoostDecFloat34");
2141 numericConverter.boostDecFloat34ToOpaqueDecFloat34(boostDecFloat34);
2147 throwInvalidType(typeName, descriptor.adjustedType);
2150 *
reinterpret_cast<std::int16_t*
>(&message[descriptor.nullOffset]) = FB_FALSE;
2157 template <
typename T>
2158 std::optional<T> getNumber(
unsigned index, std::optional<int>& scale,
const char* typeName)
2162 const auto& descriptor = getOutDescriptor(index);
2163 const auto*
const message = outMessage.data();
2165 if (*
reinterpret_cast<const std::int16_t*
>(&message[descriptor.nullOffset]) != FB_FALSE)
2166 return std::nullopt;
2168 auto data = &message[descriptor.offset];
2169#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
2170 std::optional<BoostInt128> boostInt128;
2171 std::optional<BoostDecFloat16> boostDecFloat16;
2172 std::optional<BoostDecFloat34> boostDecFloat34;
2176 switch (descriptor.adjustedType)
2178#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
2179 case DescriptorAdjustedType::INT128:
2180 boostInt128.emplace(
2181 numericConverter.opaqueInt128ToBoostInt128(*
reinterpret_cast<const OpaqueInt128*
>(data)));
2182 data =
reinterpret_cast<const std::byte*
>(&boostInt128.value());
2185 case DescriptorAdjustedType::DECFLOAT16:
2186 boostDecFloat16.emplace(numericConverter.opaqueDecFloat16ToBoostDecFloat16(
2188 data =
reinterpret_cast<const std::byte*
>(&boostDecFloat16.value());
2191 case DescriptorAdjustedType::DECFLOAT34:
2192 boostDecFloat34.emplace(numericConverter.opaqueDecFloat34ToBoostDecFloat34(
2194 data =
reinterpret_cast<const std::byte*
>(&boostDecFloat34.value());
2202 return convertNumber<T>(descriptor, data, scale, typeName);
2207 throw FbCppException(
"Invalid type: actual type " + std::string(actualType) +
", descriptor type " +
2208 std::to_string(
static_cast<unsigned>(descriptorType)));
2211 template <
typename T>
2213 const Descriptor& descriptor,
const std::byte* data, std::optional<int>& toScale,
const char* toTypeName)
2215 if (!toScale.has_value())
2217 switch (descriptor.adjustedType)
2219 case DescriptorAdjustedType::DECFLOAT16:
2220 case DescriptorAdjustedType::DECFLOAT34:
2221 case DescriptorAdjustedType::FLOAT:
2222 case DescriptorAdjustedType::DOUBLE:
2223 throwInvalidType(toTypeName, descriptor.adjustedType);
2229 toScale = descriptor.scale;
2232 switch (descriptor.adjustedType)
2234 case DescriptorAdjustedType::INT16:
2235 return numericConverter.numberToNumber<T>(
2236 ScaledInt16{*
reinterpret_cast<const std::int16_t*
>(data), descriptor.scale}, toScale.value());
2239 case DescriptorAdjustedType::INT32:
2240 return numericConverter.numberToNumber<T>(
2241 ScaledInt32{*
reinterpret_cast<const std::int32_t*
>(data), descriptor.scale}, toScale.value());
2243 case DescriptorAdjustedType::INT64:
2244 return numericConverter.numberToNumber<T>(
2245 ScaledInt64{*
reinterpret_cast<const std::int64_t*
>(data), descriptor.scale}, toScale.value());
2247#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
2248 case DescriptorAdjustedType::INT128:
2249 return numericConverter.numberToNumber<T>(
2253 case DescriptorAdjustedType::DECFLOAT16:
2254 return numericConverter.numberToNumber<T>(
2257 case DescriptorAdjustedType::DECFLOAT34:
2258 return numericConverter.numberToNumber<T>(
2262 case DescriptorAdjustedType::FLOAT:
2263 return numericConverter.numberToNumber<T>(*
reinterpret_cast<const float*
>(data), toScale.value());
2266 case DescriptorAdjustedType::DOUBLE:
2267 return numericConverter.numberToNumber<T>(*
reinterpret_cast<const double*
>(data), toScale.value());
2271 throwInvalidType(toTypeName, descriptor.adjustedType);
2276 Attachment& attachment;
2277 FbUniquePtr<Firebird::IStatus> status;
2278 impl::StatusWrapper statusWrapper;
2279 impl::CalendarConverter calendarConverter;
2280 impl::NumericConverter numericConverter;
2281 FbRef<fb::IStatement> statementHandle;
2282 FbRef<fb::IResultSet> resultSetHandle;
2283 FbRef<fb::IMessageMetadata> inMetadata;
2284 std::vector<Descriptor> inDescriptors;
2285 std::vector<std::byte> inMessage;
2286 FbRef<fb::IMessageMetadata> outMetadata;
2287 std::vector<Descriptor> outDescriptors;
2288 std::vector<std::byte> outMessage;
2298 inline std::optional<bool> Statement::get<std::optional<bool>>(
unsigned index)
2300 return getBool(index);
2304 inline std::optional<BlobId> Statement::get<std::optional<BlobId>>(
unsigned index)
2306 return getBlobId(index);
2310 inline std::optional<std::int16_t> Statement::get<std::optional<std::int16_t>>(
unsigned index)
2312 return getInt16(index);
2316 inline std::optional<ScaledInt16> Statement::get<std::optional<ScaledInt16>>(
unsigned index)
2318 return getScaledInt16(index);
2322 inline std::optional<std::int32_t> Statement::get<std::optional<std::int32_t>>(
unsigned index)
2324 return getInt32(index);
2328 inline std::optional<ScaledInt32> Statement::get<std::optional<ScaledInt32>>(
unsigned index)
2330 return getScaledInt32(index);
2334 inline std::optional<std::int64_t> Statement::get<std::optional<std::int64_t>>(
unsigned index)
2336 return getInt64(index);
2340 inline std::optional<ScaledInt64> Statement::get<std::optional<ScaledInt64>>(
unsigned index)
2342 return getScaledInt64(index);
2346 inline std::optional<ScaledOpaqueInt128> Statement::get<std::optional<ScaledOpaqueInt128>>(
unsigned index)
2348 return getScaledOpaqueInt128(index);
2351#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
2353 inline std::optional<BoostInt128> Statement::get<std::optional<BoostInt128>>(
unsigned index)
2355 return getBoostInt128(index);
2359 inline std::optional<ScaledBoostInt128> Statement::get<std::optional<ScaledBoostInt128>>(
unsigned index)
2361 return getScaledBoostInt128(index);
2366 inline std::optional<float> Statement::get<std::optional<float>>(
unsigned index)
2368 return getFloat(index);
2372 inline std::optional<double> Statement::get<std::optional<double>>(
unsigned index)
2374 return getDouble(index);
2378 inline std::optional<OpaqueDecFloat16> Statement::get<std::optional<OpaqueDecFloat16>>(
unsigned index)
2380 return getOpaqueDecFloat16(index);
2383#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
2385 inline std::optional<BoostDecFloat16> Statement::get<std::optional<BoostDecFloat16>>(
unsigned index)
2387 return getBoostDecFloat16(index);
2392 inline std::optional<OpaqueDecFloat34> Statement::get<std::optional<OpaqueDecFloat34>>(
unsigned index)
2394 return getOpaqueDecFloat34(index);
2397#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
2399 inline std::optional<BoostDecFloat34> Statement::get<std::optional<BoostDecFloat34>>(
unsigned index)
2401 return getBoostDecFloat34(index);
2406 inline std::optional<Date> Statement::get<std::optional<Date>>(
unsigned index)
2408 return getDate(index);
2412 inline std::optional<OpaqueDate> Statement::get<std::optional<OpaqueDate>>(
unsigned index)
2414 return getOpaqueDate(index);
2418 inline std::optional<Time> Statement::get<std::optional<Time>>(
unsigned index)
2420 return getTime(index);
2424 inline std::optional<OpaqueTime> Statement::get<std::optional<OpaqueTime>>(
unsigned index)
2426 return getOpaqueTime(index);
2430 inline std::optional<OpaqueTimestamp> Statement::get<std::optional<OpaqueTimestamp>>(
unsigned index)
2432 return getOpaqueTimestamp(index);
2436 inline std::optional<Timestamp> Statement::get<std::optional<Timestamp>>(
unsigned index)
2438 return getTimestamp(index);
2442 inline std::optional<TimeTz> Statement::get<std::optional<TimeTz>>(
unsigned index)
2444 return getTimeTz(index);
2448 inline std::optional<OpaqueTimeTz> Statement::get<std::optional<OpaqueTimeTz>>(
unsigned index)
2450 return getOpaqueTimeTz(index);
2454 inline std::optional<TimestampTz> Statement::get<std::optional<TimestampTz>>(
unsigned index)
2456 return getTimestampTz(index);
2460 inline std::optional<OpaqueTimestampTz> Statement::get<std::optional<OpaqueTimestampTz>>(
unsigned index)
2462 return getOpaqueTimestampTz(index);
2466 inline std::optional<std::string> Statement::get<std::optional<std::string>>(
unsigned index)
2468 return getString(index);
Represents a connection to a Firebird database.
Client & getClient() noexcept
Returns the Client object reference used to create this Attachment object.
Represents a Firebird blob identifier.
ISC_QUAD id
Stores the raw Firebird blob identifier value.
fb::IInt128 * getInt128Util(StatusType *status)
Returns a Firebird IInt128 interface.
Represents options used when preparing a Statement.
StatementOptions & setPrefetchLegacyPlan(bool value)
Enables or disables prefetching of the legacy textual plan at prepare time.
bool getPrefetchPlan() const
Reports whether the structured plan should be prefetched during prepare.
StatementOptions & setPrefetchPlan(bool value)
Enables or disables prefetching of the structured plan at prepare time.
bool getPrefetchLegacyPlan() const
Reports whether the legacy textual plan should be prefetched during prepare.
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.
bool fetchAbsolute(unsigned position)
Positions the cursor on the given absolute row number.
void setNull(unsigned index)
Marks the specified parameter as null.
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.
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.
void setDate(unsigned index, std::optional< Date > optValue)
Binds a date value or null.
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.
void free()
Releases the prepared handle and any associated result set.
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.
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.
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.
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.
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.
Statement(Statement &&o) noexcept
Transfers ownership of an existing prepared statement.
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 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 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 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.
~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.
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.
void set(unsigned index, BoostDecFloat34 value)
Convenience overload that binds a Boost 34-digit decimal floating-point value.
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.
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, 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.
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.
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.
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.
void set(unsigned index, ScaledInt32 value)
Convenience overload that binds a scaled 32-bit signed integer.
Statement(Attachment &attachment, Transaction &transaction, std::string_view sql, const StatementOptions &options={})
Prepares an SQL statement.
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.
void set(unsigned index, ScaledBoostInt128 value)
Convenience overload that binds a scaled Boost-provided 128-bit integer.
bool fetchFirst()
Positions the cursor on the first row.
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::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 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.
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.
Represents a transaction in a Firebird database.
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.
DescriptorAdjustedType
Descriptor adjusted type.
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.
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.
int scale
Decimal scale applied to value.
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.