libpqxx  7.2.1
connection.hxx
1 /* Definition of the connection class.
2  *
3  * pqxx::connection encapsulates a connection to a database.
4  *
5  * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/connection instead.
6  *
7  * Copyright (c) 2000-2020, 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_CONNECTION
14 #define PQXX_H_CONNECTION
15 
16 #include "pqxx/compiler-public.hxx"
17 #include "pqxx/internal/compiler-internal-pre.hxx"
18 
19 #include <cstddef>
20 #include <ctime>
21 #include <functional>
22 #include <list>
23 #include <map>
24 #include <memory>
25 #include <string_view>
26 #include <tuple>
27 
28 #if __has_include(<ranges>)
29 # include <ranges>
30 #endif
31 
32 #include "pqxx/errorhandler.hxx"
33 #include "pqxx/except.hxx"
34 #include "pqxx/prepared_statement.hxx"
35 #include "pqxx/strconv.hxx"
36 #include "pqxx/util.hxx"
37 #include "pqxx/zview.hxx"
38 
39 
67 namespace pqxx::internal
68 {
69 class sql_cursor;
70 
71 #if defined(PQXX_HAVE_CONCEPTS)
72 template<typename T>
74 concept ZKey_ZValues = std::ranges::input_range<T> and requires()
75 {
76  {std::tuple_size<typename std::ranges::iterator_t<T>::value_type>::value};
77 }
78 and std::tuple_size_v<typename std::ranges::iterator_t<T>::value_type> == 2 and
79  requires(T t)
80 {
81  {
82  std::get<0>(*std::cbegin(t))
83  }
84  ->ZString;
85  {
86  std::get<1>(*std::cbegin(t))
87  }
88  ->ZString;
89 };
90 #endif // PQXX_HAVE_CONCEPTS
91 } // namespace pqxx::internal
92 
93 
95 {
96 class connection_dbtransaction;
97 class connection_errorhandler;
98 class connection_largeobject;
99 class connection_notification_receiver;
100 class connection_pipeline;
101 class connection_sql_cursor;
102 class connection_stream_from;
103 class connection_stream_to;
104 class connection_transaction;
105 class const_connection_largeobject;
106 } // namespace pqxx::internal::gate
107 
108 
109 namespace pqxx
110 {
112 [[nodiscard]] std::string PQXX_LIBEXPORT
113 encrypt_password(char const user[], char const password[]);
114 
116 [[nodiscard]] inline std::string
117 encrypt_password(std::string const &user, std::string const &password)
118 {
119  return encrypt_password(user.c_str(), password.c_str());
120 }
121 
122 
124 enum class error_verbosity : int
125 {
126  // These values must match those in libpq's PGVerbosity enum.
127  terse = 0,
128  normal = 1,
129  verbose = 2
130 };
131 
132 
134 
164 class PQXX_LIBEXPORT connection
165 {
166 public:
168 
169  explicit connection(std::string const &options) : connection{options.c_str()}
170  {
171  // (Delegates to other constructor which calls check_version for us.)
172  }
173 
174  explicit connection(char const options[])
175  {
176  check_version();
177  init(options);
178  }
179 
180  explicit connection(zview options) : connection{options.c_str()}
181  {
182  // (Delegates to other constructor which calls check_version for us.)
183  }
184 
186 
191  connection(connection &&rhs);
192 
193 #if defined(PQXX_HAVE_CONCEPTS)
194 
210  template<internal::ZKey_ZValues MAPPING>
211  inline connection(MAPPING const &params);
212 #endif // PQXX_HAVE_CONCEPTS
213 
215  {
216  try
217  {
218  close();
219  }
220  catch (std::exception const &)
221  {}
222  }
223 
225 
228  connection &operator=(connection &&rhs);
229 
230  connection(connection const &) = delete;
231  connection &operator=(connection const &) = delete;
232 
234 
238  [[nodiscard]] bool PQXX_PURE is_open() const noexcept;
239 
241  void process_notice(char const[]) noexcept;
243  void process_notice(std::string const &msg) noexcept
244  {
245  process_notice(zview{msg});
246  }
248 
251  void process_notice(zview) noexcept;
252 
254  void trace(std::FILE *) noexcept;
255 
266  [[nodiscard]] char const *dbname() const;
268 
270  [[nodiscard]] char const *username() const;
271 
273  [[nodiscard]] char const *hostname() const;
274 
276  [[nodiscard]] char const *port() const;
277 
279  [[nodiscard]] int PQXX_PURE backendpid() const noexcept;
280 
282 
297  [[nodiscard]] int PQXX_PURE sock() const noexcept;
298 
300 
303  [[nodiscard]] int PQXX_PURE protocol_version() const noexcept;
304 
306 
318  [[nodiscard]] int PQXX_PURE server_version() const noexcept;
320 
322 
342  [[nodiscard]] std::string get_client_encoding() const;
344 
346 
349  void set_client_encoding(std::string const &encoding)
350  {
351  set_client_encoding(encoding.c_str());
352  }
353 
355 
358  void set_client_encoding(char const encoding[]);
359 
361  [[nodiscard]] int PQXX_PRIVATE encoding_id() const;
362 
364 
366 
381  void set_variable(std::string_view var, std::string_view value);
382 
384 
387  std::string get_variable(std::string_view);
389 
390 
395 
408  int get_notifs();
409 
410 
412 
420  int await_notification();
421 
423 
431  int await_notification(std::time_t seconds, long microseconds);
433 
435 
461  [[nodiscard]] std::string encrypt_password(
462  char const user[], char const password[], char const *algorithm = nullptr);
463  [[nodiscard]] std::string
464  encrypt_password(zview user, zview password, zview algorithm)
465  {
466  return encrypt_password(user.c_str(), password.c_str(), algorithm.c_str());
467  }
468 
497 
519  void prepare(char const name[], char const definition[]);
520 
521  void prepare(std::string const &name, std::string const &definition)
522  {
523  prepare(name.c_str(), definition.c_str());
524  }
525 
526  void prepare(zview name, zview definition)
527  {
528  prepare(name.c_str(), definition.c_str());
529  }
530 
532 
539  void prepare(char const definition[]);
540  void prepare(zview definition) { return prepare(definition.c_str()); }
541 
543  void unprepare(std::string_view name);
544 
549 
553  [[nodiscard]] std::string adorn_name(std::string_view);
554 
559 
561 
565  [[nodiscard]] std::string esc(char const text[], std::size_t maxlen) const
566  {
567  return esc(std::string_view(text, maxlen));
568  }
569 
571  [[nodiscard]] std::string esc(char const text[]) const
572  {
573  return esc(std::string_view(text));
574  }
575 
577 
580  [[nodiscard]] std::string esc(std::string_view text) const;
581 
583 
585  [[nodiscard]] std::string
586  esc_raw(unsigned char const bin[], std::size_t len) const;
587 
589  [[nodiscard]] std::string esc_raw(std::basic_string_view<std::byte>) const;
590 
592 
595  [[nodiscard]] std::string unesc_raw(std::string const &text) const
596  {
597  return unesc_raw(text.c_str());
598  }
599 
601 
604  [[nodiscard]] std::string unesc_raw(zview text) const
605  {
606  return unesc_raw(text.c_str());
607  }
608 
610 
613  [[nodiscard]] std::string unesc_raw(char const text[]) const;
614 
616 
618  [[nodiscard]] std::string
619  quote_raw(unsigned char const bin[], std::size_t len) const;
620 
622  [[nodiscard]] std::string quote_raw(std::basic_string_view<std::byte>) const;
623 
625  [[nodiscard]] std::string quote_name(std::string_view identifier) const;
626 
628 
631  template<typename T>[[nodiscard]] inline std::string quote(T const &t) const;
632 
634  [[nodiscard]] std::string quote(binarystring const &) const;
635 
636  [[nodiscard]] std::string
637  quote(std::basic_string_view<std::byte> bytes) const;
638 
640 
663  [[nodiscard]] std::string
664  esc_like(std::string_view text, char escape_char = '\\') const;
666 
668 
672  void cancel_query();
673 
675 
684  void set_verbosity(error_verbosity verbosity) noexcept;
685 
687 
699  [[nodiscard]] std::vector<errorhandler *> get_errorhandlers() const;
700 
702 
708  [[nodiscard]] std::string connection_string() const;
709 
711 
714  void close();
715 
716 private:
717  // Initialise based on connection string.
718  void init(char const options[]);
719  // Initialise based on parameter names and values.
720  void init(char const *params[], char const *values[]);
721  void complete_init();
722 
723  void wait_read() const;
724  void wait_read(std::time_t seconds, long microseconds) const;
725 
726  result make_result(
727  internal::pq::PGresult *pgr, std::shared_ptr<std::string> const &query);
728 
729  void PQXX_PRIVATE set_up_state();
730 
731  int PQXX_PRIVATE PQXX_PURE status() const noexcept;
732 
734 
738  std::size_t esc_to_buf(std::string_view text, char *buf) const;
739 
740  friend class internal::gate::const_connection_largeobject;
741  char const *PQXX_PURE err_msg() const noexcept;
742 
743  void PQXX_PRIVATE process_notice_raw(char const msg[]) noexcept;
744 
745  result exec_prepared(std::string_view statement, internal::params const &);
746 
748  void check_movable() const;
750  void check_overwritable() const;
751 
752  friend class internal::gate::connection_errorhandler;
753  void PQXX_PRIVATE register_errorhandler(errorhandler *);
754  void PQXX_PRIVATE unregister_errorhandler(errorhandler *) noexcept;
755 
756  friend class internal::gate::connection_transaction;
757  result PQXX_PRIVATE exec(std::string_view);
758  result PQXX_PRIVATE exec(std::shared_ptr<std::string>);
759  void PQXX_PRIVATE register_transaction(transaction_base *);
760  void PQXX_PRIVATE unregister_transaction(transaction_base *) noexcept;
761 
762  friend class internal::gate::connection_stream_from;
763  std::pair<std::unique_ptr<char, std::function<void(char *)>>, std::size_t>
764  PQXX_PRIVATE read_copy_line();
765 
766  friend class internal::gate::connection_stream_to;
767  void PQXX_PRIVATE write_copy_line(std::string_view);
768  void PQXX_PRIVATE end_copy_write();
769 
770  friend class internal::gate::connection_largeobject;
771  internal::pq::PGconn *raw_connection() const { return m_conn; }
772 
773  friend class internal::gate::connection_notification_receiver;
774  void add_receiver(notification_receiver *);
775  void remove_receiver(notification_receiver *) noexcept;
776 
777  friend class internal::gate::connection_pipeline;
778  void PQXX_PRIVATE start_exec(char const query[]);
779  bool PQXX_PRIVATE consume_input() noexcept;
780  bool PQXX_PRIVATE is_busy() const noexcept;
781  internal::pq::PGresult *get_result();
782 
783  friend class internal::gate::connection_dbtransaction;
784  friend class internal::gate::connection_sql_cursor;
785 
786  result exec_params(std::string_view query, internal::params const &args);
787 
789  internal::pq::PGconn *m_conn = nullptr;
790 
792  internal::unique<transaction_base> m_trans;
793 
794  std::list<errorhandler *> m_errorhandlers;
795 
796  using receiver_list =
797  std::multimap<std::string, pqxx::notification_receiver *>;
799  receiver_list m_receivers;
800 
802  int m_unique_id = 0;
803 };
804 
805 
807 using connection_base = connection;
808 
809 
810 template<typename T> inline std::string connection::quote(T const &t) const
811 {
812  if constexpr (nullness<T>::always_null)
813  {
814  return "NULL";
815  }
816  else
817  {
818  if (is_null(t))
819  return "NULL";
820  auto const text{to_string(t)};
821 
822  // Okay, there's an easy way to do this and there's a hard way. The easy
823  // way was "quote, esc(to_string(t)), quote". I'm going with the hard way
824  // because it's going to save some string manipulation that will probably
825  // incur some unnecessary memory allocations and deallocations.
826  std::string buf{'\''};
827  buf.resize(2 + 2 * std::size(text) + 1);
828  auto const content_bytes{esc_to_buf(text, buf.data() + 1)};
829  auto const closing_quote{1 + content_bytes};
830  buf[closing_quote] = '\'';
831  auto const end{closing_quote + 1};
832  buf.resize(end);
833  return buf;
834  }
835 }
836 
837 
838 #if defined(PQXX_HAVE_CONCEPTS)
839 template<internal::ZKey_ZValues MAPPING>
840 inline connection::connection(MAPPING const &params)
841 {
842  check_version();
843 
844  std::vector<char const *> keys, values;
845  if constexpr (std::ranges::sized_range<MAPPING>)
846  {
847  auto const size{std::ranges::size(params) + 1};
848  keys.reserve(size);
849  values.reserve(size);
850  }
851  for (auto const &[key, value] : params)
852  {
853  keys.push_back(internal::as_c_string(key));
854  values.push_back(internal::as_c_string(value));
855  }
856  keys.push_back(nullptr);
857  values.push_back(nullptr);
858  init(keys.data(), values.data());
859 }
860 #endif // PQXX_HAVE_CONCEPTS
861 } // namespace pqxx
862 
863 
864 namespace pqxx::internal
865 {
866 PQXX_LIBEXPORT void wait_read(internal::pq::PGconn const *);
867 PQXX_LIBEXPORT void wait_read(
868  internal::pq::PGconn const *, std::time_t seconds, long microseconds);
869 PQXX_LIBEXPORT void wait_write(internal::pq::PGconn const *);
870 } // namespace pqxx::internal
871 
872 #include "pqxx/internal/compiler-internal-post.hxx"
873 #endif
Private namespace for libpqxx&#39;s internal use; do not access.
Definition: composite.hxx:70
constexpr char const * c_str() const noexcept
Either a null pointer, or a zero-terminated text buffer.
Definition: zview.hxx:69
Base class for error-handler callbacks.
Definition: errorhandler.hxx:52
connection(std::string const &options)
Definition: connection.hxx:169
void wait_write(internal::pq::PGconn const *)
Definition: connection.cxx:972
constexpr char const * as_c_string(char const str[]) noexcept
Get a raw C string pointer.
Definition: zview.hxx:105
void prepare(zview name, zview definition)
Definition: connection.hxx:526
Connection to a database.
Definition: connection.hxx:164
Binary data corresponding to PostgreSQL&#39;s "BYTEA" binary-string type.
Definition: binarystring.hxx:56
std::string to_string(field const &value)
Convert a field to a string.
Definition: result.cxx:498
std::string unesc_raw(zview text) const
Unescape binary data, e.g. from a table field or notification payload.
Definition: connection.hxx:604
void prepare(std::string const &name, std::string const &definition)
Definition: connection.hxx:521
void set_client_encoding(std::string const &encoding)
Set client-side character encoding, by name.
Definition: connection.hxx:349
error_verbosity
Error verbosity levels.
Definition: connection.hxx:124
std::string esc(char const text[]) const
Escape string for use as SQL string literal on this connection.
Definition: connection.hxx:571
The home of all libpqxx classes, functions, templates, etc.
Definition: array.hxx:25
std::string esc(char const text[], std::size_t maxlen) const
Escape string for use as SQL string literal on this connection.
Definition: connection.hxx:565
connection(char const options[])
Definition: connection.hxx:174
~connection()
Definition: connection.hxx:214
void prepare(zview definition)
Definition: connection.hxx:540
bool is_null(TYPE const &value) noexcept
Is value null?
Definition: strconv.hxx:310
Result set containing data returned by a query or command.
Definition: result.hxx:70
STL namespace.
Marker-type wrapper: zero-terminated std::string_view.
Definition: zview.hxx:37
Definition: notification.hxx:55
void check_version()
Definition: util.hxx:144
Interface definition (and common code) for "transaction" classes.
Definition: transaction_base.hxx:67
Definition: connection.hxx:94
connection(zview options)
Definition: connection.hxx:180
std::string encrypt_password(char const user[], char const password[])
Encrypt a password.
Definition: connection.cxx:93
void wait_read(internal::pq::PGconn const *)
Definition: connection.cxx:953
std::string encrypt_password(zview user, zview password, zview algorithm)
Definition: connection.hxx:464
void process_notice(std::string const &msg) noexcept
Invoke notice processor function. Newline at end is recommended.
Definition: connection.hxx:243
connection()
Definition: connection.hxx:167
Traits describing a type&#39;s "null value," if any.
Definition: strconv.hxx:86
std::string unesc_raw(std::string const &text) const
Unescape binary data, e.g. from a table field or notification payload.
Definition: connection.hxx:595