~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to libdrizzle-2.0/libdrizzle/libdrizzle.hpp

  • Committer: Henrik Ingo
  • Date: 2011-09-23 06:14:37 UTC
  • mfrom: (2425 drizzle)
  • mto: This revision was merged to the branch mainline in revision 2439.
  • Revision ID: henrik.ingo@avoinelama.fi-20110923061437-ct1wedkb9s47uy2t
Merge newest trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
33
33
 
34
34
#pragma once
35
35
 
 
36
#include <boost/algorithm/string.hpp>
 
37
#include <boost/foreach.hpp>
 
38
#include <boost/shared_ptr.hpp>
36
39
#include <cstring>
 
40
#include <fstream>
37
41
#include <libdrizzle/libdrizzle.h>
 
42
#include <map>
 
43
#include <sstream>
38
44
#include <stdexcept>
39
45
 
40
46
namespace drizzle {
41
47
 
42
48
class bad_query : public std::runtime_error
43
49
{
44
 
};
45
 
 
46
 
class drizzle_c
 
50
public:
 
51
  bad_query(const std::string& v) : std::runtime_error(v)
 
52
  {
 
53
  }
 
54
};
 
55
 
 
56
class noncopyable
 
57
{
 
58
protected:
 
59
  noncopyable()
 
60
  {
 
61
  }
 
62
private:
 
63
  noncopyable(const noncopyable&);
 
64
  void operator=(const noncopyable&);
 
65
};
 
66
 
 
67
class drizzle_c : noncopyable
47
68
{
48
69
public:
49
70
  drizzle_c()
50
71
  {
51
 
    drizzle_create(&b_);
 
72
    drizzle_create(*this);
52
73
  }
53
74
 
54
75
  ~drizzle_c()
55
76
  {
56
 
    drizzle_free(&b_);
 
77
    drizzle_free(*this);
57
78
  }
58
79
 
 
80
  operator drizzle_st*()
 
81
  {
 
82
    return &b_;
 
83
  }
 
84
private:
59
85
  drizzle_st b_;
60
86
};
61
87
 
62
88
class result_c
63
89
{
64
90
public:
65
 
  result_c()
66
 
  {
67
 
    memset(&b_, 0, sizeof(b_));
68
 
  }
69
 
 
70
 
  ~result_c()
71
 
  {
72
 
    drizzle_result_free(&b_);
 
91
  operator drizzle_result_st*()
 
92
  {
 
93
    if (!b_)
 
94
      b_.reset(new drizzle_result_st, drizzle_result_free);
 
95
    return b_.get();
73
96
  }
74
97
 
75
98
  const char* error()
76
99
  {
77
 
    return drizzle_result_error(&b_);
 
100
    return drizzle_result_error(*this);
78
101
  }
79
102
 
80
103
  uint16_t error_code()
81
104
  {
82
 
    return drizzle_result_error_code(&b_);
 
105
    return drizzle_result_error_code(*this);
83
106
  }
84
107
 
85
108
  uint16_t column_count()
86
109
  {
87
 
    return drizzle_result_column_count(&b_);    
 
110
    return drizzle_result_column_count(*this);    
88
111
  }
89
112
 
90
113
  uint64_t row_count()
91
114
  {
92
 
    return drizzle_result_row_count(&b_);
 
115
    return drizzle_result_row_count(*this);
93
116
  }
94
117
 
95
118
  drizzle_column_st* column_next()
96
119
  {
97
 
    return drizzle_column_next(&b_);
 
120
    return drizzle_column_next(*this);
98
121
  }
99
122
 
100
123
  drizzle_row_t row_next()
101
124
  {
102
 
    return drizzle_row_next(&b_);
 
125
    return drizzle_row_next(*this);
103
126
  }
104
127
 
105
128
  void column_seek(uint16_t i)
106
129
  {
107
 
    drizzle_column_seek(&b_, i);
 
130
    drizzle_column_seek(*this, i);
108
131
  }
109
132
 
110
133
  void row_seek(uint64_t i)
111
134
  {
112
 
    drizzle_row_seek(&b_, i);
 
135
    drizzle_row_seek(*this, i);
113
136
  }
114
137
 
115
138
  size_t* row_field_sizes()
116
139
  {
117
 
    return drizzle_row_field_sizes(&b_);
 
140
    return drizzle_row_field_sizes(*this);
118
141
  }
119
 
 
120
 
  drizzle_result_st b_;
 
142
private:
 
143
  boost::shared_ptr<drizzle_result_st> b_;
121
144
};
122
145
 
123
 
class connection_c
 
146
class connection_c : noncopyable
124
147
{
125
148
public:
126
149
  explicit connection_c(drizzle_c& drizzle)
127
150
  {
128
 
    drizzle_con_create(&drizzle.b_, &b_);
 
151
    drizzle_con_create(drizzle, *this);
 
152
    read_conf_files();
129
153
  }
130
154
 
131
155
  ~connection_c()
132
156
  {
133
 
    drizzle_con_free(&b_);
 
157
    drizzle_con_free(*this);
 
158
  }
 
159
 
 
160
  operator drizzle_con_st*()
 
161
  {
 
162
    return &b_;
134
163
  }
135
164
 
136
165
  const char* error()
137
166
  {
138
 
    return drizzle_con_error(&b_);
 
167
    return drizzle_con_error(*this);
 
168
  }
 
169
 
 
170
  void set_tcp(const char* host, in_port_t port)
 
171
  {
 
172
    drizzle_con_set_tcp(*this, host, port);
 
173
  }
 
174
 
 
175
  void set_auth(const char* user, const char* password)
 
176
  {
 
177
    drizzle_con_set_auth(*this, user, password);
 
178
  }
 
179
 
 
180
  void set_db(const char* db)
 
181
  {
 
182
    drizzle_con_set_db(*this, db);
139
183
  }
140
184
 
141
185
  drizzle_return_t query(result_c& result, const char* str, size_t str_size)
142
186
  {
143
187
    drizzle_return_t ret;
144
 
    drizzle_query(&b_, &result.b_, str, str_size, &ret);
145
 
    if (ret == DRIZZLE_RETURN_OK)
146
 
      ret = drizzle_result_buffer(&result.b_);
 
188
    drizzle_query(*this, result, str, str_size, &ret);
 
189
    if (!ret)
 
190
      ret = drizzle_result_buffer(result);
147
191
    return ret;
148
192
  }
149
193
 
157
201
    return query(result, str, strlen(str));
158
202
  }
159
203
 
 
204
  result_c query(const char* str, size_t str_size)
 
205
  {
 
206
    result_c result;
 
207
    if (query(result, str, str_size))
 
208
      throw bad_query(error());
 
209
    return result;
 
210
  }
 
211
 
 
212
  result_c query(const std::string& str)
 
213
  {
 
214
    return query(str.data(), str.size());
 
215
  }
 
216
 
 
217
  result_c query(const char* str)
 
218
  {
 
219
    return query(str, strlen(str));
 
220
  }
 
221
private:
 
222
  void read_conf_files();
 
223
 
160
224
  drizzle_con_st b_;
161
225
};
162
226
 
163
 
/*
164
 
inline drizzle_return_t query(drizzle_con_st* con, result_c& result, const char* str, size_t str_size)
165
 
{
166
 
  drizzle_return_t ret;
167
 
  drizzle_query(con, &result.b_, str, str_size, &ret);
168
 
  if (ret == DRIZZLE_RETURN_OK)
169
 
    ret = drizzle_result_buffer(&result.b_);
170
 
  return ret;
171
 
}
172
 
 
173
 
inline drizzle_return_t query(drizzle_con_st* con, result_c& result, const std::string& str)
174
 
{
175
 
  return query(con, result, str.data(), str.size());
176
 
}
177
 
 
178
 
inline drizzle_return_t query(drizzle_con_st* con, result_c& result, const char* str)
179
 
{
180
 
  return query(con, result, str, strlen(str));
181
 
}
182
 
*/
 
227
class query_c
 
228
{
 
229
public:
 
230
  query_c(connection_c& con, const std::string& in = "") :
 
231
    con_(con),
 
232
    in_(in)
 
233
  {
 
234
  }
 
235
 
 
236
  void operator=(const std::string& v)
 
237
  {
 
238
    in_ = v;
 
239
    out_.clear();
 
240
  }
 
241
 
 
242
  void operator+=(const std::string& v)
 
243
  {
 
244
    in_ += v;
 
245
  }
 
246
 
 
247
  query_c& p_name(const std::string& v)
 
248
  {
 
249
    std::vector<char> r(2 * v.size() + 2);
 
250
    r.resize(drizzle_escape_string(&r.front() + 1, v.data(), v.size()) + 2);    
 
251
    r.front() = '`';
 
252
    r.back() = '`';
 
253
    p_raw(&r.front(), r.size());
 
254
    return *this;
 
255
  }
 
256
 
 
257
  query_c& p_raw(const char* v, size_t sz)
 
258
  {
 
259
    size_t i = in_.find('?');
 
260
    assert(i != std::string::npos);
 
261
    if (i == std::string::npos)
 
262
      return *this;
 
263
    out_.append(in_.substr(0, i));
 
264
    in_.erase(0, i + 1);
 
265
    out_.append(v, sz);
 
266
    return *this;
 
267
  }
 
268
 
 
269
  query_c& p_raw(const std::string& v)
 
270
  {
 
271
    return p_raw(v.data(), v.size());
 
272
  }
 
273
 
 
274
  query_c& p(const std::string& v)
 
275
  {
 
276
    std::vector<char> r(2 * v.size() + 2);
 
277
    r.resize(drizzle_escape_string(&r.front() + 1, v.data(), v.size()) + 2);    
 
278
    r.front() = '\'';
 
279
    r.back() = '\'';
 
280
    p_raw(&r.front(), r.size());
 
281
    return *this;
 
282
  }
 
283
 
 
284
  query_c& p(long long v)
 
285
  {
 
286
    std::stringstream ss;
 
287
    ss << v;
 
288
    p_raw(ss.str());
 
289
    return *this;
 
290
  }
 
291
 
 
292
  drizzle_return_t execute(result_c& result)
 
293
  {
 
294
    return con_.query(result, read());
 
295
  }
 
296
 
 
297
  result_c execute()
 
298
  {
 
299
    return con_.query(read());
 
300
  }
 
301
 
 
302
  std::string read() const
 
303
  {
 
304
    return out_ + in_;
 
305
  }
 
306
private:
 
307
  connection_c& con_;
 
308
  std::string in_;
 
309
  std::string out_;
 
310
};
 
311
 
 
312
template<class T>
 
313
const char* get_conf(const T& c, const std::string& v)
 
314
{
 
315
  typename T::const_iterator i = c.find(v);
 
316
  return i == c.end() ? NULL : i->second.c_str();
 
317
}
 
318
 
 
319
void connection_c::read_conf_files()
 
320
{
 
321
  using namespace std;
 
322
 
 
323
  vector<string> conf_files;
 
324
#ifdef WIN32
 
325
  {
 
326
    boost::array<char, MAX_PATH> d;
 
327
    GetWindowsDirectoryA(d.data(), d.size());
 
328
    conf_files.push_back(string(d.data()) + "/my.cnf");
 
329
    conf_files.push_back(string(d.data()) + "/drizzle.cnf");
 
330
    conf_files.push_back(string(d.data()) + "/drizzle.conf");
 
331
  }
 
332
#else
 
333
  conf_files.push_back("/etc/mysql/my.cnf");
 
334
  conf_files.push_back("/etc/drizzle/drizzle.cnf");
 
335
  conf_files.push_back("/etc/drizzle/drizzle.conf");
 
336
#endif
 
337
  if (const char* d = getenv("HOME"))
 
338
  {
 
339
    conf_files.push_back(string(d) + "/.my.cnf");  
 
340
    conf_files.push_back(string(d) + "/.drizzle.conf");
 
341
  }
 
342
  
 
343
  map<string, string> conf;
 
344
  BOOST_FOREACH(string& it, conf_files)
 
345
  {
 
346
    ifstream is(it.c_str());
 
347
    bool client_section = false;
 
348
    for (string s; getline(is, s); )
 
349
    {
 
350
      size_t i = s.find('#');
 
351
      if (i != string::npos)
 
352
        s.erase(i);
 
353
      boost::trim(s);
 
354
      if (boost::starts_with(s, "["))
 
355
      {
 
356
        client_section = s == "[client]";
 
357
        continue;
 
358
      }
 
359
      else if (!client_section)
 
360
        continue;
 
361
      i = s.find('=');
 
362
      if (i != string::npos)
 
363
        conf[boost::trim_copy(s.substr(0, i))] = boost::trim_copy(s.substr(i + 1));
 
364
    }
 
365
  }
 
366
  if (conf.count("host") || conf.count("port"))
 
367
    set_tcp(get_conf(conf, "host"), atoi(get_conf(conf, "port")));
 
368
  if (conf.count("user") || conf.count("password"))
 
369
    set_auth(get_conf(conf, "user"), get_conf(conf, "password"));
 
370
}
183
371
 
184
372
}