~drizzle-trunk/drizzle/development

2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
1
/*
2
 * Drizzle Client & Protocol Library
3
 *
4
 * Copyright (C) 2008 Eric Day (eday@oddments.org)
5
 * All rights reserved.
6
 *
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions are
9
 * met:
10
 *
11
 *     * Redistributions of source code must retain the above copyright
12
 * notice, this list of conditions and the following disclaimer.
13
 *
14
 *     * Redistributions in binary form must reproduce the above
15
 * copyright notice, this list of conditions and the following disclaimer
16
 * in the documentation and/or other materials provided with the
17
 * distribution.
18
 *
19
 *     * The names of its contributors may not be used to endorse or
20
 * promote products derived from this software without specific prior
21
 * written permission.
22
 *
23
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
 *
35
 */
36
37
/**
38
 * @file
39
 * @brief Query definitions
40
 */
41
42
#include "common.h"
43
44
drizzle_result_st *drizzle_query(drizzle_con_st *con, drizzle_result_st *result,
45
                                 const char *query, size_t size,
46
                                 drizzle_return_t *ret_ptr)
47
{
48
  return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_QUERY,
49
                                   (uint8_t *)query, size, size, ret_ptr);
50
}
51
52
drizzle_result_st *drizzle_query_str(drizzle_con_st *con,
53
                                     drizzle_result_st *result,
54
                                     const char *query, 
55
                                     drizzle_return_t *ret_ptr)
56
{
57
  size_t size;
58
59
  size= strlen(query);
60
61
  return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_QUERY,
62
                                   (uint8_t *)query, size, size, ret_ptr);
63
}
64
65
drizzle_result_st *drizzle_query_inc(drizzle_con_st *con,
66
                                     drizzle_result_st *result,
67
                                     const char *query, size_t size,
68
                                     size_t total, drizzle_return_t *ret_ptr)
69
{
70
  return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_QUERY,
71
                                   (uint8_t *)query, size, total, ret_ptr);
72
}
73
74
drizzle_query_st *drizzle_query_add(drizzle_st *drizzle,
75
                                    drizzle_query_st *query,
76
                                    drizzle_con_st *con,
77
                                    drizzle_result_st *result,
78
                                    const char *query_string, size_t size,
79
                                    drizzle_query_options_t options,
80
                                    void *context)
81
{
82
  query= drizzle_query_create(drizzle, query);
83
  if (query == NULL)
84
    return NULL;
85
86
  drizzle_query_set_con(query, con);
87
  drizzle_query_set_result(query, result);
88
  drizzle_query_set_string(query, query_string, size);
89
  drizzle_query_add_options(query, options);
90
  drizzle_query_set_context(query, context);
91
92
  return query;
93
}
94
95
drizzle_query_st *drizzle_query_create(drizzle_st *drizzle,
96
                                       drizzle_query_st *query)
97
{
98
  if (query == NULL)
99
  {
100
    query= new drizzle_query_st;
101
    query->options|= DRIZZLE_CON_ALLOCATED;
102
  }
103
  else
104
  {
105
    query->prev= NULL;
106
    query->options= 0;
107
    query->state= DRIZZLE_QUERY_STATE_INIT;
108
    query->con= NULL;
109
    query->result= NULL;
110
    query->string= NULL;
111
    query->size= 0;
112
    query->context= NULL;
113
    query->context_free_fn= NULL;
114
  }
115
116
  query->drizzle= drizzle;
117
118
  if (drizzle->query_list)
119
    drizzle->query_list->prev= query;
120
  query->next= drizzle->query_list;
121
  drizzle->query_list= query;
122
  drizzle->query_count++;
123
  drizzle->query_new++;
124
125
  return query;
126
}
127
128
void drizzle_query_free(drizzle_query_st *query)
129
{
130
  if (query->context != NULL && query->context_free_fn != NULL)
131
    query->context_free_fn(query, query->context);
132
133
  if (query->drizzle->query_list == query)
134
    query->drizzle->query_list= query->next;
135
  if (query->prev)
136
    query->prev->next= query->next;
137
  if (query->next)
138
    query->next->prev= query->prev;
139
  query->drizzle->query_count--;
140
141
  if (query->options & DRIZZLE_QUERY_ALLOCATED)
142
    delete query;
143
}
144
145
void drizzle_query_free_all(drizzle_st *drizzle)
146
{
147
  while (drizzle->query_list != NULL)
148
    drizzle_query_free(drizzle->query_list);
149
}
150
151
drizzle_con_st *drizzle_query_con(drizzle_query_st *query)
152
{
153
  return query->con;
154
}
155
156
void drizzle_query_set_con(drizzle_query_st *query, drizzle_con_st *con)
157
{
158
  query->con= con;
159
}
160
161
drizzle_result_st *drizzle_query_result(drizzle_query_st *query)
162
{
163
  return query->result;
164
}
165
166
void drizzle_query_set_result(drizzle_query_st *query,
167
                              drizzle_result_st *result)
168
{
169
  query->result= result;
170
}
171
172
char *drizzle_query_string(drizzle_query_st *query, size_t *size)
173
{
174
  *size= query->size;
175
  return (char *)(query->string);
176
}
177
178
void drizzle_query_set_string(drizzle_query_st *query, const char *string,
179
                              size_t size)
180
{
181
  query->string= string;
182
  query->size= size;
183
}
184
185
int drizzle_query_options(drizzle_query_st *query)
186
{
187
  return query->options;
188
}
189
190
void drizzle_query_set_options(drizzle_query_st *query,
191
                               int options)
192
{
193
  query->options= options;
194
}
195
196
void drizzle_query_add_options(drizzle_query_st *query,
197
                               int options)
198
{
199
  query->options|= options;
200
}
201
202
void drizzle_query_remove_options(drizzle_query_st *query,
203
                                  int options)
204
{
205
  query->options&= ~options;
206
}
207
208
void *drizzle_query_context(drizzle_query_st *query)
209
{
210
  return query->context;
211
}
212
213
void drizzle_query_set_context(drizzle_query_st *query, void *context)
214
{
215
  query->context= context;
216
}
217
218
void drizzle_query_set_context_free_fn(drizzle_query_st *query,
219
                                       drizzle_query_context_free_fn *function)
220
{
221
  query->context_free_fn= function;
222
}
223
224
static void drizzle_query_run_state(drizzle_query_st* query,
225
                                    drizzle_return_t* ret_ptr)
226
{
227
  switch (query->state)
228
  {
229
  case DRIZZLE_QUERY_STATE_INIT:
230
    query->state= DRIZZLE_QUERY_STATE_QUERY;
231
  case DRIZZLE_QUERY_STATE_QUERY:
232
    query->result= drizzle_query(query->con, query->result, query->string,
233
                                 query->size, ret_ptr);
234
    if (*ret_ptr == DRIZZLE_RETURN_IO_WAIT)
235
    {
236
      return;
237
    }
238
    else if (*ret_ptr != DRIZZLE_RETURN_OK)
239
    {
240
      query->state= DRIZZLE_QUERY_STATE_DONE;
241
      return;
242
    }
243
244
    query->state= DRIZZLE_QUERY_STATE_RESULT;
245
246
  case DRIZZLE_QUERY_STATE_RESULT:
247
    *ret_ptr= drizzle_result_buffer(query->result);
248
    if (*ret_ptr == DRIZZLE_RETURN_IO_WAIT)
249
    {
250
      return;
251
    }
252
253
    query->state= DRIZZLE_QUERY_STATE_DONE;
254
    return;
255
256
  default:
257
  case DRIZZLE_QUERY_STATE_DONE:
258
    return;
259
  }
260
}
261
262
drizzle_query_st *drizzle_query_run(drizzle_st *drizzle,
263
                                    drizzle_return_t *ret_ptr)
264
{
265
  int options;
266
  drizzle_query_st *query;
267
  drizzle_con_st *con;
268
269
  if (drizzle->query_new == 0 && drizzle->query_running == 0)
270
  {
271
    *ret_ptr= DRIZZLE_RETURN_OK;
272
    return NULL;
273
  }
274
275
  options= drizzle->options;
276
  drizzle->options|= DRIZZLE_NON_BLOCKING;
277
278
  /* Check to see if any queries need to be started. */
279
  if (drizzle->query_new > 0)
280
  {
281
    for (query= drizzle->query_list; query != NULL; query= query->next)
282
    {
283
      if (query->state != DRIZZLE_QUERY_STATE_INIT)
284
        continue;
285
286
      drizzle->query_new--;
287
      drizzle->query_running++;
288
      assert(query->con->query == NULL);
289
      query->con->query= query;
290
291
      drizzle_query_run_state(query, ret_ptr);
292
      if (*ret_ptr != DRIZZLE_RETURN_IO_WAIT)
293
      {
294
        assert(query->state == DRIZZLE_QUERY_STATE_DONE);
295
        drizzle->query_running--;
296
        drizzle->options= options;
297
        query->con->query= NULL;
298
        if (*ret_ptr == DRIZZLE_RETURN_ERROR_CODE || *ret_ptr == DRIZZLE_RETURN_OK)
299
        {
300
          return query;
301
        }
302
        return NULL;
303
      }
304
    }
305
    assert(drizzle->query_new == 0);
306
  }
307
308
  while (1)
309
  {
310
    /* Loop through each active connection. */
311
    while ((con= drizzle_con_ready(drizzle)) != NULL)
312
    {
313
      query= con->query;
314
      drizzle_query_run_state(query, ret_ptr);
315
      if (query->state == DRIZZLE_QUERY_STATE_DONE)
316
      {
317
        drizzle->query_running--;
318
        drizzle->options= options;
319
        con->query= NULL;
320
        return query;
321
      }
322
      assert(*ret_ptr == DRIZZLE_RETURN_IO_WAIT);
323
    }
324
325
    if (options & DRIZZLE_NON_BLOCKING)
326
    {
327
      *ret_ptr= DRIZZLE_RETURN_IO_WAIT;
328
      return NULL;
329
    }
330
331
    *ret_ptr= drizzle_con_wait(drizzle);
332
    if (*ret_ptr != DRIZZLE_RETURN_OK)
333
    {
334
      drizzle->options= options;
335
      return NULL;
336
    }
337
  }
338
}
339
340
drizzle_return_t drizzle_query_run_all(drizzle_st *drizzle)
341
{
342
  drizzle_return_t ret;
343
344
  while (drizzle->query_new > 0 || drizzle->query_running > 0)
345
  {
346
    (void)drizzle_query_run(drizzle, &ret);
347
    if (ret != DRIZZLE_RETURN_OK && ret != DRIZZLE_RETURN_ERROR_CODE)
348
      return ret;
349
  }
350
351
  return DRIZZLE_RETURN_OK;
352
}
353
354
ssize_t drizzle_safe_escape_string(char *to, size_t max_to_size, const char *from, size_t from_size)
355
{
356
  ssize_t to_size= 0;
357
  char newchar;
358
  const char *end;
359
360
  for (end= from + from_size; from < end; from++)
361
  {
362
    newchar= 0;
363
    /* All multi-byte UTF8 characters have the high bit set for all bytes. */
364
    if (!(*from & 0x80))
365
    {
366
      switch (*from)
367
      {
368
      case 0:
369
        newchar= '0';
370
        break;
371
      case '\n':
372
        newchar= 'n';
373
        break;
374
      case '\r':
375
        newchar= 'r';
376
        break;
377
      case '\032':
378
        newchar= 'Z';
379
        break;
380
      case '\\':
381
        newchar= '\\';
382
        break;
383
      case '\'':
384
        newchar= '\'';
385
        break;
386
      case '"':
387
        newchar= '"';
388
        break;
389
      default:
390
        break;
391
      }
392
    }
393
    if (newchar != '\0')
394
    {
395
      if ((size_t)to_size + 2 > max_to_size)
396
        return -1;
397
398
      *to++= '\\';
399
      *to++= newchar;
400
      to_size++;
401
    }
402
    else
403
    {
404
      if ((size_t)to_size + 1 > max_to_size)
405
        return -1;
406
407
      *to++= *from;
408
    }
409
    to_size++;
410
  }
411
412
  *to= 0;
413
414
  return to_size;
415
}
416
417
size_t drizzle_escape_string(char *to, const char *from, size_t from_size)
418
{
419
  return (size_t) drizzle_safe_escape_string(to, (from_size * 2), from, from_size);
420
}
421
422
size_t drizzle_hex_string(char *to, const char *from, size_t from_size)
423
{
424
  static const char hex_map[]= "0123456789ABCDEF";
425
  const char *from_end;
426
427
  for (from_end= from + from_size; from != from_end; from++)
428
  {
429
    *to++= hex_map[((unsigned char) *from) >> 4];
430
    *to++= hex_map[((unsigned char) *from) & 0xF];
431
  }
432
433
  *to= 0;
434
435
  return from_size * 2;
436
}
437
438
void drizzle_mysql_password_hash(char *to, const char *from, size_t from_size)
439
{
440
  SHA1_CTX ctx;
441
  uint8_t hash_tmp1[SHA1_DIGEST_LENGTH];
442
  uint8_t hash_tmp2[SHA1_DIGEST_LENGTH];
443
444
  SHA1Init(&ctx);
445
  SHA1Update(&ctx, (const uint8_t*)from, from_size);
446
  SHA1Final(hash_tmp1, &ctx);
447
448
  SHA1Init(&ctx);
449
  SHA1Update(&ctx, hash_tmp1, SHA1_DIGEST_LENGTH);
450
  SHA1Final(hash_tmp2, &ctx);
451
452
  (void)drizzle_hex_string(to, (char*)hash_tmp2, SHA1_DIGEST_LENGTH);
453
}