aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/libpqxx/include/pqxx/result.hxx
blob: b1f5ce3f4c3a6bae949b4b38f1c5319f09913de7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
/** Definitions for the pqxx::result class and support classes.
 *
 * pqxx::result represents the set of result rows from a database query.
 *
 * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/result instead.
 *
 * Copyright (c) 2000-2019, Jeroen T. Vermeulen.
 *
 * See COPYING for copyright license.  If you did not receive a file called
 * COPYING with this source code, please notify the distributor of this mistake,
 * or contact the author.
 */
#ifndef PQXX_H_RESULT
#define PQXX_H_RESULT

#include "pqxx/compiler-public.hxx"
#include "pqxx/compiler-internal-pre.hxx"

#include <ios>
#include <memory>
#include <stdexcept>

#include "pqxx/except.hxx"
#include "pqxx/types.hxx"
#include "pqxx/util.hxx"

#include "pqxx/internal/encodings.hxx"


// Methods tested in eg. test module test01 are marked with "//[t01]".

namespace pqxx
{
namespace internal
{
PQXX_LIBEXPORT void clear_result(const pq::PGresult *);

namespace gate
{
class result_connection;
class result_creation;
class result_row;
class result_sql_cursor;
} // namespace internal::gate
} // namespace internal


enum class result_format
{
    text = 0,
    binary = 1
};


/// Result set containing data returned by a query or command.
/** This behaves as a container (as defined by the C++ standard library) and
 * provides random access const iterators to iterate over its rows.  A row
 * can also be accessed by indexing a result R by the row's zero-based
 * number:
 *
 * @code
 *	for (result::size_type i=0; i < R.size(); ++i) Process(R[i]);
 * @endcode
 *
 * Result sets in libpqxx are lightweight, reference-counted wrapper objects
 * which are relatively small and cheap to copy.  Think of a result object as
 * a "smart pointer" to an underlying result set.
 *
 * @warning The result set that a result object points to is not thread-safe.
 * If you copy a result object, it still refers to the same underlying result
 * set.  So never copy, destroy, query, or otherwise access a result while
 * another thread may be copying, destroying, querying, or otherwise accessing
 * the same result set--even if it is doing so through a different result
 * object!
 */
class PQXX_LIBEXPORT result
{
public:
  using size_type = result_size_type;
  using difference_type = result_difference_type;
  using reference = row;
  using const_iterator = const_result_iterator;
  using pointer = const_iterator;
  using iterator = const_iterator;
  using const_reverse_iterator = const_reverse_result_iterator;
  using reverse_iterator = const_reverse_iterator;

  result() noexcept :		                                        //[t03]
      m_data(make_data_pointer()),
      m_query(),
      m_encoding(internal::encoding_group::MONOBYTE)
    {}
  result(const result &rhs) noexcept =default;				//[t01]

  result &operator=(const result &rhs) noexcept =default;		//[t10]

  /**
   * @name Comparisons
   */
  //@{
  bool operator==(const result &) const noexcept;			//[t70]
  bool operator!=(const result &rhs) const noexcept			//[t70]
	{ return not operator==(rhs); }
  //@}

  const_reverse_iterator rbegin() const;				//[t75]
  const_reverse_iterator crbegin() const;
  const_reverse_iterator rend() const;					//[t75]
  const_reverse_iterator crend() const;

  const_iterator begin() const noexcept;				//[t01]
  const_iterator cbegin() const noexcept;
  inline const_iterator end() const noexcept;				//[t01]
  inline const_iterator cend() const noexcept;

  reference front() const noexcept;					//[t74]
  reference back() const noexcept;					//[t75]

  PQXX_PURE size_type size() const noexcept;				//[t02]
  PQXX_PURE bool empty() const noexcept;				//[t11]
  size_type capacity() const noexcept { return size(); }		//[t20]

  void swap(result &) noexcept;						//[t77]

  const row operator[](size_type i) const noexcept;			//[t02]
  const row at(size_type) const;					//[t10]

  void clear() noexcept { m_data.reset(); m_query = nullptr; }		//[t20]

  /**
   * @name Column information
   */
  //@{
  /// Number of columns in result.
  PQXX_PURE row_size_type columns() const noexcept;			//[t11]

  /// Number of given column (throws exception if it doesn't exist).
  row_size_type column_number(const char ColName[]) const;		//[t11]

  /// Number of given column (throws exception if it doesn't exist).
  row_size_type column_number(const std::string &Name) const		//[t11]
	{return column_number(Name.c_str());}

  /// Name of column with this number (throws exception if it doesn't exist)
  const char *column_name(row_size_type Number) const;			//[t11]

  /// Type of given column
  oid column_type(row_size_type ColNum) const;				//[t07]
  /// Type of given column
  oid column_type(int ColNum) const					//[t07]
	{ return column_type(row_size_type(ColNum)); }

  /// Type of given column
  oid column_type(const std::string &ColName) const			//[t07]
	{ return column_type(column_number(ColName)); }

  /// Type of given column
  oid column_type(const char ColName[]) const				//[t07]
	{ return column_type(column_number(ColName)); }

  /// What table did this column come from?
  oid column_table(row_size_type ColNum) const;				//[t02]

  /// What table did this column come from?
  oid column_table(int ColNum) const					//[t02]
	{ return column_table(row_size_type(ColNum)); }

  /// What table did this column come from?
  oid column_table(const std::string &ColName) const			//[t02]
	{ return column_table(column_number(ColName)); }

  /// What column in its table did this column come from?
  row_size_type table_column(row_size_type ColNum) const;		//[t93]

  /// What column in its table did this column come from?
  row_size_type table_column(int ColNum) const				//[t93]
	{ return table_column(row_size_type(ColNum)); }

  /// What column in its table did this column come from?
  row_size_type table_column(const std::string &ColName) const		//[t93]
	{ return table_column(column_number(ColName)); }
  //@}

  /// Query that produced this result, if available (empty string otherwise)
  PQXX_PURE const std::string &query() const noexcept;			//[t70]

  /// If command was @c INSERT of 1 row, return oid of inserted row
  /** @return Identifier of inserted row if exactly one row was inserted, or
   * oid_none otherwise.
   */
  PQXX_PURE oid inserted_oid() const;					//[t13]

  /// If command was @c INSERT, @c UPDATE, or @c DELETE: number of affected rows
  /** @return Number of affected rows if last command was @c INSERT, @c UPDATE,
   * or @c DELETE; zero for all other commands.
   */
  PQXX_PURE size_type affected_rows() const;				//[t07]


private:
  using data_pointer = std::shared_ptr<const internal::pq::PGresult>;

  /// Underlying libpq result set.
   data_pointer m_data;

  /// Factory for data_pointer.
  static data_pointer make_data_pointer(
	const internal::pq::PGresult *res=nullptr)
	{ return data_pointer{res, internal::clear_result}; }

  /// Query string.
  std::shared_ptr<std::string> m_query;

  internal::encoding_group m_encoding;

  static const std::string s_empty_string;

  friend class pqxx::field;
  PQXX_PURE const char *GetValue(size_type Row, row_size_type Col) const;
  PQXX_PURE bool get_is_null(size_type Row, row_size_type Col) const;
  PQXX_PURE field_size_type get_length(
	size_type,
	row_size_type) const noexcept;

  friend class pqxx::internal::gate::result_creation;
  result(
        internal::pq::PGresult *rhs,
        const std::string &Query,
        internal::encoding_group enc);

  PQXX_PRIVATE void check_status() const;

  friend class pqxx::internal::gate::result_connection;
  friend class pqxx::internal::gate::result_row;
  bool operator!() const noexcept { return not m_data.get(); }
  operator bool() const noexcept { return m_data.get() != nullptr; }

  [[noreturn]] PQXX_PRIVATE void ThrowSQLError(
	const std::string &Err,
	const std::string &Query) const;
  PQXX_PRIVATE PQXX_PURE int errorposition() const;
  PQXX_PRIVATE std::string StatusError() const;

  friend class pqxx::internal::gate::result_sql_cursor;
  PQXX_PURE const char *cmd_status() const noexcept;
};
} // namespace pqxx
#include "pqxx/compiler-internal-post.hxx"
#endif