~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
  {
2407.1.2 by Olaf van der Spek
Make base members private
72
    drizzle_create(*this);
2318.5.40 by Olaf van der Spek
Oops
73
  }
74
75
  ~drizzle_c()
76
  {
2407.1.2 by Olaf van der Spek
Make base members private
77
    drizzle_free(*this);
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
  {
82
    return &b_;
83
  }
84
private:
2318.5.40 by Olaf van der Spek
Oops
85
  drizzle_st b_;
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
  {
2407.1.2 by Olaf van der Spek
Make base members private
151
    drizzle_con_create(drizzle, *this);
2407.1.4 by Olaf van der Spek
Read conf files
152
    read_conf_files();
2318.5.40 by Olaf van der Spek
Oops
153
  }
154
155
  ~connection_c()
156
  {
2407.1.2 by Olaf van der Spek
Make base members private
157
    drizzle_con_free(*this);
158
  }
159
160
  operator drizzle_con_st*()
161
  {
162
    return &b_;
2318.5.40 by Olaf van der Spek
Oops
163
  }
164
165
  const char* error()
166
  {
2407.1.2 by Olaf van der Spek
Make base members private
167
    return drizzle_con_error(*this);
2318.5.40 by Olaf van der Spek
Oops
168
  }
169
2367.2.3 by Olaf van der Spek
Use C++ API
170
  void set_tcp(const char* host, in_port_t port)
171
  {
2407.1.2 by Olaf van der Spek
Make base members private
172
    drizzle_con_set_tcp(*this, host, port);
2367.2.3 by Olaf van der Spek
Use C++ API
173
  }
174
175
  void set_auth(const char* user, const char* password)
176
  {
2407.1.2 by Olaf van der Spek
Make base members private
177
    drizzle_con_set_auth(*this, user, password);
2367.2.3 by Olaf van der Spek
Use C++ API
178
  }
179
180
  void set_db(const char* db)
181
  {
2407.1.2 by Olaf van der Spek
Make base members private
182
    drizzle_con_set_db(*this, db);
2367.2.3 by Olaf van der Spek
Use C++ API
183
  }
184
2318.5.32 by Olaf van der Spek
Refactor
185
  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
186
  {
187
    drizzle_return_t ret;
2407.1.2 by Olaf van der Spek
Make base members private
188
    drizzle_query(*this, result, str, str_size, &ret);
2407.1.3 by Olaf van der Spek
Add throwing variants of query()
189
    if (!ret)
2407.1.1 by Olaf van der Spek
Make drizzle::result_c copyable
190
      ret = drizzle_result_buffer(result);
2318.5.5 by Olaf van der Spek
C++ client lib wrapper
191
    return ret;
2318.5.40 by Olaf van der Spek
Oops
192
  }
193
194
  drizzle_return_t query(result_c& result, const std::string& str)
195
  {
196
    return query(result, str.data(), str.size());
197
  }
198
199
  drizzle_return_t query(result_c& result, const char* str)
200
  {
201
    return query(result, str, strlen(str));
202
  }
2407.1.3 by Olaf van der Spek
Add throwing variants of query()
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
  }
2407.1.2 by Olaf van der Spek
Make base members private
221
private:
2407.1.4 by Olaf van der Spek
Read conf files
222
  void read_conf_files();
223
2318.5.40 by Olaf van der Spek
Oops
224
  drizzle_con_st b_;
225
};
226
2385.3.2 by Olaf van der Spek
Add drizzle::query_c
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
2385.3.5 by Olaf van der Spek
Fix PBMS
284
  query_c& p(long long v)
2385.3.2 by Olaf van der Spek
Add drizzle::query_c
285
  {
2385.3.5 by Olaf van der Spek
Fix PBMS
286
    std::stringstream ss;
287
    ss << v;
288
    p_raw(ss.str());
2385.3.2 by Olaf van der Spek
Add drizzle::query_c
289
    return *this;
290
  }
291
292
  drizzle_return_t execute(result_c& result)
293
  {
294
    return con_.query(result, read());
295
  }
296
2407.1.3 by Olaf van der Spek
Add throwing variants of query()
297
  result_c execute()
298
  {
299
    return con_.query(read());
300
  }
301
2385.3.2 by Olaf van der Spek
Add drizzle::query_c
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
2407.1.4 by Olaf van der Spek
Read conf files
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
  
2407.1.6 by Olaf van der Spek
Refactor
343
  map<string, string> conf;
2407.1.4 by Olaf van der Spek
Read conf files
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('=');
2407.1.6 by Olaf van der Spek
Refactor
362
      if (i != string::npos)
363
        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
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
}
371
2318.5.40 by Olaf van der Spek
Oops
372
}