YAPOG  0.0.1
Yet Another Pokemon Online Game
pgstream.hpp
Go to the documentation of this file.
1 /*
2 pgstream.h: include file for the pgstream library.
3 Copyright (c) 2004-2012, Daniel Verite.
4 See COPYING file for license terms.
5 http://www.manitou-mail.org/pgstream
6 */
7 
8 #ifndef INC_PGSTREAM_H
9 #define INC_PGSTREAM_H
10 
11 #include <libpq-fe.h>
12 #include <string>
13 #include <vector>
14 
15 #include "YAPOG/Macros.hpp"
16 
17 namespace pgs
18 {
19  class sql_null
20  {
21  public:
22  sql_null() {}
23  ~sql_null() {}
24  private:
25  int m_placeholder; /* avoid a MSVC++ bug with empty classes */
26  };
27 
30  {
31  public:
32  pg_excpt() {}
33  pg_excpt(const char* e_query, const char *msg, std::string code="") {
34  if (e_query)
35  m_query=e_query;
36  else
37  m_query="";
38  m_err_msg=msg;
39  m_err_code=code;
40  }
41  virtual ~pg_excpt() {}
42  std::string query() const { return m_query; }
43  std::string errmsg() const { return m_err_msg; }
44  std::string errcode() const { return m_err_code; }
45  std::string full_error_txt() const;
46 
47  static pg_excpt mk_excpt(PGresult *r, const char* query=NULL);
48  private:
49  std::string m_query;
50  std::string m_err_msg;
51  std::string m_err_code;
52  };
53 
54 
56  {
57  friend class pg_stream;
58  friend class pg_trans;
59  public:
60  pg_cnx(PGconn* conn=NULL);
61  virtual ~pg_cnx();
62  PGconn* conn() {
63  return m_conn;
64  }
65  void connect(const char* cnx_string);
66  void set_option(const char* param, bool bvalue);
67  bool get_option(const char* param) const;
68  private:
69  bool opt_true_false(const char* value, bool* b);
70  PGconn* m_conn;
71  std::string m_connect_string;
72 
73  // true if we should close the connection when the object is destroyed
75 
76  protected:
77  // m_default_prepare
78  // true: use PQexecPrepared
79  // false: don't prepare statements
81 
82  // m_inline_params
83  // true: replace the bind variables by their values inside the sql statement
84  // false: pass the values outside the sql sentence (use PQexecParams
85  // or PQexecPrepared)
87 
88  // true if we're allowed to use nested transactions
90  };
91 
93  {
94  public:
95  pg_stmt(const char* stmt, pg_cnx& db);
96  pg_stmt(const std::string stmt, pg_cnx& db);
97  virtual ~pg_stmt();
98  private:
99  PGresult* m_res;
100  void execute(const char* stmt, pg_cnx& db);
101  };
102 
104  {
105  public:
106  pg_trans(pg_cnx& cnx);
107  virtual ~pg_trans();
108  void commit();
109  void rollback();
110  private:
112 
113  bool m_begin; // if we have issued a BEGIN
114  bool m_trans_done; // if we have issued a COMMIT or ROLLBACK
115  bool m_savepoint; // if we have issued a SAVEPOINT
116  };
117 
120  {
121  public:
123  sql_bind_param(const std::string s, int param_pos) {
124  m_name=s;
125  m_initial_offset=m_offset=param_pos;
126  m_null=false;
127  }
128  virtual ~sql_bind_param() {}
129  void offset(int off) {
130  m_offset += off;
131  }
132  void reset_offset() {
133  m_offset=m_initial_offset;
134  }
135  const std::string name() const { return m_name; }
136  const std::string type_name() const { return m_type_name; }
137  const std::string value() const { return m_value; }
138  bool null() const { return m_null; }
139  int pg_type() const { return m_type_oid; }
140  int pos() const { return m_offset; }
141  void set_null() { m_null=true; }
142  /* SELECT oid FROM pg_type -- for the supported values of "typname" */
143  enum type_oid {
144  oid_bool=16,
145  oid_bytea=17,
146  oid_int8=20,
147  oid_int2=21,
148  oid_int4=23,
149  oid_text=25,
150  oid_varchar=1043,
151  oid_numeric=1700
152  };
153  void set_type(enum type_oid o);
154  void set_type(const char*);
155  void set_value(const char* buf) { m_value=buf; }
156  void set_binary_data(const void* buf, unsigned int sz) {
157  m_data_ptr=buf;
158  m_data_size=sz;
159  }
160  const void* data_ptr() const { return m_data_ptr; }
161  unsigned int data_size() const { return m_data_size; }
162  private:
163  std::string m_name;
164  std::string m_value;
165  std::string m_type_name;
166  const void* m_data_ptr; /* pointer to external binary data (bytea parameters) */
167  unsigned int m_data_size; /* size of binary data (bytea) */
168  int m_offset; /* position of the ':' character in query */
171  bool m_null;
172  static const char* m_type_names[];
173  static int m_oids[];
174  };
175 
177  {
178  friend class pg_stream;
179  public:
180  pg_bytea();
181  pg_bytea(void* ptr, unsigned int len);
182  virtual ~pg_bytea();
183  void set_src_data(void* ptr, unsigned int len) {
184  m_data_ptr=ptr;
185  m_data_len=len;
186  }
187  void* get_data_ptr() const {
188  return m_data_ptr;
189  }
190  unsigned int get_data_size() const {
191  return m_data_len;
192  }
193  bool is_null() const {
194  return m_data_ptr==NULL;
195  }
196  protected:
197  void* m_data_ptr;
198  unsigned int m_data_len;
199  bool m_allocated; // if m_data_ptr was allocated by the class
200  };
201 
207  {
208  public:
210  // prepare_mode=0: don't prepare the statement; 1: prepare, 2:use
211  // the current default for the db connection
212  pg_stream(const char* query, pg_cnx& db,int prepare_mode=2);
213  pg_stream(const std::string query, pg_cnx& db,int prepare_mode=2);
214  virtual ~pg_stream();
215 
217  pg_stream& operator<<(const char*);
218  pg_stream& operator<<(const std::string&);
220  pg_stream& operator<<(int);
221  pg_stream& operator<<(unsigned int);
222  pg_stream& operator<<(long);
223  pg_stream& operator<<(unsigned long);
224  pg_stream& operator<<(long long);
225  pg_stream& operator<<(unsigned long long);
226  pg_stream& operator<<(short);
227  pg_stream& operator<<(unsigned short);
228  pg_stream& operator<<(double);
229  pg_stream& operator<<(bool);
230  pg_stream& operator<<(sql_null);
231  pg_stream& operator<<(pg_bytea&);
232 
233  pg_stream& operator>>(short&);
234  pg_stream& operator>>(unsigned short&);
235  pg_stream& operator>>(int&);
236  pg_stream& operator>>(unsigned int&);
237  pg_stream& operator>>(char*);
238  pg_stream& operator>>(std::string&);
239  pg_stream& operator>>(pg_bytea&);
240  pg_stream& operator>>(double&);
241  pg_stream& operator>>(bool&);
242 
243  void prepare(bool prep=true) {
244  m_prepare_wanted=prep;
245  }
246  void set_cursor(unsigned int step) {
247  m_cursor_step = step;
248  }
249  void use_bind_variables(bool u=true) {
250  m_inline_params = !u;
251  }
252 #if 0
253  void print();
254 #endif
255 
258  int eof();
259  int eos() { return eof(); }
260  bool val_is_null() const {
261  return m_val_null;
262  }
263  int affected_rows() const {
264  return m_affected_rows;
265  }
266  protected:
267  void init(const char* query,int prepare_mode,unsigned int cursor_step);
268  pg_stream(pg_cnx& db) : m_db(db) {}
270 
271  private:
273  void execute();
274 
275  void do_prepare();
276  void create_cursor();
277  void cursor_fetch();
278  void check_binds();
279  void reset_results();
280  void next_result();
281  void check_eof();
282  void query_make_space(int len);
283  void replace_placeholder(unsigned int argpos, const char* buf, int size, bool binary=false);
284  void next_bind();
285  bool check_null();
286 
287  unsigned int m_argpos;
288  char* m_query_buf;
292  char m_localQueryBuf[1024+1];
293  std::string m_query_fmt; /* initial query text */
295  std::vector<sql_bind_param> m_vars;
296  unsigned int m_query_hash;
297  // results
299  PGresult* m_pg_res;
300  int m_row_number; /* last row read from the stream */
301  int m_col_number; /* last column read from the stream */
302  bool m_val_null; /* last value read from the stream is null */
305  bool m_prepare_wanted; /* use PQexecPrepared if possible */
306  std::string m_prepare_name;
307  std::string m_cursor_name;
308 
309  // m_inline_params
310  // true: replace the bind variables by their values inside the sql statement
311  // false: pass the values outside the sql sentence (use PQexecParams
312  // or PQexecPrepared)
314 
315  // global counter to uniquely identify prepared statements and cursors
316  static int m_uniq_cnt;
317  };
318 
320  {
321  public:
322  pg_cursor(unsigned int step, const char* query, pg_cnx& cnx);
323  pg_cursor(unsigned int step, std::string query, pg_cnx& cnx);
324  };
325 } // namespace pgs
326 #endif // INC_PGSTREAM_H