field.hxx 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  1. /* Definitions for the pqxx::field class.
  2. *
  3. * pqxx::field refers to a field in a query result.
  4. *
  5. * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/field instead.
  6. *
  7. * Copyright (c) 2000-2022, Jeroen T. Vermeulen.
  8. *
  9. * See COPYING for copyright license. If you did not receive a file called
  10. * COPYING with this source code, please notify the distributor of this
  11. * mistake, or contact the author.
  12. */
  13. #ifndef PQXX_H_FIELD
  14. #define PQXX_H_FIELD
  15. #if !defined(PQXX_HEADER_PRE)
  16. # error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
  17. #endif
  18. #include <optional>
  19. #include "pqxx/array.hxx"
  20. #include "pqxx/composite.hxx"
  21. #include "pqxx/result.hxx"
  22. #include "pqxx/strconv.hxx"
  23. #include "pqxx/types.hxx"
  24. namespace pqxx
  25. {
  26. /// Reference to a field in a result set.
  27. /** A field represents one entry in a row. It represents an actual value
  28. * in the result set, and can be converted to various types.
  29. */
  30. class PQXX_LIBEXPORT field
  31. {
  32. public:
  33. using size_type = field_size_type;
  34. /// Constructor. Do not call this yourself; libpqxx will do it for you.
  35. /** Create field as reference to a field in a result set.
  36. * @param r Row that this field is part of.
  37. * @param c Column number of this field.
  38. */
  39. [[deprecated(
  40. "Do not construct fields yourself. Get them from the row.")]] field(row const &r, row_size_type c) noexcept;
  41. /// Constructor. Do not call this yourself; libpqxx will do it for you.
  42. [[deprecated(
  43. "Do not construct fields yourself. Get them from the "
  44. "row.")]] field() noexcept = default;
  45. /**
  46. * @name Comparison
  47. */
  48. //@{
  49. // TODO: noexcept. Breaks ABI.
  50. /// Byte-by-byte comparison of two fields (all nulls are considered equal)
  51. /** @warning null handling is still open to discussion and change!
  52. *
  53. * Handling of null values differs from that in SQL where a comparison
  54. * involving a null value yields null, so nulls are never considered equal
  55. * to one another or even to themselves.
  56. *
  57. * Null handling also probably differs from the closest equivalent in C++,
  58. * which is the NaN (Not-a-Number) value, a singularity comparable to
  59. * SQL's null. This is because the builtin == operator demands that a == a.
  60. *
  61. * The usefulness of this operator is questionable. No interpretation
  62. * whatsoever is imposed on the data; 0 and 0.0 are considered different,
  63. * as are null vs. the empty string, or even different (but possibly
  64. * equivalent and equally valid) encodings of the same Unicode character
  65. * etc.
  66. */
  67. [[nodiscard]] PQXX_PURE bool operator==(field const &) const;
  68. /// Byte-by-byte comparison (all nulls are considered equal)
  69. /** @warning See operator==() for important information about this operator
  70. */
  71. [[nodiscard]] PQXX_PURE bool operator!=(field const &rhs) const noexcept
  72. {
  73. return not operator==(rhs);
  74. }
  75. //@}
  76. /**
  77. * @name Column information
  78. */
  79. //@{
  80. /// Column name.
  81. [[nodiscard]] PQXX_PURE char const *name() const &;
  82. /// Column type.
  83. [[nodiscard]] oid PQXX_PURE type() const;
  84. /// What table did this column come from?
  85. [[nodiscard]] PQXX_PURE oid table() const;
  86. /// Return row number. The first row is row 0, the second is row 1, etc.
  87. PQXX_PURE constexpr row_size_type num() const noexcept { return col(); }
  88. /// What column number in its originating table did this column come from?
  89. [[nodiscard]] PQXX_PURE row_size_type table_column() const;
  90. //@}
  91. /**
  92. * @name Content access
  93. */
  94. //@{
  95. /// Read as `string_view`, or an empty one if null.
  96. /** The result only remains usable while the data for the underlying
  97. * @ref result exists. Once all `result` objects referring to that data have
  98. * been destroyed, the `string_view` will no longer point to valid memory.
  99. */
  100. [[nodiscard]] PQXX_PURE std::string_view view() const &
  101. {
  102. return std::string_view(c_str(), size());
  103. }
  104. /// Read as plain C string.
  105. /** Since the field's data is stored internally in the form of a
  106. * zero-terminated C string, this is the fastest way to read it. Use the
  107. * to() or as() functions to convert the string to other types such as
  108. * `int`, or to C++ strings.
  109. *
  110. * Do not use this for BYTEA values, or other binary values. To read those,
  111. * convert the value to your desired type using `to()` or `as()`. For
  112. * example: `f.as<std::basic_string<std::byte>>()`.
  113. */
  114. [[nodiscard]] PQXX_PURE char const *c_str() const &;
  115. /// Is this field's value null?
  116. [[nodiscard]] PQXX_PURE bool is_null() const noexcept;
  117. /// Return number of bytes taken up by the field's value.
  118. [[nodiscard]] PQXX_PURE size_type size() const noexcept;
  119. /// Read value into obj; or if null, leave obj untouched and return `false`.
  120. /** This can be used with optional types (except pointers other than C-style
  121. * strings).
  122. */
  123. template<typename T>
  124. auto to(T &obj) const -> typename std::enable_if_t<
  125. (not std::is_pointer<T>::value or std::is_same<T, char const *>::value),
  126. bool>
  127. {
  128. if (is_null())
  129. {
  130. return false;
  131. }
  132. else
  133. {
  134. auto const bytes{c_str()};
  135. from_string(bytes, obj);
  136. return true;
  137. }
  138. }
  139. /// Read field as a composite value, write its components into `fields`.
  140. /** @warning This is still experimental. It may change or be replaced.
  141. *
  142. * Returns whether the field was null. If it was, it will not touch the
  143. * values in `fields`.
  144. */
  145. template<typename... T> bool composite_to(T &...fields) const
  146. {
  147. if (is_null())
  148. {
  149. return false;
  150. }
  151. else
  152. {
  153. parse_composite(m_home.m_encoding, view(), fields...);
  154. return true;
  155. }
  156. }
  157. /// Read value into obj; or leave obj untouched and return `false` if null.
  158. template<typename T> bool operator>>(T &obj) const { return to(obj); }
  159. /// Read value into obj; or if null, use default value and return `false`.
  160. /** This can be used with `std::optional`, as well as with standard smart
  161. * pointer types, but not with raw pointers. If the conversion from a
  162. * PostgreSQL string representation allocates a pointer (e.g. using `new`),
  163. * then the object's later deallocation should be baked in as well, right
  164. * from the point where the object is created. So if you want a pointer, use
  165. * a smart pointer, not a raw pointer.
  166. *
  167. * There is one exception, of course: C-style strings. Those are just
  168. * pointers to the field's internal text data.
  169. */
  170. template<typename T>
  171. auto to(T &obj, T const &default_value) const -> typename std::enable_if_t<
  172. (not std::is_pointer<T>::value or std::is_same<T, char const *>::value),
  173. bool>
  174. {
  175. bool const null{is_null()};
  176. if (null)
  177. obj = default_value;
  178. else
  179. obj = from_string<T>(this->view());
  180. return not null;
  181. }
  182. /// Return value as object of given type, or default value if null.
  183. /** Note that unless the function is instantiated with an explicit template
  184. * argument, the Default value's type also determines the result type.
  185. */
  186. template<typename T> T as(T const &default_value) const
  187. {
  188. if (is_null())
  189. return default_value;
  190. else
  191. return from_string<T>(this->view());
  192. }
  193. /// Return value as object of given type, or throw exception if null.
  194. /** Use as `as<std::optional<int>>()` or `as<my_untemplated_optional_t>()` as
  195. * an alternative to `get<int>()`; this is disabled for use with raw pointers
  196. * (other than C-strings) because storage for the value can't safely be
  197. * allocated here
  198. */
  199. template<typename T> T as() const
  200. {
  201. if (is_null())
  202. {
  203. if constexpr (not nullness<T>::has_null)
  204. internal::throw_null_conversion(type_name<T>);
  205. else
  206. return nullness<T>::null();
  207. }
  208. else
  209. {
  210. return from_string<T>(this->view());
  211. }
  212. }
  213. /// Return value wrapped in some optional type (empty for nulls).
  214. /** Use as `get<int>()` as before to obtain previous behavior, or specify
  215. * container type with `get<int, std::optional>()`
  216. */
  217. template<typename T, template<typename> class O = std::optional>
  218. constexpr O<T> get() const
  219. {
  220. return as<O<T>>();
  221. }
  222. // TODO: constexpr noexcept, once array_parser constructor gets those.
  223. /// Parse the field as an SQL array.
  224. /** Call the parser to retrieve values (and structure) from the array.
  225. *
  226. * Make sure the @ref result object stays alive until parsing is finished. If
  227. * you keep the @ref row of `field` object alive, it will keep the @ref
  228. * result object alive as well.
  229. */
  230. array_parser as_array() const &
  231. {
  232. return array_parser{c_str(), m_home.m_encoding};
  233. }
  234. //@}
  235. protected:
  236. constexpr result const &home() const noexcept { return m_home; }
  237. constexpr result::size_type idx() const noexcept { return m_row; }
  238. constexpr row_size_type col() const noexcept { return m_col; }
  239. // TODO: Create gates.
  240. friend class pqxx::result;
  241. friend class pqxx::row;
  242. field(
  243. result const &r, result_size_type row_num, row_size_type col_num) noexcept
  244. :
  245. m_col{col_num}, m_home{r}, m_row{row_num}
  246. {}
  247. /**
  248. * You'd expect this to be unsigned, but due to the way reverse iterators
  249. * are related to regular iterators, it must be allowed to underflow to -1.
  250. */
  251. row_size_type m_col;
  252. private:
  253. result m_home;
  254. result::size_type m_row;
  255. };
  256. template<> inline bool field::to<std::string>(std::string &obj) const
  257. {
  258. bool const null{is_null()};
  259. if (not null)
  260. obj = std::string{view()};
  261. return not null;
  262. }
  263. template<>
  264. inline bool field::to<std::string>(
  265. std::string &obj, std::string const &default_value) const
  266. {
  267. bool const null{is_null()};
  268. if (null)
  269. obj = default_value;
  270. else
  271. obj = std::string{view()};
  272. return not null;
  273. }
  274. /// Specialization: `to(char const *&)`.
  275. /** The buffer has the same lifetime as the data in this result (i.e. of this
  276. * result object, or the last remaining one copied from it etc.), so take care
  277. * not to use it after the last result object referring to this query result is
  278. * destroyed.
  279. */
  280. template<> inline bool field::to<char const *>(char const *&obj) const
  281. {
  282. bool const null{is_null()};
  283. if (not null)
  284. obj = c_str();
  285. return not null;
  286. }
  287. template<> inline bool field::to<std::string_view>(std::string_view &obj) const
  288. {
  289. bool const null{is_null()};
  290. if (not null)
  291. obj = view();
  292. return not null;
  293. }
  294. template<>
  295. inline bool field::to<std::string_view>(
  296. std::string_view &obj, std::string_view const &default_value) const
  297. {
  298. bool const null{is_null()};
  299. if (null)
  300. obj = default_value;
  301. else
  302. obj = view();
  303. return not null;
  304. }
  305. template<> inline std::string_view field::as<std::string_view>() const
  306. {
  307. if (is_null())
  308. PQXX_UNLIKELY
  309. internal::throw_null_conversion(type_name<std::string_view>);
  310. return view();
  311. }
  312. template<>
  313. inline std::string_view
  314. field::as<std::string_view>(std::string_view const &default_value) const
  315. {
  316. return is_null() ? default_value : view();
  317. }
  318. template<> inline bool field::to<zview>(zview &obj) const
  319. {
  320. bool const null{is_null()};
  321. if (not null)
  322. obj = zview{c_str(), size()};
  323. return not null;
  324. }
  325. template<>
  326. inline bool field::to<zview>(zview &obj, zview const &default_value) const
  327. {
  328. bool const null{is_null()};
  329. if (null)
  330. obj = default_value;
  331. else
  332. obj = zview{c_str(), size()};
  333. return not null;
  334. }
  335. template<> inline zview field::as<zview>() const
  336. {
  337. if (is_null())
  338. PQXX_UNLIKELY
  339. internal::throw_null_conversion(type_name<zview>);
  340. return zview{c_str(), size()};
  341. }
  342. template<> inline zview field::as<zview>(zview const &default_value) const
  343. {
  344. return is_null() ? default_value : zview{c_str(), size()};
  345. }
  346. template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
  347. class field_streambuf : public std::basic_streambuf<CHAR, TRAITS>
  348. {
  349. public:
  350. using char_type = CHAR;
  351. using traits_type = TRAITS;
  352. using int_type = typename traits_type::int_type;
  353. using pos_type = typename traits_type::pos_type;
  354. using off_type = typename traits_type::off_type;
  355. using openmode = std::ios::openmode;
  356. using seekdir = std::ios::seekdir;
  357. explicit field_streambuf(field const &f) : m_field{f} { initialize(); }
  358. protected:
  359. virtual int sync() override { return traits_type::eof(); }
  360. virtual pos_type seekoff(off_type, seekdir, openmode) override
  361. {
  362. return traits_type::eof();
  363. }
  364. virtual pos_type seekpos(pos_type, openmode) override
  365. {
  366. return traits_type::eof();
  367. }
  368. virtual int_type overflow(int_type) override { return traits_type::eof(); }
  369. virtual int_type underflow() override { return traits_type::eof(); }
  370. private:
  371. field const &m_field;
  372. int_type initialize()
  373. {
  374. auto g{static_cast<char_type *>(const_cast<char *>(m_field.c_str()))};
  375. this->setg(g, g, g + std::size(m_field));
  376. return int_type(std::size(m_field));
  377. }
  378. };
  379. /// Input stream that gets its data from a result field
  380. /** Use this class exactly as you would any other istream to read data from a
  381. * field. All formatting and streaming operations of `std::istream` are
  382. * supported. What you'll typically want to use, however, is the fieldstream
  383. * alias (which defines a @ref basic_fieldstream for `char`). This is similar
  384. * to how e.g. `std::ifstream` relates to `std::basic_ifstream`.
  385. *
  386. * This class has only been tested for the char type (and its default traits).
  387. */
  388. template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
  389. class basic_fieldstream : public std::basic_istream<CHAR, TRAITS>
  390. {
  391. using super = std::basic_istream<CHAR, TRAITS>;
  392. public:
  393. using char_type = CHAR;
  394. using traits_type = TRAITS;
  395. using int_type = typename traits_type::int_type;
  396. using pos_type = typename traits_type::pos_type;
  397. using off_type = typename traits_type::off_type;
  398. basic_fieldstream(field const &f) : super{nullptr}, m_buf{f}
  399. {
  400. super::init(&m_buf);
  401. }
  402. private:
  403. field_streambuf<CHAR, TRAITS> m_buf;
  404. };
  405. using fieldstream = basic_fieldstream<char>;
  406. /// Write a result field to any type of stream
  407. /** This can be convenient when writing a field to an output stream. More
  408. * importantly, it lets you write a field to e.g. a `stringstream` which you
  409. * can then use to read, format and convert the field in ways that to() does
  410. * not support.
  411. *
  412. * Example: parse a field into a variable of the nonstandard
  413. * "<tt>long long</tt>" type.
  414. *
  415. * ```cxx
  416. * extern result R;
  417. * long long L;
  418. * stringstream S;
  419. *
  420. * // Write field's string into S
  421. * S << R[0][0];
  422. *
  423. * // Parse contents of S into L
  424. * S >> L;
  425. * ```
  426. */
  427. template<typename CHAR>
  428. inline std::basic_ostream<CHAR> &
  429. operator<<(std::basic_ostream<CHAR> &s, field const &value)
  430. {
  431. s.write(value.c_str(), std::streamsize(std::size(value)));
  432. return s;
  433. }
  434. /// Convert a field's value to type `T`.
  435. /** Unlike the "regular" `from_string`, this knows how to deal with null
  436. * values.
  437. */
  438. template<typename T> inline T from_string(field const &value)
  439. {
  440. if (value.is_null())
  441. {
  442. if constexpr (nullness<T>::has_null)
  443. return nullness<T>::null();
  444. else
  445. internal::throw_null_conversion(type_name<T>);
  446. }
  447. else
  448. {
  449. return from_string<T>(value.view());
  450. }
  451. }
  452. /// Convert a field's value to `nullptr_t`.
  453. /** Yes, you read that right. This conversion does nothing useful. It always
  454. * returns `nullptr`.
  455. *
  456. * Except... what if the field is not null? In that case, this throws
  457. * @ref conversion_error.
  458. */
  459. template<>
  460. inline std::nullptr_t from_string<std::nullptr_t>(field const &value)
  461. {
  462. if (not value.is_null())
  463. throw conversion_error{
  464. "Extracting non-null field into nullptr_t variable."};
  465. return nullptr;
  466. }
  467. /// Convert a field to a string.
  468. template<> PQXX_LIBEXPORT std::string to_string(field const &value);
  469. } // namespace pqxx
  470. #endif