libpqxx  7.3.0
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 encrypt_password(zview user, zview password)
117 {
118  return encrypt_password(user.c_str(), password.c_str());
119 }
120 
121 
123 enum class error_verbosity : int
124 {
125  // These values must match those in libpq's PGVerbosity enum.
126  terse = 0,
127  normal = 1,
128  verbose = 2
129 };
130 
131 
133 
163 class PQXX_LIBEXPORT connection
164 {
165 public:
167 
168  explicit connection(char const options[])
169  {
170  check_version();
171  init(options);
172  }
173 
174  explicit connection(zview options) : connection{options.c_str()}
175  {
176  // (Delegates to other constructor which calls check_version for us.)
177  }
178 
180 
185  connection(connection &&rhs);
186 
187 #if defined(PQXX_HAVE_CONCEPTS)
188 
204  template<internal::ZKey_ZValues MAPPING>
205  inline connection(MAPPING const &params);
206 #endif // PQXX_HAVE_CONCEPTS
207 
209  {
210  try
211  {
212  close();
213  }
214  catch (std::exception const &)
215  {}
216  }
217 
219 
222  connection &operator=(connection &&rhs);
223 
224  connection(connection const &) = delete;
225  connection &operator=(connection const &) = delete;
226 
228 
232  [[nodiscard]] bool PQXX_PURE is_open() const noexcept;
233 
235  void process_notice(char const[]) noexcept;
237 
240  void process_notice(zview) noexcept;
241 
243  void trace(std::FILE *) noexcept;
244 
255  [[nodiscard]] char const *dbname() const;
257 
259  [[nodiscard]] char const *username() const;
260 
262  [[nodiscard]] char const *hostname() const;
263 
265  [[nodiscard]] char const *port() const;
266 
268  [[nodiscard]] int PQXX_PURE backendpid() const noexcept;
269 
271 
286  [[nodiscard]] int PQXX_PURE sock() const noexcept;
287 
289 
292  [[nodiscard]] int PQXX_PURE protocol_version() const noexcept;
293 
295 
307  [[nodiscard]] int PQXX_PURE server_version() const noexcept;
309 
311 
331  [[nodiscard]] std::string get_client_encoding() const;
333 
335 
338  void set_client_encoding(zview encoding)
339  {
340  set_client_encoding(encoding.c_str());
341  }
342 
344 
347  void set_client_encoding(char const encoding[]);
348 
350  [[nodiscard]] int PQXX_PRIVATE encoding_id() const;
351 
353 
355 
370  void set_variable(std::string_view var, std::string_view value);
371 
373 
376  std::string get_variable(std::string_view);
378 
379 
384 
397  int get_notifs();
398 
399 
401 
409  int await_notification();
410 
412 
420  int await_notification(std::time_t seconds, long microseconds);
422 
424 
450  [[nodiscard]] std::string encrypt_password(
451  char const user[], char const password[], char const *algorithm = nullptr);
452  [[nodiscard]] std::string
453  encrypt_password(zview user, zview password, zview algorithm)
454  {
455  return encrypt_password(user.c_str(), password.c_str(), algorithm.c_str());
456  }
457 
486 
508  void prepare(char const name[], char const definition[]);
509 
510  void prepare(zview name, zview definition)
511  {
512  prepare(name.c_str(), definition.c_str());
513  }
514 
516 
523  void prepare(char const definition[]);
524  void prepare(zview definition) { return prepare(definition.c_str()); }
525 
527  void unprepare(std::string_view name);
528 
533 
537  [[nodiscard]] std::string adorn_name(std::string_view);
538 
543 
545 
549  [[nodiscard]] std::string esc(char const text[], std::size_t maxlen) const
550  {
551  return esc(std::string_view(text, maxlen));
552  }
553 
555  [[nodiscard]] std::string esc(char const text[]) const
556  {
557  return esc(std::string_view(text));
558  }
559 
561 
564  [[nodiscard]] std::string esc(std::string_view text) const;
565 
567 
569  [[nodiscard]] std::string
570  esc_raw(unsigned char const bin[], std::size_t len) const;
571 
573  [[nodiscard]] std::string esc_raw(std::basic_string_view<std::byte>) const;
574 
576 
579  [[nodiscard]] std::string unesc_raw(zview text) const
580  {
581  return unesc_raw(text.c_str());
582  }
583 
585 
588  [[nodiscard]] std::string unesc_raw(char const text[]) const;
589 
591 
593  [[nodiscard]] std::string
594  quote_raw(unsigned char const bin[], std::size_t len) const;
595 
597  [[nodiscard]] std::string quote_raw(std::basic_string_view<std::byte>) const;
598 
600  [[nodiscard]] std::string quote_name(std::string_view identifier) const;
601 
603 
606  template<typename T>
607  [[nodiscard]] inline std::string quote(T const &t) const;
608 
610  [[nodiscard]] std::string quote(binarystring const &) const;
611 
612  [[nodiscard]] std::string
613  quote(std::basic_string_view<std::byte> bytes) const;
614 
616 
639  [[nodiscard]] std::string
640  esc_like(std::string_view text, char escape_char = '\\') const;
642 
644 
648  void cancel_query();
649 
651 
660  void set_verbosity(error_verbosity verbosity) noexcept;
661 
663 
675  [[nodiscard]] std::vector<errorhandler *> get_errorhandlers() const;
676 
678 
684  [[nodiscard]] std::string connection_string() const;
685 
687 
690  void close();
691 
692 private:
693  // Initialise based on connection string.
694  void init(char const options[]);
695  // Initialise based on parameter names and values.
696  void init(char const *params[], char const *values[]);
697  void complete_init();
698 
699  void wait_read() const;
700  void wait_read(std::time_t seconds, long microseconds) const;
701 
702  result make_result(
703  internal::pq::PGresult *pgr, std::shared_ptr<std::string> const &query);
704 
705  void PQXX_PRIVATE set_up_state();
706 
707  int PQXX_PRIVATE PQXX_PURE status() const noexcept;
708 
710 
714  std::size_t esc_to_buf(std::string_view text, char *buf) const;
715 
716  friend class internal::gate::const_connection_largeobject;
717  char const *PQXX_PURE err_msg() const noexcept;
718 
719  void PQXX_PRIVATE process_notice_raw(char const msg[]) noexcept;
720 
721  result exec_prepared(std::string_view statement, internal::params const &);
722 
724  void check_movable() const;
726  void check_overwritable() const;
727 
728  friend class internal::gate::connection_errorhandler;
729  void PQXX_PRIVATE register_errorhandler(errorhandler *);
730  void PQXX_PRIVATE unregister_errorhandler(errorhandler *) noexcept;
731 
732  friend class internal::gate::connection_transaction;
733  result PQXX_PRIVATE exec(std::string_view);
734  result PQXX_PRIVATE exec(std::shared_ptr<std::string>);
735  void PQXX_PRIVATE register_transaction(transaction_base *);
736  void PQXX_PRIVATE unregister_transaction(transaction_base *) noexcept;
737 
738  friend class internal::gate::connection_stream_from;
739  std::pair<std::unique_ptr<char, std::function<void(char *)>>, std::size_t>
740  PQXX_PRIVATE read_copy_line();
741 
742  friend class internal::gate::connection_stream_to;
743  void PQXX_PRIVATE write_copy_line(std::string_view);
744  void PQXX_PRIVATE end_copy_write();
745 
746  friend class internal::gate::connection_largeobject;
747  internal::pq::PGconn *raw_connection() const { return m_conn; }
748 
749  friend class internal::gate::connection_notification_receiver;
750  void add_receiver(notification_receiver *);
751  void remove_receiver(notification_receiver *) noexcept;
752 
753  friend class internal::gate::connection_pipeline;
754  void PQXX_PRIVATE start_exec(char const query[]);
755  bool PQXX_PRIVATE consume_input() noexcept;
756  bool PQXX_PRIVATE is_busy() const noexcept;
757  internal::pq::PGresult *get_result();
758 
759  friend class internal::gate::connection_dbtransaction;
760  friend class internal::gate::connection_sql_cursor;
761 
762  result exec_params(std::string_view query, internal::params const &args);
763 
765  internal::pq::PGconn *m_conn = nullptr;
766 
768 
775  transaction_base const *m_trans = nullptr;
776 
777  std::list<errorhandler *> m_errorhandlers;
778 
779  using receiver_list =
780  std::multimap<std::string, pqxx::notification_receiver *>;
782  receiver_list m_receivers;
783 
785  int m_unique_id = 0;
786 };
787 
788 
790 using connection_base = connection;
791 
792 
793 template<typename T> inline std::string connection::quote(T const &t) const
794 {
795  if constexpr (nullness<T>::always_null)
796  {
797  return "NULL";
798  }
799  else
800  {
801  if (is_null(t))
802  return "NULL";
803  auto const text{to_string(t)};
804 
805  // Okay, there's an easy way to do this and there's a hard way. The easy
806  // way was "quote, esc(to_string(t)), quote". I'm going with the hard way
807  // because it's going to save some string manipulation that will probably
808  // incur some unnecessary memory allocations and deallocations.
809  std::string buf{'\''};
810  buf.resize(2 + 2 * std::size(text) + 1);
811  auto const content_bytes{esc_to_buf(text, buf.data() + 1)};
812  auto const closing_quote{1 + content_bytes};
813  buf[closing_quote] = '\'';
814  auto const end{closing_quote + 1};
815  buf.resize(end);
816  return buf;
817  }
818 }
819 
820 
821 #if defined(PQXX_HAVE_CONCEPTS)
822 template<internal::ZKey_ZValues MAPPING>
823 inline connection::connection(MAPPING const &params)
824 {
825  check_version();
826 
827  std::vector<char const *> keys, values;
828  if constexpr (std::ranges::sized_range<MAPPING>)
829  {
830  auto const size{std::ranges::size(params) + 1};
831  keys.reserve(size);
832  values.reserve(size);
833  }
834  for (auto const &[key, value] : params)
835  {
836  keys.push_back(internal::as_c_string(key));
837  values.push_back(internal::as_c_string(value));
838  }
839  keys.push_back(nullptr);
840  values.push_back(nullptr);
841  init(keys.data(), values.data());
842 }
843 #endif // PQXX_HAVE_CONCEPTS
844 } // namespace pqxx
845 
846 
847 namespace pqxx::internal
848 {
849 PQXX_LIBEXPORT void wait_read(internal::pq::PGconn const *);
850 PQXX_LIBEXPORT void wait_read(
851  internal::pq::PGconn const *, std::time_t seconds, long microseconds);
852 PQXX_LIBEXPORT void wait_write(internal::pq::PGconn const *);
853 } // namespace pqxx::internal
854 
855 #include "pqxx/internal/compiler-internal-post.hxx"
856 #endif
Internal items for libpqxx&#39; own use. Do not use these yourself.
Definition: composite.hxx:73
~connection()
Definition: connection.hxx:208
Definition: notification.hxx:55
Base class for error-handler callbacks.
Definition: errorhandler.hxx:52
Interface definition (and common code) for "transaction" classes.
Definition: transaction_base.hxx:71
connection(char const options[])
Definition: connection.hxx:168
void wait_write(internal::pq::PGconn const *)
Definition: connection.cxx:984
constexpr char const * as_c_string(char const str[]) noexcept
Get a raw C string pointer.
Definition: zview.hxx:112
std::string to_string(field const &value)
Convert a field to a string.
Definition: result.cxx:499
std::string unesc_raw(zview text) const
Unescape binary data, e.g. from a table field or notification payload.
Definition: connection.hxx:579
Traits describing a type&#39;s "null value," if any.
Definition: strconv.hxx:86
error_verbosity
Error verbosity levels.
Definition: connection.hxx:123
std::string esc(char const text[]) const
Escape string for use as SQL string literal on this connection.
Definition: connection.hxx:555
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:549
connection(zview options)
Definition: connection.hxx:174
bool is_null(TYPE const &value) noexcept
Is value null?
Definition: strconv.hxx:331
void prepare(zview name, zview definition)
Definition: connection.hxx:510
Connection to a database.
Definition: connection.hxx:163
void prepare(zview definition)
Definition: connection.hxx:524
constexpr char const * c_str() const noexcept
Either a null pointer, or a zero-terminated text buffer.
Definition: zview.hxx:76
STL namespace.
std::string encrypt_password(zview user, zview password, zview algorithm)
Definition: connection.hxx:453
void check_version()
Definition: util.hxx:167
Definition: connection.hxx:94
Binary data corresponding to PostgreSQL&#39;s "BYTEA" binary-string type.
Definition: binarystring.hxx:56
Marker-type wrapper: zero-terminated std::string_view.
Definition: zview.hxx:37
std::string encrypt_password(char const user[], char const password[])
Encrypt a password.
Definition: connection.cxx:95
connection()
Definition: connection.hxx:166
Result set containing data returned by a query or command.
Definition: result.hxx:70
void wait_read(internal::pq::PGconn const *)
Definition: connection.cxx:965
void set_client_encoding(zview encoding)
Set client-side character encoding, by name.
Definition: connection.hxx:338