libpqxx  3.1.1
connection_base.hxx
1 /*-------------------------------------------------------------------------
2  *
3  * FILE
4  * pqxx/connection_base.hxx
5  *
6  * DESCRIPTION
7  * definition of the pqxx::connection_base abstract base class.
8  * pqxx::connection_base encapsulates a frontend to backend connection
9  * DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/connection_base instead.
10  *
11  * Copyright (c) 2001-2009, Jeroen T. Vermeulen <jtv@xs4all.nl>
12  *
13  * See COPYING for copyright license. If you did not receive a file called
14  * COPYING with this source code, please notify the distributor of this mistake,
15  * or contact the author.
16  *
17  *-------------------------------------------------------------------------
18  */
19 #ifndef PQXX_H_CONNECTION_BASE
20 #define PQXX_H_CONNECTION_BASE
21 
22 #include "pqxx/compiler-public.hxx"
23 #include "pqxx/compiler-internal-pre.hxx"
24 
25 #include <bitset>
26 #include <map>
27 #include <memory>
28 
29 #include "pqxx/except"
30 #include "pqxx/prepared_statement"
31 #include "pqxx/strconv"
32 #include "pqxx/util"
33 
34 
35 /* Use of the libpqxx library starts here.
36  *
37  * Everything that can be done with a database through libpqxx must go through
38  * a connection object derived from connection_base.
39  */
40 
41 /* Methods tested in eg. self-test program test1 are marked with "//[t1]"
42  */
43 
44 namespace pqxx
45 {
46 class result;
47 class transaction_base;
48 class notify_listener;
49 class connectionpolicy;
50 
51 namespace internal
52 {
53 class reactivation_avoidance_exemption;
54 class sql_cursor;
55 
57 {
58 public:
59  reactivation_avoidance_counter() : m_counter(0) {}
60 
61  void add(int n) throw () { m_counter += n; }
62  void clear() throw () { m_counter = 0; }
63  int get() const throw () { return m_counter; }
64 
65 private:
66  int m_counter;
67 };
68 
69 }
70 
76 
77 
82 struct PQXX_LIBEXPORT PQXX_NOVTABLE noticer :
83  PGSTD::unary_function<const char[], void>
84 {
85  noticer(){} // Silences bogus warning in some gcc versions
86  virtual ~noticer() throw () {}
87  virtual void operator()(const char Msg[]) throw () =0;
88 };
89 
90 
92 struct PQXX_LIBEXPORT nonnoticer : noticer
93 {
94  nonnoticer(){} // Silences bogus warning in some gcc versions
95  virtual void operator()(const char []) throw () {}
96 };
97 
102 
103 
121 PGSTD::string PQXX_LIBEXPORT encrypt_password( //[t0]
122  const PGSTD::string &user,
123  const PGSTD::string &password);
124 
125 
126 namespace internal
127 {
128 namespace gate
129 {
130 class connection_dbtransaction;
131 class connection_largeobject;
132 class connection_notify_listener;
133 class connection_parameterized_invocation;
134 class connection_pipeline;
135 class connection_prepare_declaration;
136 class connection_prepare_invocation;
137 class connection_reactivation_avoidance_exemption;
138 class connection_sql_cursor;
139 class connection_transaction;
140 } // namespace pqxx::internal::gate
141 } // namespace pqxx::internal
142 
143 
145 
178 class PQXX_LIBEXPORT connection_base
179 {
180 public:
182  void disconnect() throw (); //[t2]
183 
185 
189  bool is_open() const throw (); //[t1]
190 
201 
202 
212  void activate(); //[t12]
213 
215 
223  void deactivate(); //[t12]
224 
226 
270  void inhibit_reactivation(bool inhibit) //[t86]
271  { m_inhibit_reactivation=inhibit; }
272 
274 
279  void simulate_failure(); //[t94]
281 
291 
293 
305  PGSTD::auto_ptr<noticer> set_noticer(PGSTD::auto_ptr<noticer> N)
306  throw (); //[t14]
307  noticer *get_noticer() const throw () { return m_Noticer.get(); } //[t14]
308 
310  void process_notice(const char[]) throw (); //[t14]
312  void process_notice(const PGSTD::string &) throw (); //[t14]
313 
315 
317  void trace(FILE *) throw (); //[t3]
318 
327 
328 
331  const char *dbname(); //[t1]
332 
334 
337  const char *username(); //[t1]
338 
340 
343  const char *hostname(); //[t1]
344 
346 
349  const char *port(); //[t1]
350 
352 
361  int backendpid() const throw (); //[t1]
362 
364 
378  int sock() const throw (); //[t87]
379 
390 
393  {
396 
399 
402 
411 
414 
417 
420 
423 
426 
428  cap_end
429  };
430 
431 
433 
449  bool supports(capability c) const throw () { return m_caps.test(c); } //[t88]
450 
452 
464  int protocol_version() const throw (); //[t1]
465 
467 
479  int server_version() const throw (); //[t1]
481 
483 
489  void set_client_encoding(const PGSTD::string &Encoding) //[t7]
490  { set_variable("CLIENT_ENCODING", Encoding); }
491 
493 
509  void set_variable(const PGSTD::string &Var,
510  const PGSTD::string &Value); //[t60]
511 
513 
520  PGSTD::string get_variable(const PGSTD::string &); //[t60]
522 
523 
528 
529 
541  int get_notifs(); //[t4]
542 
543 
545 
551  int await_notification(); //[t78]
552 
554 
560  int await_notification(long seconds, long microseconds); //[t79]
562 
563 
600 
601 
643  prepare::declaration prepare(const PGSTD::string &name,
644  const PGSTD::string &definition);
645 
647 
653  prepare::declaration prepare(const PGSTD::string &definition);
654 
656  void unprepare(const PGSTD::string &name);
657 
659 
669  void prepare_now(const PGSTD::string &name);
670 
700 
701 
709  template<typename TRANSACTOR>
710  void perform(const TRANSACTOR &T, int Attempts); //[t4]
711 
713 
716  template<typename TRANSACTOR>
717  void perform(const TRANSACTOR &T) { perform(T, 3); }
718 
723 
724 
727  PGSTD::string adorn_name(const PGSTD::string &); //[90]
728 
797 
798  PGSTD::string esc(const char str[]);
799 
801  PGSTD::string esc(const char str[], size_t maxlen);
802 
804  PGSTD::string esc(const PGSTD::string &str);
805 
807  PGSTD::string esc_raw(const unsigned char str[], size_t len);
808 
810 
811  template<typename T>
812  PGSTD::string quote(const T &t)
813  {
814  if (string_traits<T>::is_null(t)) return "NULL";
815  return "'" + this->esc(to_string(t)) + "'";
816  }
818 
820  void cancel_query();
821 
822 protected:
823  explicit connection_base(connectionpolicy &);
824  void init();
825 
826  void close() throw ();
827  void wait_read() const;
828  void wait_read(long seconds, long microseconds) const;
829  void wait_write() const;
830 
831 private:
832  result make_result(internal::pq::PGresult *rhs, const PGSTD::string &query);
833 
834  void PQXX_PRIVATE clearcaps() throw ();
835  void PQXX_PRIVATE SetupState();
836  void PQXX_PRIVATE check_result(const result &);
837 
838  void PQXX_PRIVATE InternalSetTrace() throw ();
839  int PQXX_PRIVATE Status() const throw ();
840  const char *ErrMsg() const throw ();
841  void PQXX_PRIVATE Reset();
842  void PQXX_PRIVATE RestoreVars();
843  PGSTD::string PQXX_PRIVATE RawGetVar(const PGSTD::string &);
844  void PQXX_PRIVATE process_notice_raw(const char msg[]) throw ();
845  void switchnoticer(const PGSTD::auto_ptr<noticer> &) throw ();
846 
847  void read_capabilities() throw ();
848 
849  prepare::internal::prepared_def &find_prepared(const PGSTD::string &);
850 
851  friend class internal::gate::connection_prepare_declaration;
852  void prepare_param_declare(
853  const PGSTD::string &statement,
854  const PGSTD::string &sqltype,
855  prepare::param_treatment);
856  void prepare_param_declare_varargs(
857  const PGSTD::string &statement,
858  prepare::param_treatment);
859 
860  prepare::internal::prepared_def &register_prepared(const PGSTD::string &);
861 
862  friend class internal::gate::connection_prepare_invocation;
863  result prepared_exec(const PGSTD::string &,
864  const char *const[],
865  const int[],
866  int);
867  bool prepared_exists(const PGSTD::string &) const;
868 
870  internal::pq::PGconn *m_Conn;
871 
872  connectionpolicy &m_policy;
873 
875  internal::unique<transaction_base> m_Trans;
876 
878  PGSTD::auto_ptr<noticer> m_Noticer;
879 
881 
885  internal::pq::PQnoticeProcessor m_defaultNoticeProcessor;
886 
888  FILE *m_Trace;
889 
890  typedef PGSTD::multimap<PGSTD::string, pqxx::notify_listener *> listenerlist;
892  listenerlist m_listeners;
893 
895  PGSTD::map<PGSTD::string, PGSTD::string> m_Vars;
896 
897  typedef PGSTD::map<PGSTD::string, prepare::internal::prepared_def> PSMap;
898 
900  PSMap m_prepared;
901 
903  int m_serverversion;
904 
906  internal::reactivation_avoidance_counter m_reactivation_avoidance;
907 
909  int m_unique_id;
910 
912  bool m_Completed;
913 
915  bool m_inhibit_reactivation;
916 
918  PGSTD::bitset<cap_end> m_caps;
919 
920  friend class internal::gate::connection_transaction;
921  result PQXX_PRIVATE Exec(const char[], int Retries);
922  void PQXX_PRIVATE RegisterTransaction(transaction_base *);
923  void PQXX_PRIVATE UnregisterTransaction(transaction_base *) throw ();
924  bool PQXX_PRIVATE ReadCopyLine(PGSTD::string &);
925  void PQXX_PRIVATE WriteCopyLine(const PGSTD::string &);
926  void PQXX_PRIVATE EndCopyWrite();
927  void PQXX_PRIVATE RawSetVar(const PGSTD::string &, const PGSTD::string &);
928  void PQXX_PRIVATE AddVariables(const PGSTD::map<PGSTD::string,
929  PGSTD::string> &);
930 
931  friend class internal::gate::connection_largeobject;
932  internal::pq::PGconn *RawConnection() const { return m_Conn; }
933 
934  friend class internal::gate::connection_notify_listener;
935  void add_listener(notify_listener *);
936  void remove_listener(notify_listener *) throw ();
937 
938  friend class internal::gate::connection_pipeline;
939  void PQXX_PRIVATE start_exec(const PGSTD::string &);
940  bool PQXX_PRIVATE consume_input() throw ();
941  bool PQXX_PRIVATE is_busy() const throw ();
942  int PQXX_PRIVATE encoding_code() throw ();
943  internal::pq::PGresult *get_result();
944 
945  friend class internal::gate::connection_dbtransaction;
946 
947  friend class internal::gate::connection_sql_cursor;
948  void add_reactivation_avoidance_count(int);
949 
950  friend class internal::gate::connection_reactivation_avoidance_exemption;
951 
952  friend class internal::gate::connection_parameterized_invocation;
953  result parameterized_exec(
954  const PGSTD::string &query,
955  const char *const params[],
956  const int paramlengths[],
957  int nparams);
958 
959  // Not allowed:
961  connection_base &operator=(const connection_base &);
962 };
963 
964 
965 
967 
973 class PQXX_LIBEXPORT scoped_noticer
974 {
975 public:
977 
981  scoped_noticer(connection_base &c, PGSTD::auto_ptr<noticer> t) throw () :
982  m_c(c), m_org(c.set_noticer(t)) { }
983 
984  ~scoped_noticer() { m_c.set_noticer(m_org); }
985 
986 protected:
988 
992  scoped_noticer(connection_base &c, noticer *t) throw () :
993  m_c(c),
994  m_org()
995  {
996  PGSTD::auto_ptr<noticer> x(t);
997  PGSTD::auto_ptr<noticer> y(c.set_noticer(x));
998  m_org = y;
999  }
1000 
1001 private:
1002  connection_base &m_c;
1003  PGSTD::auto_ptr<noticer> m_org;
1004 
1006  scoped_noticer();
1007  scoped_noticer(const scoped_noticer &);
1008  scoped_noticer operator=(const scoped_noticer &);
1009 };
1010 
1011 
1013 class PQXX_LIBEXPORT disable_noticer : scoped_noticer
1014 {
1015 public:
1016  explicit disable_noticer(connection_base &c) :
1017  scoped_noticer(c, new nonnoticer) {}
1018 };
1019 
1020 
1021 namespace internal
1022 {
1023 
1026 {
1027 public:
1028  explicit reactivation_avoidance_exemption(connection_base &C);
1030 
1031  void close_connection() throw () { m_open = false; }
1032 
1033 private:
1034  connection_base &m_home;
1035  int m_count;
1036  bool m_open;
1037 };
1038 
1039 
1040 void wait_read(const internal::pq::PGconn *);
1041 void wait_read(const internal::pq::PGconn *, long seconds, long microseconds);
1042 void wait_write(const internal::pq::PGconn *);
1043 } // namespace pqxx::internal
1044 
1045 
1046 } // namespace pqxx
1047 
1048 #include "pqxx/compiler-internal-post.hxx"
1049 
1050 #endif
1051