~drizzle-trunk/drizzle/development

1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
1
/*
2
 * Drizzle Client & Protocol Library
3
 *
4
 * Copyright (C) 2008 Eric Day (eday@oddments.org)
5
 * All rights reserved.
6
 *
7
 * Use and distribution licensed under the BSD license.  See
1799.2.3 by Monty Taylor
Reference root BSD copying file.
8
 * the COPYING.BSD file in the root source directory for full text.
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
9
 */
10
11
/**
12
 * @file
13
 * @brief Query definitions
14
 */
15
16
#include "common.h"
17
18
drizzle_result_st *drizzle_query(drizzle_con_st *con, drizzle_result_st *result,
19
                                 const char *query, size_t size,
20
                                 drizzle_return_t *ret_ptr)
21
{
22
  return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_QUERY,
23
                                   (uint8_t *)query, size, size, ret_ptr);
24
}
25
26
drizzle_result_st *drizzle_query_str(drizzle_con_st *con,
27
                                     drizzle_result_st *result,
28
                                     const char *query, 
29
                                     drizzle_return_t *ret_ptr)
30
{
31
  size_t size;
32
33
  size= strlen(query);
34
35
  return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_QUERY,
36
                                   (uint8_t *)query, size, size, ret_ptr);
37
}
38
39
drizzle_result_st *drizzle_query_inc(drizzle_con_st *con,
40
                                     drizzle_result_st *result,
41
                                     const char *query, size_t size,
42
                                     size_t total, drizzle_return_t *ret_ptr)
43
{
44
  return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_QUERY,
45
                                   (uint8_t *)query, size, total, ret_ptr);
46
}
47
48
drizzle_query_st *drizzle_query_add(drizzle_st *drizzle,
49
                                    drizzle_query_st *query,
50
                                    drizzle_con_st *con,
51
                                    drizzle_result_st *result,
52
                                    const char *query_string, size_t size,
53
                                    drizzle_query_options_t options,
54
                                    void *context)
55
{
56
  query= drizzle_query_create(drizzle, query);
57
  if (query == NULL)
58
    return NULL;
59
60
  drizzle_query_set_con(query, con);
61
  drizzle_query_set_result(query, result);
62
  drizzle_query_set_string(query, query_string, size);
63
  drizzle_query_add_options(query, options);
64
  drizzle_query_set_context(query, context);
65
66
  return query;
67
}
68
69
drizzle_query_st *drizzle_query_create(drizzle_st *drizzle,
70
                                       drizzle_query_st *query)
71
{
72
  if (query == NULL)
73
  {
74
    query= malloc(sizeof(drizzle_query_st));
75
    if (query == NULL)
76
    {
77
      drizzle_set_error(drizzle, "drizzle_query_create", "malloc");
78
      return NULL;
79
    }
80
81
    memset(query, 0, sizeof(drizzle_query_st));
82
    query->options|= DRIZZLE_CON_ALLOCATED;
83
  }
84
  else
85
    memset(query, 0, sizeof(drizzle_query_st));
86
87
  query->drizzle= drizzle;
88
89
  if (drizzle->query_list)
90
    drizzle->query_list->prev= query;
91
  query->next= drizzle->query_list;
92
  drizzle->query_list= query;
93
  drizzle->query_count++;
94
  drizzle->query_new++;
95
96
  return query;
97
}
98
99
void drizzle_query_free(drizzle_query_st *query)
100
{
101
  if (query->context != NULL && query->context_free_fn != NULL)
102
    query->context_free_fn(query, query->context);
103
104
  if (query->drizzle->query_list == query)
105
    query->drizzle->query_list= query->next;
106
  if (query->prev)
107
    query->prev->next= query->next;
108
  if (query->next)
109
    query->next->prev= query->prev;
110
  query->drizzle->query_count--;
111
112
  if (query->options & DRIZZLE_QUERY_ALLOCATED)
113
    free(query);
114
}
115
116
void drizzle_query_free_all(drizzle_st *drizzle)
117
{
118
  while (drizzle->query_list != NULL)
119
    drizzle_query_free(drizzle->query_list);
120
}
121
122
drizzle_con_st *drizzle_query_con(drizzle_query_st *query)
123
{
124
  return query->con;
125
}
126
127
void drizzle_query_set_con(drizzle_query_st *query, drizzle_con_st *con)
128
{
129
  query->con= con;
130
}
131
132
drizzle_result_st *drizzle_query_result(drizzle_query_st *query)
133
{
134
  return query->result;
135
}
136
137
void drizzle_query_set_result(drizzle_query_st *query,
138
                              drizzle_result_st *result)
139
{
140
  query->result= result;
141
}
142
143
char *drizzle_query_string(drizzle_query_st *query, size_t *size)
144
{
145
  *size= query->size;
146
  return (char *)(query->string);
147
}
148
149
void drizzle_query_set_string(drizzle_query_st *query, const char *string,
150
                              size_t size)
151
{
152
  query->string= string;
153
  query->size= size;
154
}
155
156
drizzle_query_options_t drizzle_query_options(drizzle_query_st *query)
157
{
158
  return query->options;
159
}
160
161
void drizzle_query_set_options(drizzle_query_st *query,
162
                               drizzle_query_options_t options)
163
{
164
  query->options= options;
165
}
166
167
void drizzle_query_add_options(drizzle_query_st *query,
168
                               drizzle_query_options_t options)
169
{
170
  query->options|= options;
171
}
172
173
void drizzle_query_remove_options(drizzle_query_st *query,
174
                                  drizzle_query_options_t options)
175
{
176
  query->options&= ~options;
177
}
178
179
void *drizzle_query_context(drizzle_query_st *query)
180
{
181
  return query->context;
182
}
183
184
void drizzle_query_set_context(drizzle_query_st *query, void *context)
185
{
186
  query->context= context;
187
}
188
189
void drizzle_query_set_context_free_fn(drizzle_query_st *query,
190
                                       drizzle_query_context_free_fn *function)
191
{
192
  query->context_free_fn= function;
193
}
194
195
static void drizzle_query_run_state(drizzle_query_st* query,
196
                                    drizzle_return_t* ret_ptr)
197
{
198
  switch (query->state)
199
  {
200
  case DRIZZLE_QUERY_STATE_INIT:
201
    query->state= DRIZZLE_QUERY_STATE_QUERY;
202
  case DRIZZLE_QUERY_STATE_QUERY:
203
    query->result= drizzle_query(query->con, query->result, query->string,
204
                                 query->size, ret_ptr);
205
    if (*ret_ptr == DRIZZLE_RETURN_IO_WAIT)
206
    {
207
      return;
208
    }
209
    else if (*ret_ptr != DRIZZLE_RETURN_OK)
210
    {
211
      query->state= DRIZZLE_QUERY_STATE_DONE;
212
      return;
213
    }
214
215
    query->state= DRIZZLE_QUERY_STATE_RESULT;
216
217
  case DRIZZLE_QUERY_STATE_RESULT:
218
    *ret_ptr= drizzle_result_buffer(query->result);
219
    if (*ret_ptr == DRIZZLE_RETURN_IO_WAIT)
220
    {
221
      return;
222
    }
223
224
    query->state= DRIZZLE_QUERY_STATE_DONE;
225
    return;
226
227
  default:
228
  case DRIZZLE_QUERY_STATE_DONE:
229
    return;
230
  }
231
}
232
233
drizzle_query_st *drizzle_query_run(drizzle_st *drizzle,
234
                                    drizzle_return_t *ret_ptr)
235
{
236
  drizzle_options_t options;
237
  drizzle_query_st *query;
238
  drizzle_con_st *con;
239
240
  if (drizzle->query_new == 0 && drizzle->query_running == 0)
241
  {
242
    *ret_ptr= DRIZZLE_RETURN_OK;
243
    return NULL;
244
  }
245
246
  options= drizzle->options;
247
  drizzle->options|= DRIZZLE_NON_BLOCKING;
248
249
  /* Check to see if any queries need to be started. */
250
  if (drizzle->query_new > 0)
251
  {
252
    for (query= drizzle->query_list; query != NULL; query= query->next)
253
    {
254
      if (query->state != DRIZZLE_QUERY_STATE_INIT)
255
        continue;
256
257
      drizzle->query_new--;
258
      drizzle->query_running++;
259
      assert(query->con->query == NULL);
260
      query->con->query= query;
261
262
      drizzle_query_run_state(query, ret_ptr);
263
      if (*ret_ptr != DRIZZLE_RETURN_IO_WAIT)
264
      {
265
        assert(query->state == DRIZZLE_QUERY_STATE_DONE);
266
        drizzle->query_running--;
267
        drizzle->options= options;
268
        query->con->query= NULL;
269
        if (*ret_ptr == DRIZZLE_RETURN_ERROR_CODE || *ret_ptr == DRIZZLE_RETURN_OK)
270
        {
271
          return query;
272
        }
273
        return NULL;
274
      }
275
    }
276
    assert(drizzle->query_new == 0);
277
  }
278
279
  while (1)
280
  {
281
    /* Loop through each active connection. */
282
    while ((con= drizzle_con_ready(drizzle)) != NULL)
283
    {
284
      query= con->query;
285
      drizzle_query_run_state(query, ret_ptr);
286
      if (query->state == DRIZZLE_QUERY_STATE_DONE)
287
      {
288
        drizzle->query_running--;
289
        drizzle->options= options;
290
        con->query= NULL;
291
        return query;
292
      }
293
      assert(*ret_ptr == DRIZZLE_RETURN_IO_WAIT);
294
    }
295
296
    if (options & DRIZZLE_NON_BLOCKING)
297
    {
298
      *ret_ptr= DRIZZLE_RETURN_IO_WAIT;
299
      return NULL;
300
    }
301
302
    *ret_ptr= drizzle_con_wait(drizzle);
303
    if (*ret_ptr != DRIZZLE_RETURN_OK)
304
    {
305
      drizzle->options= options;
306
      return NULL;
307
    }
308
  }
309
}
310
311
drizzle_return_t drizzle_query_run_all(drizzle_st *drizzle)
312
{
313
  drizzle_return_t ret;
314
315
  while (drizzle->query_new > 0 || drizzle->query_running > 0)
316
  {
317
    (void)drizzle_query_run(drizzle, &ret);
318
    if (ret != DRIZZLE_RETURN_OK && ret != DRIZZLE_RETURN_ERROR_CODE)
319
      return ret;
320
  }
321
322
  return DRIZZLE_RETURN_OK;
323
}
324
325
size_t drizzle_escape_string(char *to, const char *from, size_t from_size)
326
{
327
  size_t to_size= 0;
1857.5.1 by Andrew Hutchings
Add unit tests for libdrizzle utility functions
328
  char newchar;
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
329
330
  while (from_size > 0)
331
  {
1857.5.1 by Andrew Hutchings
Add unit tests for libdrizzle utility functions
332
    newchar= 0;
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
333
    /* All multi-byte UTF8 characters have the high bit set for all bytes. */
334
    if (!(*from & 0x80))
335
    {
336
      switch (*from)
337
      {
338
      case 0:
1857.5.1 by Andrew Hutchings
Add unit tests for libdrizzle utility functions
339
        newchar= '0';
340
        break;
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
341
      case '\n':
1857.5.1 by Andrew Hutchings
Add unit tests for libdrizzle utility functions
342
        newchar= 'n';
343
        break;
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
344
      case '\r':
1857.5.1 by Andrew Hutchings
Add unit tests for libdrizzle utility functions
345
        newchar= 'r';
346
        break;
347
      case '\032':
348
        newchar= 'Z';
349
        break;
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
350
      case '\\':
351
      case '\'':
352
      case '"':
353
        *to++= '\\';
354
        to_size++;
355
      default:
356
        break;
357
      }
358
    }
1857.5.1 by Andrew Hutchings
Add unit tests for libdrizzle utility functions
359
    if (newchar != 0)
360
    {
361
      *to++= '\\';
362
      *to++= newchar;
363
      to_size++;
364
    }
365
    else 
366
      *to++= *from++;
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
367
    from_size--;
368
    to_size++;
369
  }
370
371
  *to= 0;
372
373
  return to_size;
374
}
375
376
size_t drizzle_hex_string(char *to, const char *from, size_t from_size)
377
{
378
  static const char hex_map[]= "0123456789ABCDEF";
379
  const char *from_end;
380
381
  for (from_end= from + from_size; from != from_end; from++)
382
  {
383
    *to++= hex_map[((unsigned char) *from) >> 4];
384
    *to++= hex_map[((unsigned char) *from) & 0xF];
385
  }
386
387
  *to= 0;
388
389
  return from_size * 2;
390
}
391
392
void drizzle_mysql_password_hash(char *to, const char *from, size_t from_size)
393
{
394
  SHA1_CTX ctx;
395
  uint8_t hash_tmp1[SHA1_DIGEST_LENGTH];
396
  uint8_t hash_tmp2[SHA1_DIGEST_LENGTH];
397
398
  SHA1Init(&ctx);
399
  SHA1Update(&ctx, (const uint8_t*)from, from_size);
400
  SHA1Final(hash_tmp1, &ctx);
401
402
  SHA1Init(&ctx);
403
  SHA1Update(&ctx, hash_tmp1, SHA1_DIGEST_LENGTH);
404
  SHA1Final(hash_tmp2, &ctx);
405
406
  (void)drizzle_hex_string(to, (char*)hash_tmp2, SHA1_DIGEST_LENGTH);
407
}