row.hxx 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. /** Definitions for the pqxx::result class and support classes.
  2. *
  3. * pqxx::result represents the set of result rows from a database query.
  4. *
  5. * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/result instead.
  6. *
  7. * Copyright (c) 2000-2019, 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 mistake,
  11. * or contact the author.
  12. */
  13. #ifndef PQXX_H_ROW
  14. #define PQXX_H_ROW
  15. #include "pqxx/compiler-public.hxx"
  16. #include "pqxx/compiler-internal-pre.hxx"
  17. #include "pqxx/except.hxx"
  18. #include "pqxx/field.hxx"
  19. #include "pqxx/result.hxx"
  20. // Methods tested in eg. test module test01 are marked with "//[t01]".
  21. namespace pqxx
  22. {
  23. /// Reference to one row in a result.
  24. /** A row represents one row (also called a row) in a query result set.
  25. * It also acts as a container mapping column numbers or names to field
  26. * values (see below):
  27. *
  28. * @code
  29. * cout << row["date"].c_str() << ": " << row["name"].c_str() << endl;
  30. * @endcode
  31. *
  32. * The row itself acts like a (non-modifyable) container, complete with its
  33. * own const_iterator and const_reverse_iterator.
  34. */
  35. class PQXX_LIBEXPORT row
  36. {
  37. public:
  38. using size_type = row_size_type;
  39. using difference_type = row_difference_type;
  40. using const_iterator = const_row_iterator;
  41. using iterator = const_iterator;
  42. using reference = field;
  43. using pointer = const_row_iterator;
  44. using const_reverse_iterator = const_reverse_row_iterator;
  45. using reverse_iterator = const_reverse_iterator;
  46. row() =default;
  47. /// @deprecated Do not use this constructor. It will become private.
  48. row(result r, size_t i) noexcept;
  49. ~row() noexcept =default; // Yes Scott Meyers, you're absolutely right[1]
  50. /**
  51. * @name Comparison
  52. */
  53. //@{
  54. PQXX_PURE bool operator==(const row &) const noexcept; //[t75]
  55. bool operator!=(const row &rhs) const noexcept //[t75]
  56. { return not operator==(rhs); }
  57. //@}
  58. const_iterator begin() const noexcept; //[t82]
  59. const_iterator cbegin() const noexcept;
  60. const_iterator end() const noexcept; //[t82]
  61. const_iterator cend() const noexcept;
  62. /**
  63. * @name Field access
  64. */
  65. //@{
  66. reference front() const noexcept; //[t74]
  67. reference back() const noexcept; //[t75]
  68. const_reverse_row_iterator rbegin() const; //[t82]
  69. const_reverse_row_iterator crbegin() const;
  70. const_reverse_row_iterator rend() const; //[t82]
  71. const_reverse_row_iterator crend() const;
  72. reference operator[](size_type) const noexcept; //[t11]
  73. reference operator[](int) const noexcept; //[t02]
  74. /** Address field by name.
  75. * @warning This is much slower than indexing by number, or iterating.
  76. */
  77. reference operator[](const char[]) const; //[t11]
  78. /** Address field by name.
  79. * @warning This is much slower than indexing by number, or iterating.
  80. */
  81. reference operator[](const std::string &) const; //[t11]
  82. reference at(size_type) const; //[t11]
  83. reference at(int) const; //[t11]
  84. /** Address field by name.
  85. * @warning This is much slower than indexing by number, or iterating.
  86. */
  87. reference at(const char[]) const; //[t11]
  88. /** Address field by name.
  89. * @warning This is much slower than indexing by number, or iterating.
  90. */
  91. reference at(const std::string &) const; //[t11]
  92. //@}
  93. size_type size() const noexcept //[t11]
  94. { return m_end-m_begin; }
  95. void swap(row &) noexcept; //[t11]
  96. /// Row number, assuming this is a real row and not end()/rend().
  97. size_t rownumber() const noexcept { return size_t(m_index); } //[t11]
  98. /**
  99. * @name Column information
  100. */
  101. //@{
  102. /// Number of given column (throws exception if it doesn't exist)
  103. size_type column_number(const std::string &ColName) const //[t30]
  104. { return column_number(ColName.c_str()); }
  105. /// Number of given column (throws exception if it doesn't exist)
  106. size_type column_number(const char[]) const; //[t30]
  107. /// Type of given column
  108. oid column_type(size_type) const; //[t07]
  109. /// Type of given column
  110. oid column_type(int ColNum) const //[t07]
  111. { return column_type(size_type(ColNum)); }
  112. /// Type of given column
  113. oid column_type(const std::string &ColName) const //[t07]
  114. { return column_type(column_number(ColName)); }
  115. /// Type of given column
  116. oid column_type(const char ColName[]) const //[t07]
  117. { return column_type(column_number(ColName)); }
  118. /// What table did this column come from?
  119. oid column_table(size_type ColNum) const; //[t02]
  120. /// What table did this column come from?
  121. oid column_table(int ColNum) const //[t02]
  122. { return column_table(size_type(ColNum)); }
  123. /// What table did this column come from?
  124. oid column_table(const std::string &ColName) const //[t02]
  125. { return column_table(column_number(ColName)); }
  126. /// What column number in its table did this result column come from?
  127. /** A meaningful answer can be given only if the column in question comes
  128. * directly from a column in a table. If the column is computed in any
  129. * other way, a logic_error will be thrown.
  130. *
  131. * @param ColNum a zero-based column number in this result set
  132. * @return a zero-based column number in originating table
  133. */
  134. size_type table_column(size_type) const; //[t93]
  135. /// What column number in its table did this result column come from?
  136. size_type table_column(int ColNum) const //[t93]
  137. { return table_column(size_type(ColNum)); }
  138. /// What column number in its table did this result column come from?
  139. size_type table_column(const std::string &ColName) const //[t93]
  140. { return table_column(column_number(ColName)); }
  141. //@}
  142. size_t num() const { return rownumber(); } //[t01]
  143. /** Produce a slice of this row, containing the given range of columns.
  144. *
  145. * The slice runs from the range's starting column to the range's end
  146. * column, exclusive. It looks just like a normal result row, except
  147. * slices can be empty.
  148. *
  149. * @warning Slicing is a relatively new feature, and not all software may be
  150. * prepared to deal with empty slices. If there is any chance that your
  151. * program might be creating empty slices and passing them to code that may
  152. * not be designed with the possibility of empty rows in mind, be sure to
  153. * test for that case.
  154. */
  155. row slice(size_type Begin, size_type End) const;
  156. // Is this an empty slice?
  157. PQXX_PURE bool empty() const noexcept;
  158. protected:
  159. friend class field;
  160. /// Result set of which this is one row.
  161. result m_result;
  162. /// Row number.
  163. /**
  164. * You'd expect this to be a size_t, but due to the way reverse iterators
  165. * are related to regular iterators, it must be allowed to underflow to -1.
  166. */
  167. long m_index = 0;
  168. /// First column in slice. This row ignores lower-numbered columns.
  169. size_type m_begin = 0;
  170. /// End column in slice. This row only sees lower-numbered columns.
  171. size_type m_end = 0;
  172. };
  173. /// Iterator for fields in a row. Use as row::const_iterator.
  174. class PQXX_LIBEXPORT const_row_iterator : public field
  175. {
  176. public:
  177. using iterator_category = std::random_access_iterator_tag;
  178. using value_type = const field;
  179. using pointer = const field *;
  180. using size_type = row_size_type;
  181. using difference_type = row_difference_type;
  182. using reference = field;
  183. const_row_iterator(const row &T, row_size_type C) noexcept : //[t82]
  184. field{T, C} {}
  185. const_row_iterator(const field &F) noexcept : field{F} {} //[t82]
  186. /**
  187. * @name Dereferencing operators
  188. */
  189. //@{
  190. pointer operator->() const { return this; } //[t82]
  191. reference operator*() const { return field{*this}; } //[t82]
  192. //@}
  193. /**
  194. * @name Manipulations
  195. */
  196. //@{
  197. const_row_iterator operator++(int); //[t82]
  198. const_row_iterator &operator++() { ++m_col; return *this; } //[t82]
  199. const_row_iterator operator--(int); //[t82]
  200. const_row_iterator &operator--() { --m_col; return *this; } //[t82]
  201. const_row_iterator &operator+=(difference_type i) //[t82]
  202. { m_col = size_type(difference_type(m_col) + i); return *this; }
  203. const_row_iterator &operator-=(difference_type i) //[t82]
  204. { m_col = size_type(difference_type(m_col) - i); return *this; }
  205. //@}
  206. /**
  207. * @name Comparisons
  208. */
  209. //@{
  210. bool operator==(const const_row_iterator &i) const //[t82]
  211. {return col()==i.col();}
  212. bool operator!=(const const_row_iterator &i) const //[t82]
  213. {return col()!=i.col();}
  214. bool operator<(const const_row_iterator &i) const //[t82]
  215. {return col()<i.col();}
  216. bool operator<=(const const_row_iterator &i) const //[t82]
  217. {return col()<=i.col();}
  218. bool operator>(const const_row_iterator &i) const //[t82]
  219. {return col()>i.col();}
  220. bool operator>=(const const_row_iterator &i) const //[t82]
  221. {return col()>=i.col();}
  222. //@}
  223. /**
  224. * @name Arithmetic operators
  225. */
  226. //@{
  227. inline const_row_iterator operator+(difference_type) const; //[t82]
  228. friend const_row_iterator operator+( //[t82]
  229. difference_type,
  230. const_row_iterator);
  231. inline const_row_iterator operator-(difference_type) const; //[t82]
  232. inline difference_type operator-(const_row_iterator) const; //[t82]
  233. //@}
  234. };
  235. /// Reverse iterator for a row. Use as row::const_reverse_iterator.
  236. class PQXX_LIBEXPORT const_reverse_row_iterator : private const_row_iterator
  237. {
  238. public:
  239. using super = const_row_iterator;
  240. using iterator_type = const_row_iterator;
  241. using iterator_type::iterator_category;
  242. using iterator_type::difference_type;
  243. using iterator_type::pointer;
  244. using value_type = iterator_type::value_type;
  245. using reference = iterator_type::reference;
  246. const_reverse_row_iterator(const const_reverse_row_iterator &r) : //[t82]
  247. const_row_iterator{r} {}
  248. explicit
  249. const_reverse_row_iterator(const super &rhs) noexcept : //[t82]
  250. const_row_iterator{rhs} { super::operator--(); }
  251. PQXX_PURE iterator_type base() const noexcept; //[t82]
  252. /**
  253. * @name Dereferencing operators
  254. */
  255. //@{
  256. using iterator_type::operator->; //[t82]
  257. using iterator_type::operator*; //[t82]
  258. //@}
  259. /**
  260. * @name Manipulations
  261. */
  262. //@{
  263. const_reverse_row_iterator &
  264. operator=(const const_reverse_row_iterator &r) //[t82]
  265. { iterator_type::operator=(r); return *this; }
  266. const_reverse_row_iterator operator++() //[t82]
  267. { iterator_type::operator--(); return *this; }
  268. const_reverse_row_iterator operator++(int); //[t82]
  269. const_reverse_row_iterator &operator--() //[t82]
  270. { iterator_type::operator++(); return *this; }
  271. const_reverse_row_iterator operator--(int); //[t82]
  272. const_reverse_row_iterator &operator+=(difference_type i) //[t82]
  273. { iterator_type::operator-=(i); return *this; }
  274. const_reverse_row_iterator &operator-=(difference_type i) //[t82]
  275. { iterator_type::operator+=(i); return *this; }
  276. //@}
  277. /**
  278. * @name Arithmetic operators
  279. */
  280. //@{
  281. const_reverse_row_iterator operator+(difference_type i) const //[t82]
  282. { return const_reverse_row_iterator{base()-i}; }
  283. const_reverse_row_iterator operator-(difference_type i) //[t82]
  284. { return const_reverse_row_iterator{base()+i}; }
  285. difference_type
  286. operator-(const const_reverse_row_iterator &rhs) const //[t82]
  287. { return rhs.const_row_iterator::operator-(*this); }
  288. //@}
  289. /**
  290. * @name Comparisons
  291. */
  292. //@{
  293. bool operator==(const const_reverse_row_iterator &rhs) const noexcept //[t82]
  294. { return iterator_type::operator==(rhs); }
  295. bool operator!=(const const_reverse_row_iterator &rhs) const noexcept //[t82]
  296. { return !operator==(rhs); }
  297. bool operator<(const const_reverse_row_iterator &rhs) const //[t82]
  298. { return iterator_type::operator>(rhs); }
  299. bool operator<=(const const_reverse_row_iterator &rhs) const //[t82]
  300. { return iterator_type::operator>=(rhs); }
  301. bool operator>(const const_reverse_row_iterator &rhs) const //[t82]
  302. { return iterator_type::operator<(rhs); }
  303. bool operator>=(const const_reverse_row_iterator &rhs) const //[t82]
  304. { return iterator_type::operator<=(rhs); }
  305. //@}
  306. };
  307. inline const_row_iterator
  308. const_row_iterator::operator+(difference_type o) const
  309. {
  310. return const_row_iterator{
  311. row(home(), idx()),
  312. size_type(difference_type(col()) + o)};
  313. }
  314. inline const_row_iterator
  315. operator+(const_row_iterator::difference_type o, const_row_iterator i)
  316. { return i + o; }
  317. inline const_row_iterator
  318. const_row_iterator::operator-(difference_type o) const
  319. {
  320. return const_row_iterator{
  321. row(home(), idx()),
  322. size_type(difference_type(col()) - o)};
  323. }
  324. inline const_row_iterator::difference_type
  325. const_row_iterator::operator-(const_row_iterator i) const
  326. { return difference_type(num() - i.num()); }
  327. } // namespace pqxx
  328. /*
  329. [1] Scott Meyers, in one of his essential books, "Effective C++" and "More
  330. Effective C++", points out that it is good style to have any class containing
  331. a member of pointer type define a destructor--just to show that it knows what
  332. it is doing with the pointer. This helps prevent nasty memory leak / double
  333. deletion bugs typically resulting from programmers' omission to deal with such
  334. issues in their destructors.
  335. The @c -Weffc++ option in gcc generates warnings for noncompliance with Scott's
  336. style guidelines, and hence necessitates the definition of this destructor,
  337. trivial as it may be.
  338. */
  339. #include "pqxx/compiler-internal-post.hxx"
  340. #endif