~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to libdrizzle-2.0/libdrizzle.hpp

mergeĀ lp:~hingo/drizzle/drizzle-auth_ldap-fix-and-docs

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Drizzle Client Library
 
2
 * Copyright (C) 2011 Olaf van der Spek
 
3
 * All rights reserved.
 
4
 *
 
5
 * Redistribution and use in source and binary forms, with or without
 
6
 * modification, are permitted provided that the following conditions are
 
7
 * met:
 
8
 *
 
9
 *     * Redistributions of source code must retain the above copyright
 
10
 * notice, this list of conditions and the following disclaimer.
 
11
 *
 
12
 *     * Redistributions in binary form must reproduce the above
 
13
 * copyright notice, this list of conditions and the following disclaimer
 
14
 * in the documentation and/or other materials provided with the
 
15
 * distribution.
 
16
 *
 
17
 *     * The names of its contributors may not be used to endorse or
 
18
 * promote products derived from this software without specific prior
 
19
 * written permission.
 
20
 *
 
21
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 
22
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 
23
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 
24
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 
25
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
26
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 
27
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
28
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
29
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
30
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 
31
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
32
 */
 
33
 
 
34
#pragma once
 
35
 
 
36
#include <boost/algorithm/string.hpp>
 
37
#include <boost/foreach.hpp>
 
38
#include <boost/shared_ptr.hpp>
 
39
#include <cstring>
 
40
#include <fstream>
 
41
#include <libdrizzle-2.0/libdrizzle.h>
 
42
#include <map>
 
43
#include <sstream>
 
44
#include <stdexcept>
 
45
 
 
46
namespace drizzle {
 
47
 
 
48
class bad_query : public std::runtime_error
 
49
{
 
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
 
68
{
 
69
public:
 
70
  drizzle_c()
 
71
  {
 
72
    b_= drizzle_create();
 
73
  }
 
74
 
 
75
  ~drizzle_c()
 
76
  {
 
77
    drizzle_free(b_);
 
78
  }
 
79
 
 
80
  operator drizzle_st*()
 
81
  {
 
82
    return b_;
 
83
  }
 
84
private:
 
85
  drizzle_st *b_;
 
86
};
 
87
 
 
88
class result_c
 
89
{
 
90
public:
 
91
  operator drizzle_result_st*()
 
92
  {
 
93
    if (!b_)
 
94
      b_.reset(new drizzle_result_st, drizzle_result_free);
 
95
    return b_.get();
 
96
  }
 
97
 
 
98
  const char* error()
 
99
  {
 
100
    return drizzle_result_error(*this);
 
101
  }
 
102
 
 
103
  uint16_t error_code()
 
104
  {
 
105
    return drizzle_result_error_code(*this);
 
106
  }
 
107
 
 
108
  uint16_t column_count()
 
109
  {
 
110
    return drizzle_result_column_count(*this);    
 
111
  }
 
112
 
 
113
  uint64_t row_count()
 
114
  {
 
115
    return drizzle_result_row_count(*this);
 
116
  }
 
117
 
 
118
  drizzle_column_st* column_next()
 
119
  {
 
120
    return drizzle_column_next(*this);
 
121
  }
 
122
 
 
123
  drizzle_row_t row_next()
 
124
  {
 
125
    return drizzle_row_next(*this);
 
126
  }
 
127
 
 
128
  void column_seek(uint16_t i)
 
129
  {
 
130
    drizzle_column_seek(*this, i);
 
131
  }
 
132
 
 
133
  void row_seek(uint64_t i)
 
134
  {
 
135
    drizzle_row_seek(*this, i);
 
136
  }
 
137
 
 
138
  size_t* row_field_sizes()
 
139
  {
 
140
    return drizzle_row_field_sizes(*this);
 
141
  }
 
142
private:
 
143
  boost::shared_ptr<drizzle_result_st> b_;
 
144
};
 
145
 
 
146
class connection_c : noncopyable
 
147
{
 
148
public:
 
149
  explicit connection_c(drizzle_c& drizzle)
 
150
  {
 
151
    b_= drizzle_con_create(drizzle);
 
152
 
 
153
    if (b_ == NULL)
 
154
    {
 
155
      throw "drizzle_con_create() failed";
 
156
    }
 
157
    read_conf_files();
 
158
  }
 
159
 
 
160
  ~connection_c()
 
161
  {
 
162
    drizzle_con_free(b_);
 
163
  }
 
164
 
 
165
  operator drizzle_con_st*()
 
166
  {
 
167
    return b_;
 
168
  }
 
169
 
 
170
  const char* error()
 
171
  {
 
172
    return drizzle_con_error(b_);
 
173
  }
 
174
 
 
175
  void set_tcp(const char* host, in_port_t port)
 
176
  {
 
177
    drizzle_con_set_tcp(b_, host, port);
 
178
  }
 
179
 
 
180
  void set_auth(const char* user, const char* password)
 
181
  {
 
182
    drizzle_con_set_auth(b_, user, password);
 
183
  }
 
184
 
 
185
  void set_db(const char* db)
 
186
  {
 
187
    drizzle_con_set_db(b_, db);
 
188
  }
 
189
 
 
190
  drizzle_return_t query(result_c& result, const char* str, size_t str_size)
 
191
  {
 
192
    drizzle_return_t ret;
 
193
 
 
194
    drizzle_query(*this, result, str, str_size, &ret);
 
195
 
 
196
    if (!ret)
 
197
    {
 
198
      ret = drizzle_result_buffer(result);
 
199
    }
 
200
 
 
201
    return ret;
 
202
  }
 
203
 
 
204
  drizzle_return_t query(result_c& result, const std::string& str)
 
205
  {
 
206
    return query(result, str.data(), str.size());
 
207
  }
 
208
 
 
209
  drizzle_return_t query(result_c& result, const char* str)
 
210
  {
 
211
    return query(result, str, strlen(str));
 
212
  }
 
213
 
 
214
  result_c query(const char* str, size_t str_size)
 
215
  {
 
216
    result_c result;
 
217
    if (query(result, str, str_size))
 
218
    {
 
219
      throw bad_query(error());
 
220
    }
 
221
 
 
222
    return result;
 
223
  }
 
224
 
 
225
  result_c query(const std::string& str)
 
226
  {
 
227
    return query(str.data(), str.size());
 
228
  }
 
229
 
 
230
  result_c query(const char* str)
 
231
  {
 
232
    return query(str, strlen(str));
 
233
  }
 
234
private:
 
235
  void read_conf_files();
 
236
 
 
237
  drizzle_con_st *b_;
 
238
};
 
239
 
 
240
class query_c
 
241
{
 
242
public:
 
243
  query_c(connection_c& con, const std::string& in = "") :
 
244
    con_(con),
 
245
    in_(in)
 
246
  {
 
247
  }
 
248
 
 
249
  void operator=(const std::string& v)
 
250
  {
 
251
    in_ = v;
 
252
    out_.clear();
 
253
  }
 
254
 
 
255
  void operator+=(const std::string& v)
 
256
  {
 
257
    in_ += v;
 
258
  }
 
259
 
 
260
  query_c& p_name(const std::string& v)
 
261
  {
 
262
    std::vector<char> r(2 * v.size() + 2);
 
263
    r.resize(drizzle_escape_string(&r.front() + 1, r.size(), v.data(), v.size()) + 2);    
 
264
    r.front() = '`';
 
265
    r.back() = '`';
 
266
    p_raw(&r.front(), r.size());
 
267
    return *this;
 
268
  }
 
269
 
 
270
  query_c& p_raw(const char* v, size_t sz)
 
271
  {
 
272
    size_t i = in_.find('?');
 
273
    assert(i != std::string::npos);
 
274
    if (i == std::string::npos)
 
275
      return *this;
 
276
    out_.append(in_.substr(0, i));
 
277
    in_.erase(0, i + 1);
 
278
    out_.append(v, sz);
 
279
    return *this;
 
280
  }
 
281
 
 
282
  query_c& p_raw(const std::string& v)
 
283
  {
 
284
    return p_raw(v.data(), v.size());
 
285
  }
 
286
 
 
287
  query_c& p(const std::string& v)
 
288
  {
 
289
    std::vector<char> r(2 * v.size() + 2);
 
290
    r.resize(drizzle_escape_string(&r.front() + 1, r.size(), v.data(), v.size()) + 2);    
 
291
    r.front() = '\'';
 
292
    r.back() = '\'';
 
293
    p_raw(&r.front(), r.size());
 
294
    return *this;
 
295
  }
 
296
 
 
297
  query_c& p(long long v)
 
298
  {
 
299
    std::stringstream ss;
 
300
    ss << v;
 
301
    p_raw(ss.str());
 
302
    return *this;
 
303
  }
 
304
 
 
305
  drizzle_return_t execute(result_c& result)
 
306
  {
 
307
    return con_.query(result, read());
 
308
  }
 
309
 
 
310
  result_c execute()
 
311
  {
 
312
    return con_.query(read());
 
313
  }
 
314
 
 
315
  std::string read() const
 
316
  {
 
317
    return out_ + in_;
 
318
  }
 
319
private:
 
320
  connection_c& con_;
 
321
  std::string in_;
 
322
  std::string out_;
 
323
};
 
324
 
 
325
template<class T>
 
326
const char* get_conf(const T& c, const std::string& v)
 
327
{
 
328
  typename T::const_iterator i = c.find(v);
 
329
  return i == c.end() ? NULL : i->second.c_str();
 
330
}
 
331
 
 
332
void connection_c::read_conf_files()
 
333
{
 
334
  using namespace std;
 
335
 
 
336
  vector<string> conf_files;
 
337
#ifdef WIN32
 
338
  {
 
339
    boost::array<char, MAX_PATH> d;
 
340
    GetWindowsDirectoryA(d.data(), d.size());
 
341
    conf_files.push_back(string(d.data()) + "/my.cnf");
 
342
    conf_files.push_back(string(d.data()) + "/drizzle.cnf");
 
343
    conf_files.push_back(string(d.data()) + "/drizzle.conf");
 
344
  }
 
345
#else
 
346
  conf_files.push_back("/etc/mysql/my.cnf");
 
347
  conf_files.push_back("/etc/drizzle/drizzle.cnf");
 
348
  conf_files.push_back("/etc/drizzle/drizzle.conf");
 
349
#endif
 
350
  if (const char* d = getenv("HOME"))
 
351
  {
 
352
    conf_files.push_back(string(d) + "/.my.cnf");  
 
353
    conf_files.push_back(string(d) + "/.drizzle.conf");
 
354
  }
 
355
  
 
356
  map<string, string> conf;
 
357
  BOOST_FOREACH(string& it, conf_files)
 
358
  {
 
359
    ifstream is(it.c_str());
 
360
    bool client_section = false;
 
361
    for (string s; getline(is, s); )
 
362
    {
 
363
      size_t i = s.find('#');
 
364
      if (i != string::npos)
 
365
        s.erase(i);
 
366
      boost::trim(s);
 
367
      if (boost::starts_with(s, "["))
 
368
      {
 
369
        client_section = s == "[client]";
 
370
        continue;
 
371
      }
 
372
      else if (!client_section)
 
373
        continue;
 
374
      i = s.find('=');
 
375
      if (i != string::npos)
 
376
        conf[boost::trim_copy(s.substr(0, i))] = boost::trim_copy(s.substr(i + 1));
 
377
    }
 
378
  }
 
379
  if (conf.count("host") || conf.count("port"))
 
380
    set_tcp(get_conf(conf, "host"), atoi(get_conf(conf, "port")));
 
381
  if (conf.count("user") || conf.count("password"))
 
382
    set_auth(get_conf(conf, "user"), get_conf(conf, "password"));
 
383
}
 
384
 
 
385
}