libpqxx 7.7.0
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-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
16#include <optional>
17
18#include "pqxx/array.hxx"
19#include "pqxx/composite.hxx"
20#include "pqxx/result.hxx"
21#include "pqxx/strconv.hxx"
22#include "pqxx/types.hxx"
23
24namespace pqxx
25{
27
30class PQXX_LIBEXPORT field
31{
32public:
34
36
40 [[deprecated(
41 "Do not construct fields yourself. Get them from the row.")]] field(row const &r, row_size_type c) noexcept;
42
44 [[deprecated(
45 "Do not construct fields yourself. Get them from the row.")]] field() =
46 default;
47
53
69 [[nodiscard]] PQXX_PURE bool operator==(field const &) const;
70
72
74 [[nodiscard]] PQXX_PURE bool operator!=(field const &rhs) const
75 {
76 return not operator==(rhs);
77 }
79
85 [[nodiscard]] PQXX_PURE char const *name() const &;
86
88 [[nodiscard]] oid PQXX_PURE type() const;
89
91 [[nodiscard]] PQXX_PURE oid table() const;
92
94 PQXX_PURE row_size_type num() const { return col(); }
95
97 [[nodiscard]] PQXX_PURE row_size_type table_column() const;
99
105 [[nodiscard]] PQXX_PURE std::string_view view() const &
106 {
107 return std::string_view(c_str(), size());
108 }
109
111
120 [[nodiscard]] PQXX_PURE char const *c_str() const &;
121
123 [[nodiscard]] PQXX_PURE bool is_null() const noexcept;
124
126 [[nodiscard]] PQXX_PURE size_type size() const noexcept;
127
129
132 template<typename T>
133 auto to(T &obj) const -> typename std::enable_if_t<
134 (not std::is_pointer<T>::value or std::is_same<T, char const *>::value),
135 bool>
136 {
137 if (is_null())
138 {
139 return false;
140 }
141 else
142 {
143 auto const bytes{c_str()};
144 from_string(bytes, obj);
145 return true;
146 }
147 }
148
150
155 template<typename... T> bool composite_to(T &...fields) const
156 {
157 if (is_null())
158 {
159 return false;
160 }
161 else
162 {
163 parse_composite(m_home.m_encoding, view(), fields...);
164 return true;
165 }
166 }
167
169 template<typename T> bool operator>>(T &obj) const { return to(obj); }
170
172
182 template<typename T>
183 auto to(T &obj, T const &default_value) const -> typename std::enable_if_t<
184 (not std::is_pointer<T>::value or std::is_same<T, char const *>::value),
185 bool>
186 {
187 bool const null{is_null()};
188 if (null)
189 obj = default_value;
190 else
191 obj = from_string<T>(this->view());
192 return not null;
193 }
194
196
199 template<typename T> T as(T const &default_value) const
200 {
201 if (is_null())
202 return default_value;
203 else
204 return from_string<T>(this->view());
205 }
206
208
213 template<typename T> T as() const
214 {
215 if (is_null())
216 {
217 if constexpr (not nullness<T>::has_null)
218 internal::throw_null_conversion(type_name<T>);
219 else
220 return nullness<T>::null();
221 }
222 else
223 {
224 return from_string<T>(this->view());
225 }
226 }
227
229
232 template<typename T, template<typename> class O = std::optional>
233 constexpr O<T> get() const
234 {
235 return as<O<T>>();
236 }
237
239
246 {
247 return array_parser{c_str(), m_home.m_encoding};
248 }
250
251
252protected:
253 result const &home() const noexcept { return m_home; }
254 result::size_type idx() const noexcept { return m_row; }
255 row_size_type col() const noexcept { return m_col; }
256
257 // TODO: Create gates.
258 friend class pqxx::result;
259 friend class pqxx::row;
260 field(result const &r, result_size_type row_num, row_size_type col_num) :
261 m_col{col_num}, m_home{r}, m_row{row_num}
262 {}
263
269
270private:
271 result m_home;
272 result::size_type m_row;
273};
274
275
276template<> inline bool field::to<std::string>(std::string &obj) const
277{
278 bool const null{is_null()};
279 if (not null)
280 obj = std::string{view()};
281 return not null;
282}
283
284
285template<>
286inline bool field::to<std::string>(
287 std::string &obj, std::string const &default_value) const
288{
289 bool const null{is_null()};
290 if (null)
291 obj = default_value;
292 else
293 obj = std::string{view()};
294 return not null;
295}
296
297
299
304template<> inline bool field::to<char const *>(char const *&obj) const
305{
306 bool const null{is_null()};
307 if (not null)
308 obj = c_str();
309 return not null;
310}
311
312
313template<> inline bool field::to<std::string_view>(std::string_view &obj) const
314{
315 bool const null{is_null()};
316 if (not null)
317 obj = view();
318 return not null;
319}
320
321
322template<>
323inline bool field::to<std::string_view>(
324 std::string_view &obj, std::string_view const &default_value) const
325{
326 bool const null{is_null()};
327 if (null)
328 obj = default_value;
329 else
330 obj = view();
331 return not null;
332}
333
334
335template<> inline std::string_view field::as<std::string_view>() const
336{
337 if (is_null())
338 PQXX_UNLIKELY
339 internal::throw_null_conversion(type_name<std::string_view>);
340 return view();
341}
342
343
344template<>
345inline std::string_view
346field::as<std::string_view>(std::string_view const &default_value) const
347{
348 return is_null() ? default_value : view();
349}
350
351
352template<> inline bool field::to<zview>(zview &obj) const
353{
354 bool const null{is_null()};
355 if (not null)
356 obj = zview{c_str(), size()};
357 return not null;
358}
359
360
361template<>
362inline bool field::to<zview>(zview &obj, zview const &default_value) const
363{
364 bool const null{is_null()};
365 if (null)
366 obj = default_value;
367 else
368 obj = zview{c_str(), size()};
369 return not null;
370}
371
372
373template<> inline zview field::as<zview>() const
374{
375 if (is_null())
376 PQXX_UNLIKELY
377 internal::throw_null_conversion(type_name<zview>);
378 return zview{c_str(), size()};
379}
380
381
382template<> inline zview field::as<zview>(zview const &default_value) const
383{
384 return is_null() ? default_value : zview{c_str(), size()};
385}
386
387
388template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
389class field_streambuf : public std::basic_streambuf<CHAR, TRAITS>
390{
391public:
392 using char_type = CHAR;
393 using traits_type = TRAITS;
394 using int_type = typename traits_type::int_type;
395 using pos_type = typename traits_type::pos_type;
396 using off_type = typename traits_type::off_type;
397 using openmode = std::ios::openmode;
398 using seekdir = std::ios::seekdir;
399
400 explicit field_streambuf(field const &f) : m_field{f} { initialize(); }
401
402protected:
403 virtual int sync() override { return traits_type::eof(); }
404
406 {
407 return traits_type::eof();
408 }
410 {
411 return traits_type::eof();
412 }
413 virtual int_type overflow(int_type) override { return traits_type::eof(); }
414 virtual int_type underflow() override { return traits_type::eof(); }
415
416private:
417 field const &m_field;
418
419 int_type initialize()
420 {
421 auto g{static_cast<char_type *>(const_cast<char *>(m_field.c_str()))};
422 this->setg(g, g, g + std::size(m_field));
423 return int_type(std::size(m_field));
424 }
425};
426
427
429
437template<typename CHAR = char, typename TRAITS = std::char_traits<CHAR>>
438class basic_fieldstream : public std::basic_istream<CHAR, TRAITS>
439{
440 using super = std::basic_istream<CHAR, TRAITS>;
441
442public:
443 using char_type = CHAR;
444 using traits_type = TRAITS;
445 using int_type = typename traits_type::int_type;
446 using pos_type = typename traits_type::pos_type;
447 using off_type = typename traits_type::off_type;
448
449 basic_fieldstream(field const &f) : super{nullptr}, m_buf{f}
450 {
451 super::init(&m_buf);
452 }
453
454private:
456};
457
459
461
481template<typename CHAR>
482inline std::basic_ostream<CHAR> &
483operator<<(std::basic_ostream<CHAR> &s, field const &value)
484{
485 s.write(value.c_str(), std::streamsize(std::size(value)));
486 return s;
487}
488
489
491
494template<typename T> inline T from_string(field const &value)
495{
496 if (value.is_null())
497 {
498 if constexpr (nullness<T>::has_null)
499 return nullness<T>::null();
500 else
502 }
503 else
504 {
505 return from_string<T>(value.view());
506 }
507}
508
509
511
517template<>
518inline std::nullptr_t from_string<std::nullptr_t>(field const &value)
519{
520 if (not value.is_null())
521 throw conversion_error{
522 "Extracting non-null field into nullptr_t variable."};
523 return nullptr;
524}
525
526
528template<> PQXX_LIBEXPORT std::string to_string(field const &value);
529} // namespace pqxx
530#endif
The home of all libpqxx classes, functions, templates, etc.
Definition: array.hxx:23
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:483
int row_size_type
Number of fields in a row of database data.
Definition: types.hxx:30
std::size_t field_size_type
Number of bytes in a field of database data.
Definition: types.hxx:36
int result_size_type
Number of rows in a result set.
Definition: types.hxx:24
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:31
std::nullptr_t from_string< std::nullptr_t >(field const &value)
Convert a field's value to nullptr_t.
Definition: field.hxx:518
std::string to_string(field const &value)
Convert a field to a string.
Definition: result.cxx:528
bool is_null(TYPE const &value) noexcept
Is value null?
Definition: strconv.hxx:364
T from_string(field const &value)
Convert a field's value to type T.
Definition: field.hxx:494
void PQXX_COLD throw_null_conversion(std::string const &type)
Definition: strconv.cxx:252
Low-level array parser.
Definition: array.hxx:44
Value conversion failed, e.g. when converting "Hello" to int.
Definition: except.hxx:176
Reference to a field in a result set.
Definition: field.hxx:31
array_parser as_array() const &
Parse the field as an SQL array.
Definition: field.hxx:245
row_size_type col() const noexcept
Definition: field.hxx:255
PQXX_PURE size_type size() const noexcept
Return number of bytes taken up by the field's value.
Definition: field.cxx:72
T as(T const &default_value) const
Return value as object of given type, or default value if null.
Definition: field.hxx:199
row_size_type m_col
Definition: field.hxx:268
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:183
field_size_type size_type
Definition: field.hxx:33
bool operator>>(T &obj) const
Read value into obj; or leave obj untouched and return false if null.
Definition: field.hxx:169
field(result const &r, result_size_type row_num, row_size_type col_num)
Definition: field.hxx:260
field()=default
Constructor. Do not call this yourself; libpqxx will do it for you.
result::size_type idx() const noexcept
Definition: field.hxx:254
PQXX_PURE char const * c_str() const &
Read as plain C string.
Definition: field.cxx:60
T as() const
Return value as object of given type, or throw exception if null.
Definition: field.hxx:213
PQXX_PURE bool operator!=(field const &rhs) const
Byte-by-byte comparison (all nulls are considered equal)
Definition: field.hxx:74
result const & home() const noexcept
Definition: field.hxx:253
PQXX_PURE std::string_view view() const &
Read as string_view, or an empty one if null.
Definition: field.hxx:105
bool composite_to(T &...fields) const
Read field as a composite value, write its components into fields.
Definition: field.hxx:155
PQXX_PURE bool is_null() const noexcept
Is this field's value null?
Definition: field.cxx:66
constexpr O< T > get() const
Return value wrapped in some optional type (empty for nulls).
Definition: field.hxx:233
Definition: field.hxx:390
TRAITS traits_type
Definition: field.hxx:393
typename traits_type::off_type off_type
Definition: field.hxx:396
field_streambuf(field const &f)
Definition: field.hxx:400
virtual pos_type seekoff(off_type, seekdir, openmode) override
Definition: field.hxx:405
virtual pos_type seekpos(pos_type, openmode) override
Definition: field.hxx:409
std::ios::openmode openmode
Definition: field.hxx:397
virtual int_type overflow(int_type) override
Definition: field.hxx:413
typename traits_type::pos_type pos_type
Definition: field.hxx:395
virtual int sync() override
Definition: field.hxx:403
typename traits_type::int_type int_type
Definition: field.hxx:394
virtual int_type underflow() override
Definition: field.hxx:414
CHAR char_type
Definition: field.hxx:392
std::ios::seekdir seekdir
Definition: field.hxx:398
Input stream that gets its data from a result field.
Definition: field.hxx:439
TRAITS traits_type
Definition: field.hxx:444
basic_fieldstream(field const &f)
Definition: field.hxx:449
typename traits_type::pos_type pos_type
Definition: field.hxx:446
typename traits_type::off_type off_type
Definition: field.hxx:447
typename traits_type::int_type int_type
Definition: field.hxx:445
CHAR char_type
Definition: field.hxx:443
Result set containing data returned by a query or command.
Definition: result.hxx:68
result_size_type size_type
Definition: result.hxx:70
Reference to one row in a result.
Definition: row.hxx:43
Traits describing a type's "null value," if any.
Definition: strconv.hxx:89
Marker-type wrapper: zero-terminated std::string_view.
Definition: zview.hxx:38