libpqxx  7.3.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-2021, 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,
113  deprecated("Use connection::encrypt_password instead.")]] std::string
114  PQXX_LIBEXPORT
115  encrypt_password(char const user[], char const password[]);
116 
118 [[nodiscard,
119  deprecated("Use connection::encrypt_password instead.")]] inline std::string
120 encrypt_password(zview user, zview password)
121 {
122 #include "pqxx/internal/ignore-deprecated-pre.hxx"
123  return encrypt_password(user.c_str(), password.c_str());
124 #include "pqxx/internal/ignore-deprecated-post.hxx"
125 }
126 
127 
129 enum class error_verbosity : int
130 {
131  // These values must match those in libpq's PGVerbosity enum.
132  terse = 0,
133  normal = 1,
134  verbose = 2
135 };
136 
137 
139 
169 class PQXX_LIBEXPORT connection
170 {
171 public:
173 
175  explicit connection(char const options[])
176  {
177  check_version();
178  init(options);
179  }
180 
182  explicit connection(zview options) : connection{options.c_str()}
183  {
184  // (Delegates to other constructor which calls check_version for us.)
185  }
186 
188 
193  connection(connection &&rhs);
194 
195 #if defined(PQXX_HAVE_CONCEPTS)
196 
212  template<internal::ZKey_ZValues MAPPING>
213  inline connection(MAPPING const &params);
214 #endif // PQXX_HAVE_CONCEPTS
215 
217  {
218  try
219  {
220  close();
221  }
222  catch (std::exception const &)
223  {}
224  }
225 
227 
230  connection &operator=(connection &&rhs);
231 
232  connection(connection const &) = delete;
233  connection &operator=(connection const &) = delete;
234 
236 
240  [[nodiscard]] bool PQXX_PURE is_open() const noexcept;
241 
243  void process_notice(char const[]) noexcept;
245 
248  void process_notice(zview) noexcept;
249 
251  void trace(std::FILE *) noexcept;
252 
263  [[nodiscard]] char const *dbname() const;
265 
267  [[nodiscard]] char const *username() const;
268 
270  [[nodiscard]] char const *hostname() const;
271 
273  [[nodiscard]] char const *port() const;
274 
276  [[nodiscard]] int PQXX_PURE backendpid() const noexcept;
277 
279 
294  [[nodiscard]] int PQXX_PURE sock() const noexcept;
295 
297 
300  [[nodiscard]] int PQXX_PURE protocol_version() const noexcept;
301 
303 
315  [[nodiscard]] int PQXX_PURE server_version() const noexcept;
317 
319 
339  [[nodiscard]] std::string get_client_encoding() const;
341 
343 
346  void set_client_encoding(zview encoding)
347  {
348  set_client_encoding(encoding.c_str());
349  }
350 
352 
355  void set_client_encoding(char const encoding[]);
356 
358  [[nodiscard]] int PQXX_PRIVATE encoding_id() const;
359 
361 
363 
378  void set_variable(std::string_view var, std::string_view value);
379 
381 
384  std::string get_variable(std::string_view);
386 
387 
392 
405  int get_notifs();
406 
407 
409 
417  int await_notification();
418 
420 
428  int await_notification(std::time_t seconds, long microseconds);
430 
461  [[nodiscard]] std::string
463  encrypt_password(zview user, zview password, zview algorithm)
464  {
465  return encrypt_password(user.c_str(), password.c_str(), algorithm.c_str());
466  }
468  [[nodiscard]] std::string encrypt_password(
469  char const user[], char const password[], char const *algorithm = nullptr);
471 
514 
516 
520  void prepare(zview name, zview definition)
521  {
522  prepare(name.c_str(), definition.c_str());
523  }
524 
529  void prepare(char const name[], char const definition[]);
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 
546 
548 
551  [[nodiscard]] std::string adorn_name(std::string_view);
552 
557 
559 
563  [[nodiscard]] std::string esc(char const text[], std::size_t maxlen) const
564  {
565  return esc(std::string_view(text, maxlen));
566  }
567 
569  [[nodiscard]] std::string esc(char const text[]) const
570  {
571  return esc(std::string_view(text));
572  }
573 
575 
578  [[nodiscard]] std::string esc(std::string_view text) const;
579 
581 
583  [[nodiscard, deprecated("Use std::byte for binary data.")]] std::string
584  esc_raw(unsigned char const bin[], std::size_t len) const;
585 
587  [[nodiscard]] std::string esc_raw(std::basic_string_view<std::byte>) const;
588 
590 
593  [[nodiscard]] std::string unesc_raw(zview text) const
594  {
595  return unesc_raw(text.c_str());
596  }
597 
599 
602  [[nodiscard]] std::string unesc_raw(char const text[]) const;
603 
605 
607  [[nodiscard, deprecated("Use std::byte for binary data.")]] std::string
608  quote_raw(unsigned char const bin[], std::size_t len) const;
609 
611  [[nodiscard]] std::string quote_raw(std::basic_string_view<std::byte>) const;
612 
614  [[nodiscard]] std::string quote_name(std::string_view identifier) const;
615 
617 
620  template<typename T>
621  [[nodiscard]] inline std::string quote(T const &t) const;
622 
624  [[nodiscard, deprecated("Use std::byte for binary data.")]] std::string
625  quote(binarystring const &) const;
626 
628  [[nodiscard]] std::string
629  quote(std::basic_string_view<std::byte> bytes) const;
630 
632 
655  [[nodiscard]] std::string
656  esc_like(std::string_view text, char escape_char = '\\') const;
658 
660 
664  void cancel_query();
665 
667 
676  void set_verbosity(error_verbosity verbosity) noexcept;
677 
679 
691  [[nodiscard]] std::vector<errorhandler *> get_errorhandlers() const;
692 
694 
700  [[nodiscard]] std::string connection_string() const;
701 
703 
706  void close();
707 
708 private:
709  // Initialise based on connection string.
710  void init(char const options[]);
711  // Initialise based on parameter names and values.
712  void init(char const *params[], char const *values[]);
713  void complete_init();
714 
715  void wait_read() const;
716  void wait_read(std::time_t seconds, long microseconds) const;
717 
718  result make_result(
719  internal::pq::PGresult *pgr, std::shared_ptr<std::string> const &query,
720  std::string_view desc = ""sv);
721 
722  void PQXX_PRIVATE set_up_state();
723 
724  int PQXX_PRIVATE PQXX_PURE status() const noexcept;
725 
727 
731  std::size_t esc_to_buf(std::string_view text, char *buf) const;
732 
733  friend class internal::gate::const_connection_largeobject;
734  char const *PQXX_PURE err_msg() const noexcept;
735 
736  void PQXX_PRIVATE process_notice_raw(char const msg[]) noexcept;
737 
738  result exec_prepared(std::string_view statement, internal::params const &);
739 
741  void check_movable() const;
743  void check_overwritable() const;
744 
745  friend class internal::gate::connection_errorhandler;
746  void PQXX_PRIVATE register_errorhandler(errorhandler *);
747  void PQXX_PRIVATE unregister_errorhandler(errorhandler *) noexcept;
748 
749  friend class internal::gate::connection_transaction;
750  result PQXX_PRIVATE exec(std::string_view, std::string_view = ""sv);
751  result
752  PQXX_PRIVATE exec(std::shared_ptr<std::string>, std::string_view = ""sv);
753  void PQXX_PRIVATE register_transaction(transaction_base *);
754  void PQXX_PRIVATE unregister_transaction(transaction_base *) noexcept;
755 
756  friend class internal::gate::connection_stream_from;
757  std::pair<std::unique_ptr<char, std::function<void(char *)>>, std::size_t>
758  PQXX_PRIVATE read_copy_line();
759 
760  friend class internal::gate::connection_stream_to;
761  void PQXX_PRIVATE write_copy_line(std::string_view);
762  void PQXX_PRIVATE end_copy_write();
763 
764  friend class internal::gate::connection_largeobject;
765  internal::pq::PGconn *raw_connection() const { return m_conn; }
766 
767  friend class internal::gate::connection_notification_receiver;
768  void add_receiver(notification_receiver *);
769  void remove_receiver(notification_receiver *) noexcept;
770 
771  friend class internal::gate::connection_pipeline;
772  void PQXX_PRIVATE start_exec(char const query[]);
773  bool PQXX_PRIVATE consume_input() noexcept;
774  bool PQXX_PRIVATE is_busy() const noexcept;
775  internal::pq::PGresult *get_result();
776 
777  friend class internal::gate::connection_dbtransaction;
778  friend class internal::gate::connection_sql_cursor;
779 
780  result exec_params(std::string_view query, internal::params const &args);
781 
783  internal::pq::PGconn *m_conn = nullptr;
784 
786 
793  transaction_base const *m_trans = nullptr;
794 
795  std::list<errorhandler *> m_errorhandlers;
796 
797  using receiver_list =
798  std::multimap<std::string, pqxx::notification_receiver *>;
800  receiver_list m_receivers;
801 
803  int m_unique_id = 0;
804 };
805 
806 
808 using connection_base = connection;
809 
810 
811 template<typename T> inline std::string connection::quote(T const &t) const
812 {
813  if constexpr (nullness<T>::always_null)
814  {
815  return "NULL";
816  }
817  else
818  {
819  if (is_null(t))
820  return "NULL";
821  auto const text{to_string(t)};
822 
823  // Okay, there's an easy way to do this and there's a hard way. The easy
824  // way was "quote, esc(to_string(t)), quote". I'm going with the hard way
825  // because it's going to save some string manipulation that will probably
826  // incur some unnecessary memory allocations and deallocations.
827  std::string buf{'\''};
828  buf.resize(2 + 2 * std::size(text) + 1);
829  auto const content_bytes{esc_to_buf(text, buf.data() + 1)};
830  auto const closing_quote{1 + content_bytes};
831  buf[closing_quote] = '\'';
832  auto const end{closing_quote + 1};
833  buf.resize(end);
834  return buf;
835  }
836 }
837 
838 
839 #if defined(PQXX_HAVE_CONCEPTS)
840 template<internal::ZKey_ZValues MAPPING>
841 inline connection::connection(MAPPING const &params)
842 {
843  check_version();
844 
845  std::vector<char const *> keys, values;
846  if constexpr (std::ranges::sized_range<MAPPING>)
847  {
848  auto const size{std::ranges::size(params) + 1};
849  keys.reserve(size);
850  values.reserve(size);
851  }
852  for (auto const &[key, value] : params)
853  {
854  keys.push_back(internal::as_c_string(key));
855  values.push_back(internal::as_c_string(value));
856  }
857  keys.push_back(nullptr);
858  values.push_back(nullptr);
859  init(keys.data(), values.data());
860 }
861 #endif // PQXX_HAVE_CONCEPTS
862 } // namespace pqxx
863 
864 
865 namespace pqxx::internal
866 {
867 PQXX_LIBEXPORT void wait_read(internal::pq::PGconn const *);
868 PQXX_LIBEXPORT void wait_read(
869  internal::pq::PGconn const *, std::time_t seconds, long microseconds);
870 PQXX_LIBEXPORT void wait_write(internal::pq::PGconn const *);
871 } // namespace pqxx::internal
872 
873 #include "pqxx/internal/compiler-internal-post.hxx"
874 #endif
void wait_read(internal::pq::PGconn const *)
Definition: connection.cxx:977
Interface definition (and common code) for "transaction" classes.
Definition: transaction_base.hxx:71
bool is_null(TYPE const &value) noexcept
Is value null?
Definition: strconv.hxx:353
The home of all libpqxx classes, functions, templates, etc.
Definition: array.hxx:25
Binary data corresponding to PostgreSQL&#39;s "BYTEA" binary-string type.
Definition: binarystring.hxx:56
std::string esc(char const text[]) const
Escape string for use as SQL string literal on this connection.
Definition: connection.hxx:569
Base class for error-handler callbacks.
Definition: errorhandler.hxx:52
void prepare(zview definition)
Definition: connection.hxx:540
STL namespace.
connection()
Definition: connection.hxx:172
Marker-type wrapper: zero-terminated std::string_view.
Definition: zview.hxx:37
connection(char const options[])
Connect to a database, using options string.
Definition: connection.hxx:175
Result set containing data returned by a query or command.
Definition: result.hxx:70
connection(zview options)
Connect to a database, using options string.
Definition: connection.hxx:182
Definition: notification.hxx:55
Definition: connection.hxx:94
std::string unesc_raw(zview text) const
Unescape binary data, e.g. from a table field or notification payload.
Definition: connection.hxx:593
std::string to_string(field const &value)
Convert a field to a string.
Definition: result.cxx:503
std::string encrypt_password(zview user, zview password, zview algorithm)
Encrypt a password for a given user.
Definition: connection.hxx:463
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:563
std::string encrypt_password(char const user[], char const password[])
Encrypt a password.
Definition: connection.cxx:95
constexpr char const * as_c_string(char const str[]) noexcept
Get a raw C string pointer.
Definition: zview.hxx:121
void prepare(zview name, zview definition)
Define a prepared statement.
Definition: connection.hxx:520
void check_version()
Definition: util.hxx:167
void set_client_encoding(zview encoding)
Set client-side character encoding, by name.
Definition: connection.hxx:346
constexpr char const * c_str() const noexcept
Either a null pointer, or a zero-terminated text buffer.
Definition: zview.hxx:85
Internal items for libpqxx&#39; own use. Do not use these yourself.
Definition: composite.hxx:73
~connection()
Definition: connection.hxx:216
void wait_write(internal::pq::PGconn const *)
Definition: connection.cxx:996
Connection to a database.
Definition: connection.hxx:169
Traits describing a type&#39;s "null value," if any.
Definition: strconv.hxx:86
error_verbosity
Error verbosity levels.
Definition: connection.hxx:129