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:
1047#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
1048 case DescriptorAdjustedType::INT128:
1051 std::string strValue(value);
1054 if (
const auto dotPos = strValue.find_last_of(
'.'); dotPos != std::string_view::npos)
1056 for (
auto pos = dotPos + 1; pos < strValue.size(); ++pos)
1058 const char c = value[pos];
1060 if (c <
'0' || c >
'9')
1066 strValue.erase(dotPos, 1);
1069#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
1070 const auto parseDecimalToBoostInt128 = [
this](std::string_view text)
1072 bool isNegative =
false;
1073 std::size_t pos = 0;
1075 if (!text.empty() && (text.front() ==
'+' || text.front() ==
'-'))
1077 isNegative = text.front() ==
'-';
1081 if (pos == text.size())
1082 this->numericConverter.throwConversionErrorFromString(std::string{text});
1086 for (; pos < text.size(); ++pos)
1088 const char c = text[pos];
1090 if (c <
'0' || c >
'9')
1091 this->numericConverter.throwConversionErrorFromString(std::string{text});
1094 result +=
static_cast<int>(c -
'0');
1097 return isNegative ? -result : result;
1100 auto scaledValue =
ScaledBoostInt128{parseDecimalToBoostInt128(strValue), scale};
1102 if (scale != descriptor.scale)
1104 scaledValue.
value = numericConverter.numberToNumber<
BoostInt128>(scaledValue, descriptor.scale);
1105 scaledValue.scale = descriptor.scale;
1110 static_assert(
sizeof(
long long) ==
sizeof(std::int64_t));
1111 std::int64_t intValue;
1112 const auto convResult =
1113 std::from_chars(strValue.data(), strValue.data() + strValue.size(), intValue);
1114 if (convResult.ec != std::errc{} || convResult.ptr != strValue.data() + strValue.size())
1115 numericConverter.throwConversionErrorFromString(strValue);
1118 if (scale != descriptor.scale)
1121 numericConverter.numberToNumber<std::int64_t>(scaledValue, descriptor.scale);
1122 scaledValue.scale = descriptor.scale;
1130 case DescriptorAdjustedType::FLOAT:
1131 case DescriptorAdjustedType::DOUBLE:
1134#if defined(__APPLE__)
1136 std::string valueString{value};
1137 char* parseEnd =
nullptr;
1138 doubleValue = std::strtod(valueString.c_str(), &parseEnd);
1139 if (parseEnd != valueString.c_str() + valueString.size() || errno == ERANGE)
1140 numericConverter.throwConversionErrorFromString(std::move(valueString));
1142 const auto convResult = std::from_chars(value.data(), value.data() + value.size(), doubleValue);
1143 if (convResult.ec != std::errc{} || convResult.ptr != value.data() + value.size())
1144 numericConverter.throwConversionErrorFromString(std::string{value});
1150 case DescriptorAdjustedType::DATE:
1151 *
reinterpret_cast<OpaqueDate*
>(&message[descriptor.offset]) =
1152 calendarConverter.stringToOpaqueDate(value);
1155 case DescriptorAdjustedType::TIME:
1156 *
reinterpret_cast<OpaqueTime*
>(&message[descriptor.offset]) =
1157 calendarConverter.stringToOpaqueTime(value);
1160 case DescriptorAdjustedType::TIMESTAMP:
1162 calendarConverter.stringToOpaqueTimestamp(value);
1165 case DescriptorAdjustedType::TIME_TZ:
1166 *
reinterpret_cast<OpaqueTimeTz*
>(&message[descriptor.offset]) =
1167 calendarConverter.stringToOpaqueTimeTz(value);
1170 case DescriptorAdjustedType::TIMESTAMP_TZ:
1172 calendarConverter.stringToOpaqueTimestampTz(value);
1174#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
1175 case DescriptorAdjustedType::DECFLOAT16:
1176 case DescriptorAdjustedType::DECFLOAT34:
1183 numericConverter.throwConversionErrorFromString(std::string{value});
1188 case DescriptorAdjustedType::STRING:
1189 if (value.length() > descriptor.length)
1191 static constexpr std::intptr_t STATUS_STRING_TRUNCATION[] = {
1193 isc_string_truncation,
1200 *
reinterpret_cast<std::uint16_t*
>(&message[descriptor.offset]) =
1201 static_cast<std::uint16_t
>(value.length());
1202 std::copy(value.begin(), value.end(),
1203 reinterpret_cast<char*
>(&message[descriptor.offset +
sizeof(std::uint16_t)]));
1207 throwInvalidType(
"std::string_view", descriptor.adjustedType);
1210 *
reinterpret_cast<std::int16_t*
>(&message[descriptor.nullOffset]) = FB_FALSE;
1216 void setBlobId(
unsigned index, std::optional<BlobId> optValue)
1218 if (!optValue.has_value())
1226 const auto& value = optValue.value();
1227 const auto& descriptor = getInDescriptor(index);
1228 auto*
const message = inMessage.data();
1230 switch (descriptor.adjustedType)
1232 case DescriptorAdjustedType::BLOB:
1233 *
reinterpret_cast<ISC_QUAD*
>(&message[descriptor.offset]) = value.id;
1237 throwInvalidType(
"BlobId", descriptor.adjustedType);
1240 *
reinterpret_cast<std::int16_t*
>(&message[descriptor.nullOffset]) = FB_FALSE;
1245 void set(
unsigned index, std::nullopt_t)
1255 setBlobId(index, value);
1261 void set(
unsigned index, std::optional<BlobId> value)
1263 setBlobId(index, value);
1269 void set(
unsigned index,
bool value)
1271 setBool(index, value);
1277 void set(
unsigned index, std::int16_t value)
1279 setInt16(index, value);
1287 setScaledInt16(index, value);
1293 void set(
unsigned index, std::int32_t value)
1295 setInt32(index, value);
1303 setScaledInt32(index, value);
1309 void set(
unsigned index, std::int64_t value)
1311 setInt64(index, value);
1319 setScaledInt64(index, value);
1327 setOpaqueInt128(index, value);
1330#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
1336 setBoostInt128(index, value);
1344 setScaledBoostInt128(index, value);
1351 void set(
unsigned index,
float value)
1353 setFloat(index, value);
1359 void set(
unsigned index,
double value)
1361 setDouble(index, value);
1369 setOpaqueDecFloat16(index, value);
1372#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
1378 setBoostDecFloat16(index, value);
1387 setOpaqueDecFloat34(index, value);
1390#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
1396 setBoostDecFloat34(index, value);
1405 setDate(index, value);
1413 setOpaqueDate(index, value);
1421 setTime(index, value);
1429 setOpaqueTime(index, value);
1437 setTimestamp(index, value);
1445 setOpaqueTimestamp(index, value);
1453 setTimeTz(index, value);
1461 setOpaqueTimeTz(index, value);
1469 setTimestampTz(index, value);
1477 setOpaqueTimestampTz(index, value);
1483 void set(
unsigned index, std::string_view value)
1485 setString(index, value);
1491 template <
typename T>
1492 void set(
unsigned index, std::optional<T> value)
1494 if (value.has_value())
1495 set(index, value.value());
1515 const auto& descriptor = getOutDescriptor(index);
1516 const auto*
const message = outMessage.data();
1518 return *
reinterpret_cast<const std::int16_t*
>(&message[descriptor.nullOffset]) != FB_FALSE;
1528 const auto& descriptor = getOutDescriptor(index);
1529 const auto*
const message = outMessage.data();
1531 if (*
reinterpret_cast<const std::int16_t*
>(&message[descriptor.nullOffset]) != FB_FALSE)
1532 return std::nullopt;
1534 switch (descriptor.adjustedType)
1536 case DescriptorAdjustedType::BOOLEAN:
1537 return message[descriptor.offset] != std::byte{0};
1540 throwInvalidType(
"bool", descriptor.adjustedType);
1549 std::optional<int> scale{0};
1550 return getNumber<std::int16_t>(index, scale,
"std::int16_t");
1558 std::optional<int> scale;
1559 const auto value = getNumber<std::int16_t>(index, scale,
"ScaledInt16");
1560 return value.has_value() ? std::optional{
ScaledInt16{value.
value(), scale.value()}} : std::nullopt;
1568 std::optional<int> scale{0};
1569 return getNumber<std::int32_t>(index, scale,
"std::int32_t");
1577 std::optional<int> scale;
1578 const auto value = getNumber<std::int32_t>(index, scale,
"ScaledInt32");
1579 return value.has_value() ? std::optional{
ScaledInt32{value.
value(), scale.value()}} : std::nullopt;
1587 std::optional<int> scale{0};
1588 return getNumber<std::int64_t>(index, scale,
"std::int64_t");
1596 std::optional<int> scale;
1597 const auto value = getNumber<std::int64_t>(index, scale,
"ScaledInt64");
1598 return value.has_value() ? std::optional{
ScaledInt64{value.
value(), scale.value()}} : std::nullopt;
1608 const auto& descriptor = getOutDescriptor(index);
1609 const auto*
const message = outMessage.data();
1611 if (*
reinterpret_cast<const std::int16_t*
>(&message[descriptor.nullOffset]) != FB_FALSE)
1612 return std::nullopt;
1614 switch (descriptor.adjustedType)
1616 case DescriptorAdjustedType::INT128:
1622 throwInvalidType(
"OpaqueInt128", descriptor.adjustedType);
1626#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
1632 std::optional<int> scale{0};
1633 const auto value = getNumber<BoostInt128>(index, scale,
"BoostInt128");
1634 return value.has_value() ? std::optional{value.value()} : std::nullopt;
1642 std::optional<int> scale;
1643 const auto value = getNumber<BoostInt128>(index, scale,
"ScaledBoostInt128");
1644 return value.has_value() ? std::optional{
ScaledBoostInt128{value.
value(), scale.value()}} : std::nullopt;
1653 std::optional<int> scale{0};
1654 return getNumber<float>(index, scale,
"float");
1662 std::optional<int> scale{0};
1663 return getNumber<double>(index, scale,
"double");
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::DECFLOAT16:
1685 throwInvalidType(
"OpaqueDecFloat16", descriptor.adjustedType);
1689#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
1695 std::optional<int> scale{0};
1696 return getNumber<BoostDecFloat16>(index, scale,
"BoostDecFloat16");
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::DECFLOAT34:
1719 throwInvalidType(
"OpaqueDecFloat34", descriptor.adjustedType);
1723#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
1729 std::optional<int> scale{0};
1730 return getNumber<BoostDecFloat34>(index, scale,
"BoostDecFloat34");
1741 const auto& descriptor = getOutDescriptor(index);
1742 const auto*
const message = outMessage.data();
1744 if (*
reinterpret_cast<const std::int16_t*
>(&message[descriptor.nullOffset]) != FB_FALSE)
1745 return std::nullopt;
1747 switch (descriptor.adjustedType)
1749 case DescriptorAdjustedType::DATE:
1750 return calendarConverter.opaqueDateToDate(
1751 *
reinterpret_cast<const OpaqueDate*
>(&message[descriptor.offset]));
1754 throwInvalidType(
"Date", descriptor.adjustedType);
1765 const auto& descriptor = getOutDescriptor(index);
1766 const auto*
const message = outMessage.data();
1768 if (*
reinterpret_cast<const std::int16_t*
>(&message[descriptor.nullOffset]) != FB_FALSE)
1769 return std::nullopt;
1771 switch (descriptor.adjustedType)
1773 case DescriptorAdjustedType::DATE:
1777 throwInvalidType(
"OpaqueDate", descriptor.adjustedType);
1788 const auto& descriptor = getOutDescriptor(index);
1789 const auto*
const message = outMessage.data();
1791 if (*
reinterpret_cast<const std::int16_t*
>(&message[descriptor.nullOffset]) != FB_FALSE)
1792 return std::nullopt;
1794 switch (descriptor.adjustedType)
1796 case DescriptorAdjustedType::TIME:
1797 return calendarConverter.opaqueTimeToTime(
1798 *
reinterpret_cast<const OpaqueTime*
>(&message[descriptor.offset]));
1801 throwInvalidType(
"Time", descriptor.adjustedType);
1812 const auto& descriptor = getOutDescriptor(index);
1813 const auto*
const message = outMessage.data();
1815 if (*
reinterpret_cast<const std::int16_t*
>(&message[descriptor.nullOffset]) != FB_FALSE)
1816 return std::nullopt;
1818 switch (descriptor.adjustedType)
1820 case DescriptorAdjustedType::TIME:
1824 throwInvalidType(
"OpaqueTime", descriptor.adjustedType);
1835 const auto& descriptor = getOutDescriptor(index);
1836 const auto*
const message = outMessage.data();
1838 if (*
reinterpret_cast<const std::int16_t*
>(&message[descriptor.nullOffset]) != FB_FALSE)
1839 return std::nullopt;
1841 switch (descriptor.adjustedType)
1843 case DescriptorAdjustedType::TIMESTAMP:
1844 return calendarConverter.opaqueTimestampToTimestamp(
1845 *
reinterpret_cast<const OpaqueTimestamp*
>(&message[descriptor.offset]));
1848 throwInvalidType(
"Timestamp", descriptor.adjustedType);
1859 const auto& descriptor = getOutDescriptor(index);
1860 const auto*
const message = outMessage.data();
1862 if (*
reinterpret_cast<const std::int16_t*
>(&message[descriptor.nullOffset]) != FB_FALSE)
1863 return std::nullopt;
1865 switch (descriptor.adjustedType)
1867 case DescriptorAdjustedType::TIMESTAMP:
1871 throwInvalidType(
"OpaqueTimestamp", descriptor.adjustedType);
1882 const auto& descriptor = getOutDescriptor(index);
1883 const auto*
const message = outMessage.data();
1885 if (*
reinterpret_cast<const std::int16_t*
>(&message[descriptor.nullOffset]) != FB_FALSE)
1886 return std::nullopt;
1888 switch (descriptor.adjustedType)
1890 case DescriptorAdjustedType::TIME_TZ:
1891 return calendarConverter.opaqueTimeTzToTimeTz(
1892 *
reinterpret_cast<const OpaqueTimeTz*
>(&message[descriptor.offset]));
1895 throwInvalidType(
"TimeTz", descriptor.adjustedType);
1906 const auto& descriptor = getOutDescriptor(index);
1907 const auto*
const message = outMessage.data();
1909 if (*
reinterpret_cast<const std::int16_t*
>(&message[descriptor.nullOffset]) != FB_FALSE)
1910 return std::nullopt;
1912 switch (descriptor.adjustedType)
1914 case DescriptorAdjustedType::TIME_TZ:
1918 throwInvalidType(
"OpaqueTimeTz", descriptor.adjustedType);
1929 const auto& descriptor = getOutDescriptor(index);
1930 const auto*
const message = outMessage.data();
1932 if (*
reinterpret_cast<const std::int16_t*
>(&message[descriptor.nullOffset]) != FB_FALSE)
1933 return std::nullopt;
1935 switch (descriptor.adjustedType)
1937 case DescriptorAdjustedType::TIMESTAMP_TZ:
1938 return calendarConverter.opaqueTimestampTzToTimestampTz(
1942 throwInvalidType(
"TimestampTz", descriptor.adjustedType);
1953 const auto& descriptor = getOutDescriptor(index);
1954 const auto*
const message = outMessage.data();
1956 if (*
reinterpret_cast<const std::int16_t*
>(&message[descriptor.nullOffset]) != FB_FALSE)
1957 return std::nullopt;
1959 switch (descriptor.adjustedType)
1961 case DescriptorAdjustedType::TIMESTAMP_TZ:
1965 throwInvalidType(
"OpaqueTimestampTz", descriptor.adjustedType);
1976 const auto& descriptor = getOutDescriptor(index);
1977 const auto*
const message = outMessage.data();
1979 if (*
reinterpret_cast<const std::int16_t*
>(&message[descriptor.nullOffset]) != FB_FALSE)
1980 return std::nullopt;
1982 switch (descriptor.adjustedType)
1984 case DescriptorAdjustedType::BLOB:
1987 value.
id = *
reinterpret_cast<const ISC_QUAD*
>(&message[descriptor.offset]);
1992 throwInvalidType(
"BlobId", descriptor.adjustedType);
2003 const auto& descriptor = getOutDescriptor(index);
2004 const auto*
const message = outMessage.data();
2006 if (*
reinterpret_cast<const std::int16_t*
>(&message[descriptor.nullOffset]) != FB_FALSE)
2007 return std::nullopt;
2009 const auto data = &message[descriptor.offset];
2011 switch (descriptor.adjustedType)
2013 case DescriptorAdjustedType::BOOLEAN:
2014 return (message[descriptor.offset] != std::byte{0}) ? std::string{
"true"} : std::string{
"false"};
2016 case DescriptorAdjustedType::INT16:
2017 return numericConverter.numberToString(
2018 ScaledInt16{*
reinterpret_cast<const std::int16_t*
>(data), descriptor.
scale});
2020 case DescriptorAdjustedType::INT32:
2021 return numericConverter.numberToString(
2022 ScaledInt32{*
reinterpret_cast<const std::int32_t*
>(data), descriptor.
scale});
2024 case DescriptorAdjustedType::INT64:
2025 return numericConverter.numberToString(
2026 ScaledInt64{*
reinterpret_cast<const std::int64_t*
>(data), descriptor.
scale});
2028#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
2029 case DescriptorAdjustedType::INT128:
2031 numericConverter.opaqueInt128ToBoostInt128(*
reinterpret_cast<const OpaqueInt128*
>(data)),
2035 case DescriptorAdjustedType::FLOAT:
2036 return numericConverter.numberToString(*
reinterpret_cast<const float*
>(data));
2038 case DescriptorAdjustedType::DOUBLE:
2039 return numericConverter.numberToString(*
reinterpret_cast<const double*
>(data));
2041 case DescriptorAdjustedType::DATE:
2042 return calendarConverter.opaqueDateToString(*
reinterpret_cast<const OpaqueDate*
>(data));
2044 case DescriptorAdjustedType::TIME:
2045 return calendarConverter.opaqueTimeToString(*
reinterpret_cast<const OpaqueTime*
>(data));
2047 case DescriptorAdjustedType::TIMESTAMP:
2048 return calendarConverter.opaqueTimestampToString(*
reinterpret_cast<const OpaqueTimestamp*
>(data));
2050 case DescriptorAdjustedType::TIME_TZ:
2051 return calendarConverter.opaqueTimeTzToString(*
reinterpret_cast<const OpaqueTimeTz*
>(data));
2053 case DescriptorAdjustedType::TIMESTAMP_TZ:
2054 return calendarConverter.opaqueTimestampTzToString(
2057#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
2058 case DescriptorAdjustedType::DECFLOAT16:
2059 return numericConverter.numberToString(numericConverter.opaqueDecFloat16ToBoostDecFloat16(
2062 case DescriptorAdjustedType::DECFLOAT34:
2063 return numericConverter.numberToString(numericConverter.opaqueDecFloat34ToBoostDecFloat34(
2067 case DescriptorAdjustedType::STRING:
2068 return std::string{
reinterpret_cast<const char*
>(data +
sizeof(std::uint16_t)),
2069 *
reinterpret_cast<const std::uint16_t*
>(data)};
2072 throwInvalidType(
"std::string", descriptor.adjustedType);
2083 template <
typename T>
2090 const Descriptor& getInDescriptor(
unsigned index)
2092 if (index >= inDescriptors.size())
2093 throw std::out_of_range(
"index out of range");
2095 return inDescriptors[index];
2101 const Descriptor& getOutDescriptor(
unsigned index)
2103 if (index >= outDescriptors.size())
2104 throw std::out_of_range(
"index out of range");
2106 return outDescriptors[index];
2112 template <
typename T>
2113 void setNumber(
unsigned index,
DescriptorAdjustedType valueType, T value,
int scale,
const char* typeName)
2117 const auto& descriptor = getInDescriptor(index);
2118 auto*
const message = inMessage.data();
2120 const auto descriptorData = &message[descriptor.offset];
2121 std::optional<int> descriptorScale{descriptor.scale};
2123 Descriptor valueDescriptor;
2124 valueDescriptor.adjustedType = valueType;
2125 valueDescriptor.scale = scale;
2127 const auto valueAddress =
reinterpret_cast<const std::byte*
>(&value);
2129 switch (descriptor.adjustedType)
2131 case DescriptorAdjustedType::INT16:
2132 *
reinterpret_cast<std::int16_t*
>(descriptorData) =
2133 convertNumber<std::int16_t>(valueDescriptor, valueAddress, descriptorScale,
"std::int16_t");
2136 case DescriptorAdjustedType::INT32:
2137 *
reinterpret_cast<std::int32_t*
>(descriptorData) =
2138 convertNumber<std::int32_t>(valueDescriptor, valueAddress, descriptorScale,
"std::int32_t");
2141 case DescriptorAdjustedType::INT64:
2142 *
reinterpret_cast<std::int64_t*
>(descriptorData) =
2143 convertNumber<std::int64_t>(valueDescriptor, valueAddress, descriptorScale,
"std::int64_t");
2146#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
2147 case DescriptorAdjustedType::INT128:
2149 const auto boostInt128 =
2150 convertNumber<BoostInt128>(valueDescriptor, valueAddress, descriptorScale,
"BoostInt128");
2152 numericConverter.boostInt128ToOpaqueInt128(boostInt128);
2157 case DescriptorAdjustedType::FLOAT:
2158 *
reinterpret_cast<float*
>(descriptorData) =
2159 convertNumber<float>(valueDescriptor, valueAddress, descriptorScale,
"float");
2162 case DescriptorAdjustedType::DOUBLE:
2163 *
reinterpret_cast<double*
>(descriptorData) =
2164 convertNumber<double>(valueDescriptor, valueAddress, descriptorScale,
"double");
2167#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
2168 case DescriptorAdjustedType::DECFLOAT16:
2170 const auto boostDecFloat16 = convertNumber<BoostDecFloat16>(
2171 valueDescriptor, valueAddress, descriptorScale,
"BoostDecFloat16");
2173 numericConverter.boostDecFloat16ToOpaqueDecFloat16(boostDecFloat16);
2177 case DescriptorAdjustedType::DECFLOAT34:
2179 const auto boostDecFloat34 = convertNumber<BoostDecFloat34>(
2180 valueDescriptor, valueAddress, descriptorScale,
"BoostDecFloat34");
2182 numericConverter.boostDecFloat34ToOpaqueDecFloat34(boostDecFloat34);
2188 throwInvalidType(typeName, descriptor.adjustedType);
2191 *
reinterpret_cast<std::int16_t*
>(&message[descriptor.nullOffset]) = FB_FALSE;
2198 template <
typename T>
2199 std::optional<T> getNumber(
unsigned index, std::optional<int>& scale,
const char* typeName)
2203 const auto& descriptor = getOutDescriptor(index);
2204 const auto*
const message = outMessage.data();
2206 if (*
reinterpret_cast<const std::int16_t*
>(&message[descriptor.nullOffset]) != FB_FALSE)
2207 return std::nullopt;
2209 auto data = &message[descriptor.offset];
2210#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
2211 std::optional<BoostInt128> boostInt128;
2212 std::optional<BoostDecFloat16> boostDecFloat16;
2213 std::optional<BoostDecFloat34> boostDecFloat34;
2216 switch (descriptor.adjustedType)
2218#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
2219 case DescriptorAdjustedType::INT128:
2220 boostInt128.emplace(
2221 numericConverter.opaqueInt128ToBoostInt128(*
reinterpret_cast<const OpaqueInt128*
>(data)));
2222 data =
reinterpret_cast<const std::byte*
>(&boostInt128.value());
2225 case DescriptorAdjustedType::DECFLOAT16:
2226 boostDecFloat16.emplace(numericConverter.opaqueDecFloat16ToBoostDecFloat16(
2228 data =
reinterpret_cast<const std::byte*
>(&boostDecFloat16.value());
2231 case DescriptorAdjustedType::DECFLOAT34:
2232 boostDecFloat34.emplace(numericConverter.opaqueDecFloat34ToBoostDecFloat34(
2234 data =
reinterpret_cast<const std::byte*
>(&boostDecFloat34.value());
2242 return convertNumber<T>(descriptor, data, scale, typeName);
2247 throw FbCppException(
"Invalid type: actual type " + std::string(actualType) +
", descriptor type " +
2248 std::to_string(
static_cast<unsigned>(descriptorType)));
2251 template <
typename T>
2253 const Descriptor& descriptor,
const std::byte* data, std::optional<int>& toScale,
const char* toTypeName)
2255 if (!toScale.has_value())
2257 switch (descriptor.adjustedType)
2259 case DescriptorAdjustedType::DECFLOAT16:
2260 case DescriptorAdjustedType::DECFLOAT34:
2261 case DescriptorAdjustedType::FLOAT:
2262 case DescriptorAdjustedType::DOUBLE:
2263 throwInvalidType(toTypeName, descriptor.adjustedType);
2269 toScale = descriptor.scale;
2272 switch (descriptor.adjustedType)
2274 case DescriptorAdjustedType::INT16:
2275 return numericConverter.numberToNumber<T>(
2276 ScaledInt16{*
reinterpret_cast<const std::int16_t*
>(data), descriptor.scale}, toScale.value());
2279 case DescriptorAdjustedType::INT32:
2280 return numericConverter.numberToNumber<T>(
2281 ScaledInt32{*
reinterpret_cast<const std::int32_t*
>(data), descriptor.scale}, toScale.value());
2283 case DescriptorAdjustedType::INT64:
2284 return numericConverter.numberToNumber<T>(
2285 ScaledInt64{*
reinterpret_cast<const std::int64_t*
>(data), descriptor.scale}, toScale.value());
2287#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
2288 case DescriptorAdjustedType::INT128:
2289 return numericConverter.numberToNumber<T>(
2293 case DescriptorAdjustedType::DECFLOAT16:
2294 return numericConverter.numberToNumber<T>(
2297 case DescriptorAdjustedType::DECFLOAT34:
2298 return numericConverter.numberToNumber<T>(
2302 case DescriptorAdjustedType::FLOAT:
2303 return numericConverter.numberToNumber<T>(*
reinterpret_cast<const float*
>(data), toScale.value());
2306 case DescriptorAdjustedType::DOUBLE:
2307 return numericConverter.numberToNumber<T>(*
reinterpret_cast<const double*
>(data), toScale.value());
2311 throwInvalidType(toTypeName, descriptor.adjustedType);
2316 Attachment& attachment;
2317 FbUniquePtr<Firebird::IStatus> status;
2318 impl::StatusWrapper statusWrapper;
2319 impl::CalendarConverter calendarConverter;
2320 impl::NumericConverter numericConverter;
2321 FbRef<fb::IStatement> statementHandle;
2322 FbRef<fb::IResultSet> resultSetHandle;
2323 FbRef<fb::IMessageMetadata> inMetadata;
2324 std::vector<Descriptor> inDescriptors;
2325 std::vector<std::byte> inMessage;
2326 FbRef<fb::IMessageMetadata> outMetadata;
2327 std::vector<Descriptor> outDescriptors;
2328 std::vector<std::byte> outMessage;
2338 inline std::optional<bool> Statement::get<std::optional<bool>>(
unsigned index)
2340 return getBool(index);
2344 inline std::optional<BlobId> Statement::get<std::optional<BlobId>>(
unsigned index)
2346 return getBlobId(index);
2350 inline std::optional<std::int16_t> Statement::get<std::optional<std::int16_t>>(
unsigned index)
2352 return getInt16(index);
2356 inline std::optional<ScaledInt16> Statement::get<std::optional<ScaledInt16>>(
unsigned index)
2358 return getScaledInt16(index);
2362 inline std::optional<std::int32_t> Statement::get<std::optional<std::int32_t>>(
unsigned index)
2364 return getInt32(index);
2368 inline std::optional<ScaledInt32> Statement::get<std::optional<ScaledInt32>>(
unsigned index)
2370 return getScaledInt32(index);
2374 inline std::optional<std::int64_t> Statement::get<std::optional<std::int64_t>>(
unsigned index)
2376 return getInt64(index);
2380 inline std::optional<ScaledInt64> Statement::get<std::optional<ScaledInt64>>(
unsigned index)
2382 return getScaledInt64(index);
2386 inline std::optional<ScaledOpaqueInt128> Statement::get<std::optional<ScaledOpaqueInt128>>(
unsigned index)
2388 return getScaledOpaqueInt128(index);
2391#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
2393 inline std::optional<BoostInt128> Statement::get<std::optional<BoostInt128>>(
unsigned index)
2395 return getBoostInt128(index);
2399 inline std::optional<ScaledBoostInt128> Statement::get<std::optional<ScaledBoostInt128>>(
unsigned index)
2401 return getScaledBoostInt128(index);
2406 inline std::optional<float> Statement::get<std::optional<float>>(
unsigned index)
2408 return getFloat(index);
2412 inline std::optional<double> Statement::get<std::optional<double>>(
unsigned index)
2414 return getDouble(index);
2418 inline std::optional<OpaqueDecFloat16> Statement::get<std::optional<OpaqueDecFloat16>>(
unsigned index)
2420 return getOpaqueDecFloat16(index);
2423#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
2425 inline std::optional<BoostDecFloat16> Statement::get<std::optional<BoostDecFloat16>>(
unsigned index)
2427 return getBoostDecFloat16(index);
2432 inline std::optional<OpaqueDecFloat34> Statement::get<std::optional<OpaqueDecFloat34>>(
unsigned index)
2434 return getOpaqueDecFloat34(index);
2437#if FB_CPP_USE_BOOST_MULTIPRECISION != 0
2439 inline std::optional<BoostDecFloat34> Statement::get<std::optional<BoostDecFloat34>>(
unsigned index)
2441 return getBoostDecFloat34(index);
2446 inline std::optional<Date> Statement::get<std::optional<Date>>(
unsigned index)
2448 return getDate(index);
2452 inline std::optional<OpaqueDate> Statement::get<std::optional<OpaqueDate>>(
unsigned index)
2454 return getOpaqueDate(index);
2458 inline std::optional<Time> Statement::get<std::optional<Time>>(
unsigned index)
2460 return getTime(index);
2464 inline std::optional<OpaqueTime> Statement::get<std::optional<OpaqueTime>>(
unsigned index)
2466 return getOpaqueTime(index);
2470 inline std::optional<OpaqueTimestamp> Statement::get<std::optional<OpaqueTimestamp>>(
unsigned index)
2472 return getOpaqueTimestamp(index);
2476 inline std::optional<Timestamp> Statement::get<std::optional<Timestamp>>(
unsigned index)
2478 return getTimestamp(index);
2482 inline std::optional<TimeTz> Statement::get<std::optional<TimeTz>>(
unsigned index)
2484 return getTimeTz(index);
2488 inline std::optional<OpaqueTimeTz> Statement::get<std::optional<OpaqueTimeTz>>(
unsigned index)
2490 return getOpaqueTimeTz(index);
2494 inline std::optional<TimestampTz> Statement::get<std::optional<TimestampTz>>(
unsigned index)
2496 return getTimestampTz(index);
2500 inline std::optional<OpaqueTimestampTz> Statement::get<std::optional<OpaqueTimestampTz>>(
unsigned index)
2502 return getOpaqueTimestampTz(index);
2506 inline std::optional<std::string> Statement::get<std::optional<std::string>>(
unsigned index)
2508 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.
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.