libpqxx
The C++ client library for PostgreSQL
field.hxx
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-2024, 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
16#if !defined(PQXX_HEADER_PRE)
17# error "Include libpqxx headers as <pqxx/header>, not <pqxx/header.hxx>."
18#endif
19
20#include <optional>
21
22#include "pqxx/array.hxx"
23#include "pqxx/composite.hxx"
24#include "pqxx/result.hxx"
25#include "pqxx/strconv.hxx"
26#include "pqxx/types.hxx"
27
28namespace pqxx
29{
31
34class PQXX_LIBEXPORT field
35{
36public:
37 using size_type = field_size_type;
38
44
60 [[nodiscard]] PQXX_PURE bool operator==(field const &) const noexcept;
61
63
65 [[nodiscard]] PQXX_PURE bool operator!=(field const &rhs) const noexcept
66 {
67 return not operator==(rhs);
68 }
70
76 [[nodiscard]] PQXX_PURE char const *name() const &;
77
79 [[nodiscard]] oid PQXX_PURE type() const;
80
82 [[nodiscard]] PQXX_PURE oid table() const;
83
85 PQXX_PURE constexpr row_size_type num() const noexcept { return col(); }
86
88 [[nodiscard]] PQXX_PURE row_size_type table_column() const;
90
107
111 [[nodiscard]] PQXX_PURE std::string_view view() const &
112 {
113 return std::string_view(c_str(), size());
114 }
115
117
126 [[nodiscard]] PQXX_PURE char const *c_str() const &;
127
129 [[nodiscard]] PQXX_PURE bool is_null() const noexcept;
130
132 [[nodiscard]] PQXX_PURE size_type size() const noexcept;
133
135
138 template<typename T>
139 auto to(T &obj) const ->
140 typename std::enable_if_t<
141 (not std::is_pointer<T>::value or std::is_same<T, char const *>::value),
142 bool>
143 {
144 if (is_null())
145 {
146 return false;
147 }
148 else
149 {
150 auto const data{c_str()};
151 from_string(data, obj);
152 return true;
153 }
154 }
155
157
162 template<typename... T> bool composite_to(T &...fields) const
163 {
164 if (is_null())
165 {
166 return false;
167 }
168 else
169 {
170 parse_composite(m_home.m_encoding, view(), fields...);
171 return true;
172 }
173 }
174
176 template<typename T> bool operator>>(T &obj) const { return to(obj); }
177
179
189 template<typename T>
190 auto to(T &obj, T const &default_value) const ->
191 typename std::enable_if_t<
192 (not std::is_pointer<T>::value or std::is_same<T, char const *>::value),
193 bool>
194 {
195 bool const null{is_null()};
196 if (null)
197 obj = default_value;
198 else
199 obj = from_string<T>(this->view());
200 return not null;
201 }
202
204
207 template<typename T> T as(T const &default_value) const
208 {
209 if (is_null())
210 return default_value;
211 else
212 return from_string<T>(this->view());
213 }
214
216
221 template<typename T> T as() const
222 {
223 if (is_null())
224 {
225 if constexpr (not nullness<T>::has_null)
227 else
228 return nullness<T>::null();
229 }
230 else
231 {
232 return from_string<T>(this->view());
233 }
234 }
235
237
240 template<typename T, template<typename> class O = std::optional>
241 constexpr O<T> get() const
242 {
243 return as<O<T>>();
244 }
245
247
253 array_parser as_array() const & noexcept
254 {
255 return array_parser{c_str(), m_home.m_encoding};
256 }
258
260
264 [[deprecated(
265 "Do not construct fields yourself. Get them from the row.")]] field(row const &r, row_size_type c) noexcept;
266
268 [[deprecated(
269 "Do not construct fields yourself. Get them from the "
270 "row.")]] field() noexcept = default;
271
272
273protected:
274 constexpr result const &home() const noexcept { return m_home; }
275 constexpr result::size_type idx() const noexcept { return m_row; }
276 constexpr row_size_type col() const noexcept { return m_col; }
277
278 // TODO: Create gates.
279 friend class pqxx::result;
280 friend class pqxx::row;
281 field(
282 result const &r, result_size_type row_num, row_size_type col_num) noexcept
283 :
284 m_col{col_num}, m_home{r}, m_row{row_num}
285 {}
286
292
293private:
294 result m_home;
295 result::size_type m_row;
296};
297
298
299template<> inline bool field::to<std::string>(std::string &obj) const
300{
301 bool const null{is_null()};
302 if (not null)
303 obj = std::string{view()};
304 return not null;
305}
306
307
308template<>
309inline bool field::to<std::string>(
310 std::string &obj, std::string const &default_value) const
311{
312 bool const null{is_null()};
313 if (null)
314 obj = default_value;
315 else
316 obj = std::string{view()};
317 return not null;
318}
319
320
322
327template<> inline bool field::to<char const *>(char const *&obj) const
328{
329 bool const null{is_null()};
330 if (not null)
331 obj = c_str();
332 return not null;
333}
334
335
336template<> inline bool field::to<std::string_view>(std::string_view &obj) const
337{
338 bool const null{is_null()};
339 if (not null)
340 obj = view();
341 return not null;
342}
343
344
345template<>
346inline bool field::to<std::string_view>(
347 std::string_view &obj, std::string_view const &default_value) const
348{
349 bool const null{is_null()};
350 if (null)
351 obj = default_value;
352 else
353 obj = view();
354 return not null;
355}
356
357
358template<> inline std::string_view field::as<std::string_view>() const
359{
360 if (is_null())
361 PQXX_UNLIKELY
362 internal::throw_null_conversion(type_name<std::string_view>);
363 return view();
364}
365
366
367template<>
368inline std::string_view
369field::as<std::string_view>(std::string_view const &default_value) const
370{
371 return is_null() ? default_value : view();
372}
373
374
375template<> inline bool field::to<zview>(zview &obj) const
376{
377 bool const null{is_null()};
378 if (not null)
379 obj = zview{c_str(), size()};
380 return not null;
381}
382
383
384template<>
385inline bool field::to<zview>(zview &obj, zview const &default_value) const
386{
387 bool const null{is_null()};
388 if (null)
389 obj = default_value;
390 else
391 obj = zview{c_str(), size()};
392 return not null;
393}
394
395
396template<> inline zview field::as<zview>() const
397{
398 if (is_null())
399 PQXX_UNLIKELY
400 internal::throw_null_conversion(type_name<zview>);
401 return zview{c_str(), size()};
402}
403
404
405template<> inline zview field::as<zview>(zview const &default_value) const
406{
407 return is_null() ? default_value : zview{c_str(), size()};
408}
409
410
411template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
412class field_streambuf : public std::basic_streambuf<CHAR, TRAITS>
413{
414public:
415 using char_type = CHAR;
416 using traits_type = TRAITS;
417 using int_type = typename traits_type::int_type;
418 using pos_type = typename traits_type::pos_type;
419 using off_type = typename traits_type::off_type;
420 using openmode = std::ios::openmode;
421 using seekdir = std::ios::seekdir;
422
423 explicit field_streambuf(field const &f) : m_field{f} { initialize(); }
424
425protected:
426 virtual int sync() override { return traits_type::eof(); }
427
428 virtual pos_type seekoff(off_type, seekdir, openmode) override
429 {
430 return traits_type::eof();
431 }
432 virtual pos_type seekpos(pos_type, openmode) override
433 {
434 return traits_type::eof();
435 }
436 virtual int_type overflow(int_type) override { return traits_type::eof(); }
437 virtual int_type underflow() override { return traits_type::eof(); }
438
439private:
440 field const &m_field;
441
442 int_type initialize()
443 {
444 auto g{static_cast<char_type *>(const_cast<char *>(m_field.c_str()))};
445 this->setg(g, g, g + std::size(m_field));
446 return int_type(std::size(m_field));
447 }
448};
449
450
452
465template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
466class basic_fieldstream : public std::basic_istream<CHAR, TRAITS>
467{
468 using super = std::basic_istream<CHAR, TRAITS>;
469
470public:
471 using char_type = CHAR;
472 using traits_type = TRAITS;
473 using int_type = typename traits_type::int_type;
474 using pos_type = typename traits_type::pos_type;
475 using off_type = typename traits_type::off_type;
476
477 [[deprecated("Use field::as<...>() or field::c_str().")]] basic_fieldstream(
478 field const &f) :
479 super{nullptr}, m_buf{f}
480 {
481 super::init(&m_buf);
482 }
483
484private:
486};
487
488
491
492
494
517template<typename CHAR>
518[[deprecated(
519 "Do this by hand, probably with better error checking.")]] inline std::
520 basic_ostream<CHAR> &
521 operator<<(std::basic_ostream<CHAR> &s, field const &value)
522{
523 s.write(value.c_str(), std::streamsize(std::size(value)));
524 return s;
525}
526
527
529
532template<typename T> inline T from_string(field const &value)
533{
534 if (value.is_null())
535 {
536 if constexpr (nullness<T>::has_null)
537 return nullness<T>::null();
538 else
540 }
541 else
542 {
543 return from_string<T>(value.view());
544 }
545}
546
547
549
555template<>
556inline std::nullptr_t from_string<std::nullptr_t>(field const &value)
557{
558 if (not value.is_null())
559 throw conversion_error{
560 "Extracting non-null field into nullptr_t variable."};
561 return nullptr;
562}
563
564
566template<> PQXX_LIBEXPORT std::string to_string(field const &value);
567} // namespace pqxx
568#endif
Low-level array parser.
Definition: array.hxx:529
Input stream that gets its data from a result field.
Definition: field.hxx:467
Definition: field.hxx:413
Reference to a field in a result set.
Definition: field.hxx:35
PQXX_PURE size_type size() const noexcept
Return number of bytes taken up by the field's value.
Definition: field.cxx:77
T as(T const &default_value) const
Return value as object of given type, or default value if null.
Definition: field.hxx:207
row_size_type m_col
Definition: field.hxx:291
array_parser as_array() const &noexcept
Parse the field as an SQL array.
Definition: field.hxx:253
auto to(T &obj, T const &default_value) const -> typename std::enable_if_t<(not std::is_pointer< T >::value or std::is_same< T, char const * >::value), bool >
Read value into obj; or if null, use default value and return false.
Definition: field.hxx:190
bool operator>>(T &obj) const
Read value into obj; or leave obj untouched and return false if null.
Definition: field.hxx:176
PQXX_PURE bool operator!=(field const &rhs) const noexcept
Byte-by-byte comparison (all nulls are considered equal)
Definition: field.hxx:65
PQXX_PURE char const * c_str() const &
Read as plain C string.
Definition: field.cxx:65
T as() const
Return value as object of given type, or throw exception if null.
Definition: field.hxx:221
PQXX_PURE std::string_view view() const &
Read as string_view, or an empty one if null.
Definition: field.hxx:111
bool composite_to(T &...fields) const
Read field as a composite value, write its components into fields.
Definition: field.hxx:162
field() noexcept=default
Constructor. Do not call this yourself; libpqxx will do it for you.
PQXX_PURE bool is_null() const noexcept
Is this field's value null?
Definition: field.cxx:71
constexpr O< T > get() const
Return value wrapped in some optional type (empty for nulls).
Definition: field.hxx:241
Result set containing data returned by a query or command.
Definition: result.hxx:73
Reference to one row in a result.
Definition: row.hxx:47
Marker-type wrapper: zero-terminated std::string_view.
Definition: zview.hxx:38
Value conversion failed, e.g. when converting "Hello" to int.
Definition: except.hxx:283
void throw_null_conversion(std::string const &type)
Throw exception for attempt to convert SQL NULL to given type.
Definition: strconv.cxx:255
The home of all libpqxx classes, functions, templates, etc.
Definition: array.cxx:27
std::basic_ostream< CHAR > & operator<<(std::basic_ostream< CHAR > &s, field const &value)
Write a result field to any type of stream.
Definition: field.hxx:521
int row_size_type
Number of fields in a row of database data.
Definition: types.hxx:34
std::size_t field_size_type
Number of bytes in a field of database data.
Definition: types.hxx:40
int result_size_type
Number of rows in a result set.
Definition: types.hxx:28
constexpr bool is_null(TYPE const &value) noexcept
Is value null?
Definition: strconv.hxx:514
void parse_composite(pqxx::internal::encoding_group enc, std::string_view text, T &...fields)
Parse a string representation of a value of a composite type.
Definition: composite.hxx:35
unsigned int oid
PostgreSQL database row identifier.
Definition: libpq-forward.hxx:33
PQXX_LIBEXPORT std::string to_string(field const &value)
Convert a field to a string.
Definition: result.cxx:566
T from_string(field const &value)
Convert a field's value to type T.
Definition: field.hxx:532
Traits describing a type's "null value," if any.
Definition: strconv.hxx:91
static TYPE null()
Return a null value.