~drizzle-trunk/drizzle/development

2318.5.17 by Olaf van der Spek
Fix copyright
1
/* Drizzle Client Library
2318.5.16 by Olaf van der Spek
Fix copyright
2
 * Copyright (C) 2011 Olaf van der Spek
2318.5.17 by Olaf van der Spek
Fix copyright
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.
2318.5.16 by Olaf van der Spek
Fix copyright
32
 */
33
2318.5.40 by Olaf van der Spek
Oops
34
#pragma once
35
2407.1.4 by Olaf van der Spek
Read conf files
36
#include <boost/algorithm/string.hpp>
37
#include <boost/foreach.hpp>
2407.1.1 by Olaf van der Spek
Make drizzle::result_c copyable
38
#include <boost/shared_ptr.hpp>
2318.5.40 by Olaf van der Spek
Oops
39
#include <cstring>
2407.1.4 by Olaf van der Spek
Read conf files
40
#include <fstream>
2449.1.2 by Brian Aker
Additional fixes for libdrizzle.
41
#include <libdrizzle-2.0/libdrizzle.h>
2407.1.4 by Olaf van der Spek
Read conf files
42
#include <map>
2385.3.5 by Olaf van der Spek
Fix PBMS
43
#include <sstream>
2318.5.40 by Olaf van der Spek
Oops
44
#include <stdexcept>
45
46
namespace drizzle {
47
48
class bad_query : public std::runtime_error
49
{
2407.1.3 by Olaf van der Spek
Add throwing variants of query()
50
public:
51
  bad_query(const std::string& v) : std::runtime_error(v)
52
  {
53
  }
2318.5.40 by Olaf van der Spek
Oops
54
};
55
2385.3.4 by Olaf van der Spek
drizzle::noncopyable
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
2318.5.40 by Olaf van der Spek
Oops
68
{
69
public:
70
  drizzle_c()
71
  {
2463.1.2 by Brian Aker
First pass, drizzle_create() no longer takes an argument. This means that we can now change drizzle_st without being concerned about ABI.
72
    b_= drizzle_create();
2318.5.40 by Olaf van der Spek
Oops
73
  }
74
75
  ~drizzle_c()
76
  {
2463.1.2 by Brian Aker
First pass, drizzle_create() no longer takes an argument. This means that we can now change drizzle_st without being concerned about ABI.
77
    drizzle_free(b_);
2318.5.40 by Olaf van der Spek
Oops
78
  }
79
2407.1.2 by Olaf van der Spek
Make base members private
80
  operator drizzle_st*()
81
  {
2463.1.2 by Brian Aker
First pass, drizzle_create() no longer takes an argument. This means that we can now change drizzle_st without being concerned about ABI.
82
    return b_;
2407.1.2 by Olaf van der Spek
Make base members private
83
  }
84
private:
2463.1.2 by Brian Aker
First pass, drizzle_create() no longer takes an argument. This means that we can now change drizzle_st without being concerned about ABI.
85
  drizzle_st *b_;
2318.5.40 by Olaf van der Spek
Oops
86
};
87
2407.1.1 by Olaf van der Spek
Make drizzle::result_c copyable
88
class result_c
2318.5.40 by Olaf van der Spek
Oops
89
{
90
public:
2407.1.1 by Olaf van der Spek
Make drizzle::result_c copyable
91
  operator drizzle_result_st*()
92
  {
93
    if (!b_)
94
      b_.reset(new drizzle_result_st, drizzle_result_free);
95
    return b_.get();
2318.5.40 by Olaf van der Spek
Oops
96
  }
97
2318.5.6 by Olaf van der Spek
Refactor
98
  const char* error()
99
  {
2407.1.1 by Olaf van der Spek
Make drizzle::result_c copyable
100
    return drizzle_result_error(*this);
2318.5.6 by Olaf van der Spek
Refactor
101
  }
102
103
  uint16_t error_code()
104
  {
2407.1.1 by Olaf van der Spek
Make drizzle::result_c copyable
105
    return drizzle_result_error_code(*this);
2318.5.6 by Olaf van der Spek
Refactor
106
  }
107
2318.5.5 by Olaf van der Spek
C++ client lib wrapper
108
  uint16_t column_count()
109
  {
2407.1.1 by Olaf van der Spek
Make drizzle::result_c copyable
110
    return drizzle_result_column_count(*this);    
2318.5.5 by Olaf van der Spek
C++ client lib wrapper
111
  }
112
113
  uint64_t row_count()
114
  {
2407.1.1 by Olaf van der Spek
Make drizzle::result_c copyable
115
    return drizzle_result_row_count(*this);
2318.5.5 by Olaf van der Spek
C++ client lib wrapper
116
  }
117
2318.5.12 by Olaf van der Spek
Refactor
118
  drizzle_column_st* column_next()
119
  {
2407.1.1 by Olaf van der Spek
Make drizzle::result_c copyable
120
    return drizzle_column_next(*this);
2318.5.12 by Olaf van der Spek
Refactor
121
  }
122
2318.5.5 by Olaf van der Spek
C++ client lib wrapper
123
  drizzle_row_t row_next()
124
  {
2407.1.1 by Olaf van der Spek
Make drizzle::result_c copyable
125
    return drizzle_row_next(*this);
2318.5.5 by Olaf van der Spek
C++ client lib wrapper
126
  }
2318.5.12 by Olaf van der Spek
Refactor
127
128
  void column_seek(uint16_t i)
129
  {
2407.1.1 by Olaf van der Spek
Make drizzle::result_c copyable
130
    drizzle_column_seek(*this, i);
2318.5.12 by Olaf van der Spek
Refactor
131
  }
132
133
  void row_seek(uint64_t i)
134
  {
2407.1.1 by Olaf van der Spek
Make drizzle::result_c copyable
135
    drizzle_row_seek(*this, i);
2318.5.12 by Olaf van der Spek
Refactor
136
  }
137
138
  size_t* row_field_sizes()
139
  {
2407.1.1 by Olaf van der Spek
Make drizzle::result_c copyable
140
    return drizzle_row_field_sizes(*this);
2318.5.12 by Olaf van der Spek
Refactor
141
  }
2407.1.1 by Olaf van der Spek
Make drizzle::result_c copyable
142
private:
143
  boost::shared_ptr<drizzle_result_st> b_;
2318.5.40 by Olaf van der Spek
Oops
144
};
145
2385.3.4 by Olaf van der Spek
drizzle::noncopyable
146
class connection_c : noncopyable
2318.5.40 by Olaf van der Spek
Oops
147
{
148
public:
149
  explicit connection_c(drizzle_c& drizzle)
150
  {
2463.1.4 by Brian Aker
Remove con from being passed object.
151
    b_= drizzle_con_create(drizzle);
152
153
    if (b_ == NULL)
154
    {
155
      throw "drizzle_con_create() failed";
156
    }
2407.1.4 by Olaf van der Spek
Read conf files
157
    read_conf_files();
2318.5.40 by Olaf van der Spek
Oops
158
  }
159
160
  ~connection_c()
161
  {
2463.1.4 by Brian Aker
Remove con from being passed object.
162
    drizzle_con_free(b_);
2407.1.2 by Olaf van der Spek
Make base members private
163
  }
164
165
  operator drizzle_con_st*()
166
  {
2463.1.4 by Brian Aker
Remove con from being passed object.
167
    return b_;
2318.5.40 by Olaf van der Spek
Oops
168
  }
169
170
  const char* error()
171
  {
2463.1.4 by Brian Aker
Remove con from being passed object.
172
    return drizzle_con_error(b_);
2318.5.40 by Olaf van der Spek
Oops
173
  }
174
2367.2.3 by Olaf van der Spek
Use C++ API
175
  void set_tcp(const char* host, in_port_t port)
176
  {
2463.1.4 by Brian Aker
Remove con from being passed object.
177
    drizzle_con_set_tcp(b_, host, port);
2367.2.3 by Olaf van der Spek
Use C++ API
178
  }
179
180
  void set_auth(const char* user, const char* password)
181
  {
2463.1.4 by Brian Aker
Remove con from being passed object.
182
    drizzle_con_set_auth(b_, user, password);
2367.2.3 by Olaf van der Spek
Use C++ API
183
  }
184
185
  void set_db(const char* db)
186
  {
2463.1.4 by Brian Aker
Remove con from being passed object.
187
    drizzle_con_set_db(b_, db);
2367.2.3 by Olaf van der Spek
Use C++ API
188
  }
189
2318.5.32 by Olaf van der Spek
Refactor
190
  drizzle_return_t query(result_c& result, const char* str, size_t str_size)
2318.5.5 by Olaf van der Spek
C++ client lib wrapper
191
  {
192
    drizzle_return_t ret;
2463.1.4 by Brian Aker
Remove con from being passed object.
193
2407.1.2 by Olaf van der Spek
Make base members private
194
    drizzle_query(*this, result, str, str_size, &ret);
2463.1.4 by Brian Aker
Remove con from being passed object.
195
2407.1.3 by Olaf van der Spek
Add throwing variants of query()
196
    if (!ret)
2463.1.4 by Brian Aker
Remove con from being passed object.
197
    {
2407.1.1 by Olaf van der Spek
Make drizzle::result_c copyable
198
      ret = drizzle_result_buffer(result);
2463.1.4 by Brian Aker
Remove con from being passed object.
199
    }
200
2318.5.5 by Olaf van der Spek
C++ client lib wrapper
201
    return ret;
2318.5.40 by Olaf van der Spek
Oops
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
  }
2407.1.3 by Olaf van der Spek
Add throwing variants of query()
213
214
  result_c query(const char* str, size_t str_size)
215
  {
216
    result_c result;
217
    if (query(result, str, str_size))
2463.1.4 by Brian Aker
Remove con from being passed object.
218
    {
2407.1.3 by Olaf van der Spek
Add throwing variants of query()
219
      throw bad_query(error());
2463.1.4 by Brian Aker
Remove con from being passed object.
220
    }
221
2407.1.3 by Olaf van der Spek
Add throwing variants of query()
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
  }
2407.1.2 by Olaf van der Spek
Make base members private
234
private:
2407.1.4 by Olaf van der Spek
Read conf files
235
  void read_conf_files();
236
2463.1.4 by Brian Aker
Remove con from being passed object.
237
  drizzle_con_st *b_;
2318.5.40 by Olaf van der Spek
Oops
238
};
239
2385.3.2 by Olaf van der Spek
Add drizzle::query_c
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);
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
263
    r.resize(drizzle_escape_string(&r.front() + 1, r.size(), v.data(), v.size()) + 2);    
2385.3.2 by Olaf van der Spek
Add drizzle::query_c
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);
2461.1.1 by Brian Aker
Fix safety issues around calling API with no check for NULL
290
    r.resize(drizzle_escape_string(&r.front() + 1, r.size(), v.data(), v.size()) + 2);    
2385.3.2 by Olaf van der Spek
Add drizzle::query_c
291
    r.front() = '\'';
292
    r.back() = '\'';
293
    p_raw(&r.front(), r.size());
294
    return *this;
295
  }
296
2385.3.5 by Olaf van der Spek
Fix PBMS
297
  query_c& p(long long v)
2385.3.2 by Olaf van der Spek
Add drizzle::query_c
298
  {
2385.3.5 by Olaf van der Spek
Fix PBMS
299
    std::stringstream ss;
300
    ss << v;
301
    p_raw(ss.str());
2385.3.2 by Olaf van der Spek
Add drizzle::query_c
302
    return *this;
303
  }
304
305
  drizzle_return_t execute(result_c& result)
306
  {
307
    return con_.query(result, read());
308
  }
309
2407.1.3 by Olaf van der Spek
Add throwing variants of query()
310
  result_c execute()
311
  {
312
    return con_.query(read());
313
  }
314
2385.3.2 by Olaf van der Spek
Add drizzle::query_c
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
2407.1.4 by Olaf van der Spek
Read conf files
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
  
2407.1.6 by Olaf van der Spek
Refactor
356
  map<string, string> conf;
2407.1.4 by Olaf van der Spek
Read conf files
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('=');
2407.1.6 by Olaf van der Spek
Refactor
375
      if (i != string::npos)
376
        conf[boost::trim_copy(s.substr(0, i))] = boost::trim_copy(s.substr(i + 1));
2407.1.4 by Olaf van der Spek
Read conf files
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
2318.5.40 by Olaf van der Spek
Oops
385
}