statement_parameters.hxx 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /** Common implementation for statement parameter lists.
  2. *
  3. * These are used for both prepared statements and parameterized statements.
  4. *
  5. * DO NOT INCLUDE THIS FILE DIRECTLY. Other headers include it for you.
  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_STATEMENT_PARAMETER
  14. #define PQXX_H_STATEMENT_PARAMETER
  15. #include "pqxx/compiler-public.hxx"
  16. #include "pqxx/compiler-internal-pre.hxx"
  17. #include <cstring>
  18. #include <iterator>
  19. #include <string>
  20. #include <vector>
  21. #include "pqxx/binarystring"
  22. #include "pqxx/strconv"
  23. #include "pqxx/util"
  24. #include "pqxx/internal/type_utils.hxx"
  25. namespace pqxx
  26. {
  27. namespace internal
  28. {
  29. /// Marker type: pass a dynamically-determined number of statement parameters.
  30. /** Normally when invoking a prepared or parameterised statement, the number
  31. * of parameters is known at compile time. For instance,
  32. * @c t.exec_prepared("foo", 1, "x"); executes statement @c foo with two
  33. * parameters, an @c int and a C string.
  34. *
  35. * But sometimes you may want to pass a number of parameters known only at run
  36. * time. In those cases, a @c dynamic_params encodes a dynamically
  37. * determined number of parameters.
  38. */
  39. template<typename IT> class dynamic_params
  40. {
  41. public:
  42. /// Wrap a sequence of pointers or iterators.
  43. dynamic_params(IT begin, IT end) : m_begin(begin), m_end(end) {}
  44. /// Wrap a container.
  45. template<typename C> explicit dynamic_params(const C &container) :
  46. m_begin(std::begin(container)),
  47. m_end(std::end(container))
  48. {}
  49. IT begin() const { return m_begin; }
  50. IT end() const { return m_end; }
  51. private:
  52. const IT m_begin, m_end;
  53. };
  54. class PQXX_LIBEXPORT statement_parameters
  55. {
  56. protected:
  57. statement_parameters() =default;
  58. statement_parameters &operator=(const statement_parameters &) =delete;
  59. void add_param() { this->add_checked_param("", false, false); }
  60. template<typename T> void add_param(const T &v, bool nonnull)
  61. {
  62. nonnull = (nonnull && not pqxx::string_traits<T>::is_null(v));
  63. this->add_checked_param(
  64. (nonnull ? pqxx::to_string(v) : ""),
  65. nonnull,
  66. false);
  67. }
  68. void add_binary_param(const binarystring &b, bool nonnull)
  69. { this->add_checked_param(b.str(), nonnull, true); }
  70. /// Marshall parameter values into C-compatible arrays for passing to libpq.
  71. int marshall(
  72. std::vector<const char *> &values,
  73. std::vector<int> &lengths,
  74. std::vector<int> &binaries) const;
  75. private:
  76. void add_checked_param(const std::string &value, bool nonnull, bool binary);
  77. std::vector<std::string> m_values;
  78. std::vector<bool> m_nonnull;
  79. std::vector<bool> m_binary;
  80. };
  81. /// Internal type: encode statement parameters.
  82. /** Compiles arguments for prepared statements and parameterised queries into
  83. * a format that can be passed into libpq.
  84. *
  85. * Objects of this type are meant to be short-lived. If you pass in a non-null
  86. * pointer as a parameter, it may simply use that pointer as a parameter value.
  87. */
  88. struct params
  89. {
  90. /// Construct directly from a series of statement arguments.
  91. /** The arrays all default to zero, null, and empty strings.
  92. */
  93. template<typename ...Args> params(Args && ... args)
  94. {
  95. strings.reserve(sizeof...(args));
  96. lengths.reserve(sizeof...(args));
  97. nonnulls.reserve(sizeof...(args));
  98. binaries.reserve(sizeof...(args));
  99. // Start recursively storing parameters.
  100. add_fields(std::forward<Args>(args)...);
  101. }
  102. /// Compose a vector of pointers to parameter string values.
  103. std::vector<const char *> get_pointers() const
  104. {
  105. const std::size_t num_fields = lengths.size();
  106. std::size_t cur_string = 0, cur_bin_string = 0;
  107. std::vector<const char *> pointers(num_fields);
  108. for (std::size_t index = 0; index < num_fields; index++)
  109. {
  110. const char *value;
  111. if (binaries[index])
  112. {
  113. value = bin_strings[cur_bin_string].get();
  114. cur_bin_string++;
  115. }
  116. else if (nonnulls[index])
  117. {
  118. value = strings[cur_string].c_str();
  119. cur_string++;
  120. }
  121. else
  122. {
  123. value = nullptr;
  124. }
  125. pointers[index] = value;
  126. }
  127. return pointers;
  128. }
  129. /// String values, for string parameters.
  130. std::vector<std::string> strings;
  131. /// As used by libpq: lengths of non-null arguments, in bytes.
  132. std::vector<int> lengths;
  133. /// As used by libpq: boolean "is this parameter non-null?"
  134. std::vector<int> nonnulls;
  135. /// As used by libpq: boolean "is this parameter in binary format?"
  136. std::vector<int> binaries;
  137. /// Binary string values, for binary parameters.
  138. std::vector<pqxx::binarystring> bin_strings;
  139. private:
  140. /// Add a non-null string field.
  141. void add_field(std::string str)
  142. {
  143. lengths.push_back(int(str.size()));
  144. nonnulls.push_back(1);
  145. binaries.push_back(0);
  146. strings.emplace_back(std::move(str));
  147. }
  148. /// Compile one argument (specialised for null pointer, a null value).
  149. void add_field(std::nullptr_t)
  150. {
  151. lengths.push_back(0);
  152. nonnulls.push_back(0);
  153. binaries.push_back(0);
  154. }
  155. /// Compile one argument (specialised for binarystring).
  156. void add_field(const binarystring &arg)
  157. {
  158. lengths.push_back(int(arg.size()));
  159. nonnulls.push_back(1);
  160. binaries.push_back(1);
  161. bin_strings.push_back(arg);
  162. }
  163. /// Compile one argument (default, generic implementation).
  164. /** Uses string_traits to represent the argument as a std::string.
  165. */
  166. template<typename Arg> void add_field(const Arg &arg)
  167. {
  168. if (string_traits<Arg>::is_null(arg)) add_field(nullptr);
  169. else add_field(to_string(arg));
  170. }
  171. /// Compile a dynamic_params object into a dynamic number of parameters.
  172. template<typename IT> void add_field(const dynamic_params<IT> &parameters)
  173. {
  174. for (auto param: parameters) add_field(param);
  175. }
  176. /// Compile argument list.
  177. /** This recursively "peels off" the next remaining element, compiles its
  178. * information into its final form, and calls itself for the rest of the
  179. * list.
  180. *
  181. * @param arg Current argument to be compiled.
  182. * @param args Optional remaining arguments, to be compiled recursively.
  183. */
  184. template<typename Arg, typename ...More>
  185. void add_fields(Arg &&arg, More && ... args)
  186. {
  187. add_field(std::forward<Arg>(arg));
  188. // Compile remaining arguments, if any.
  189. add_fields(std::forward<More>(args)...);
  190. }
  191. /// Terminating version of add_fields, at the end of the list.
  192. /** Recursion in add_fields ends with this call.
  193. */
  194. void add_fields() {}
  195. };
  196. } // namespace pqxx::internal
  197. } // namespace pqxx
  198. #include "pqxx/compiler-internal-post.hxx"
  199. #endif