~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/oldlibdrizzle/client.cc

MergedĀ inĀ trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 */
19
19
 
20
20
/*
21
 
  This file is included by both libdrizzle.c (the DRIZZLE client C API)
 
21
  This file is included by both libdrizzleclient.c (the DRIZZLE client C API)
22
22
  and the drizzled server to connect to another DRIZZLE server.
23
23
 
24
24
  The differences for the two cases are:
25
25
 
26
26
  - Things that only works for the client:
27
27
  - Trying to automaticly determinate user name if not supplied to
28
 
    drizzle_connect()
 
28
    drizzleclient_connect()
29
29
  - Support for reading local file with LOAD DATA LOCAL
30
30
  - SHARED memory handling
31
31
  - Prepared statements
32
 
 
 
32
 
33
33
  - Things that only works for the server
34
34
  - Alarm handling on connect
35
 
 
 
35
 
36
36
  In all other cases, the code should be idential for the client and
37
37
  server.
38
38
*/
39
39
 
 
40
 
 
41
#include "libdrizzle_priv.h"
 
42
#include "net_serv.h"
 
43
#include "pack.h"
 
44
#include "errmsg.h"
 
45
#include "drizzle_methods.h"
 
46
 
40
47
#include <stdarg.h>
41
 
 
42
 
#include <libdrizzle/libdrizzle.h>
43
 
#include <libdrizzle/net_serv.h>
44
 
#include "libdrizzle_priv.h"
45
 
 
46
48
#include <sys/poll.h>
47
49
#include <sys/ioctl.h>
48
50
 
52
54
#undef max_allowed_packet
53
55
#undef net_buffer_length
54
56
 
55
 
#include <libdrizzle/errmsg.h>
56
 
#include <vio/violite.h>
57
57
 
58
58
#include <sys/stat.h>
59
59
#include <signal.h>
76
76
#include <sys/un.h>
77
77
 
78
78
#include <errno.h>
79
 
#define SOCKET_ERROR -1
80
 
 
81
 
 
82
 
#include <drizzled/version.h>
83
 
#include <libdrizzle/sql_common.h>
84
 
#include <libdrizzle/gettext.h>
85
 
#include "local_infile.h"
86
 
 
87
 
 
88
 
 
89
 
 
90
 
 
91
 
 
92
 
 
 
79
 
 
80
 
 
81
#include <drizzled/gettext.h>
 
82
#include "libdrizzle.h"
 
83
 
 
84
using namespace std;
93
85
 
94
86
#if defined(HAVE_GETPWUID) && defined(NO_GETPWUID_DECL)
95
87
struct passwd *getpwuid(uid_t);
97
89
#endif
98
90
 
99
91
 
100
 
 
101
92
/*****************************************************************************
102
93
  Read a packet from server. Give error message if socket was down
103
94
  or packet is an error message
104
95
*****************************************************************************/
105
96
 
106
 
uint32_t cli_safe_read(DRIZZLE *drizzle)
 
97
/* I'm not sure if this is even used anymore, but now that libdrizzleclient is
 
98
   server only, this is safe to set here. */
 
99
extern "C" bool safe_read_error_impl(NET *net);
 
100
 
 
101
bool safe_read_error_impl(NET *net)
 
102
{
 
103
  if (net->vio)
 
104
    return drizzleclient_vio_was_interrupted(net->vio);
 
105
  return false;
 
106
}
 
107
 
 
108
 
 
109
safe_read_error_hook_func safe_read_error_hook= safe_read_error_impl;
 
110
 
 
111
uint32_t drizzleclient_cli_safe_read(DRIZZLE *drizzle)
107
112
{
108
113
  NET *net= &drizzle->net;
109
114
  uint32_t len=0;
110
115
 
111
116
  if (net->vio != 0)
112
 
    len=my_net_read(net);
 
117
    len=drizzleclient_net_read(net);
113
118
 
114
119
  if (len == packet_error || len == 0)
115
120
  {
116
 
#ifdef DRIZZLE_SERVER
117
 
    if (net->vio && vio_was_interrupted(net->vio))
118
 
      return (packet_error);
119
 
#endif /*DRIZZLE_SERVER*/
120
 
    drizzle_disconnect(drizzle);
121
 
    drizzle_set_error(drizzle, net->last_errno == CR_NET_PACKET_TOO_LARGE ?
 
121
    if (safe_read_error_hook != NULL)
 
122
      if (safe_read_error_hook(net))
 
123
        return (packet_error);
 
124
    drizzleclient_disconnect(drizzle);
 
125
    drizzleclient_set_error(drizzle, net->last_errno == CR_NET_PACKET_TOO_LARGE ?
122
126
                      CR_NET_PACKET_TOO_LARGE : CR_SERVER_LOST,
123
 
                      sqlstate_get_unknown());
 
127
                      drizzleclient_sqlstate_get_unknown());
124
128
    return (packet_error);
125
129
  }
126
130
  if (net->read_pos[0] == 255)
133
137
      len-=2;
134
138
      if (pos[0] == '#')
135
139
      {
136
 
        strncpy(net->sqlstate, pos+1, SQLSTATE_LENGTH);
137
 
        pos+= SQLSTATE_LENGTH+1;
 
140
        strncpy(net->sqlstate, pos+1, LIBDRIZZLE_SQLSTATE_LENGTH);
 
141
        pos+= LIBDRIZZLE_SQLSTATE_LENGTH+1;
138
142
      }
139
143
      else
140
144
      {
143
147
          (unknown error sql state).
144
148
        */
145
149
 
146
 
        strcpy(net->sqlstate, sqlstate_get_unknown());
 
150
        strcpy(net->sqlstate, drizzleclient_sqlstate_get_unknown());
147
151
      }
148
152
 
149
153
      strncpy(net->last_error,(char*) pos, min((uint32_t) len,
150
154
              (uint32_t) sizeof(net->last_error)-1));
151
155
    }
152
156
    else
153
 
      drizzle_set_error(drizzle, CR_UNKNOWN_ERROR, sqlstate_get_unknown());
 
157
      drizzleclient_set_error(drizzle, CR_UNKNOWN_ERROR, drizzleclient_sqlstate_get_unknown());
154
158
    /*
155
159
      Cover a protocol design error: error packet does not
156
160
      contain the server status. Therefore, the client has no way
168
172
}
169
173
 
170
174
bool
171
 
cli_advanced_command(DRIZZLE *drizzle, enum enum_server_command command,
 
175
drizzleclient_cli_advanced_command(DRIZZLE *drizzle, enum enum_server_command command,
172
176
         const unsigned char *header, uint32_t header_length,
173
177
         const unsigned char *arg, uint32_t arg_length, bool skip_check)
174
178
{
178
182
 
179
183
  if (drizzle->net.vio == 0)
180
184
  {            /* Do reconnect if possible */
181
 
    if (drizzle_reconnect(drizzle) || stmt_skip)
 
185
    if (drizzleclient_reconnect(drizzle) || stmt_skip)
182
186
      return(1);
183
187
  }
184
188
  if (drizzle->status != DRIZZLE_STATUS_READY ||
185
189
      drizzle->server_status & SERVER_MORE_RESULTS_EXISTS)
186
190
  {
187
 
    drizzle_set_error(drizzle, CR_COMMANDS_OUT_OF_SYNC,
188
 
                      sqlstate_get_unknown());
 
191
    drizzleclient_set_error(drizzle, CR_COMMANDS_OUT_OF_SYNC,
 
192
                      drizzleclient_sqlstate_get_unknown());
189
193
    return(1);
190
194
  }
191
195
 
192
 
  net_clear_error(net);
 
196
  drizzleclient_drizzleclient_net_clear_error(net);
193
197
  drizzle->info=0;
194
198
  drizzle->affected_rows= ~(uint64_t) 0;
195
199
  /*
197
201
    the previous command was a shutdown command, we may have the
198
202
    response for the COM_QUIT already in the communication buffer
199
203
  */
200
 
  net_clear(&drizzle->net, (command != COM_QUIT));
 
204
  drizzleclient_net_clear(&drizzle->net, (command != COM_QUIT));
201
205
 
202
 
  if (net_write_command(net,(unsigned char) command, header, header_length,
 
206
  if (drizzleclient_net_write_command(net,(unsigned char) command, header, header_length,
203
207
      arg, arg_length))
204
208
  {
205
209
    if (net->last_errno == CR_NET_PACKET_TOO_LARGE)
206
210
    {
207
 
      drizzle_set_error(drizzle, CR_NET_PACKET_TOO_LARGE, sqlstate_get_unknown());
 
211
      drizzleclient_set_error(drizzle, CR_NET_PACKET_TOO_LARGE, drizzleclient_sqlstate_get_unknown());
208
212
      goto end;
209
213
    }
210
 
    drizzle_disconnect(drizzle);
211
 
    if (drizzle_reconnect(drizzle) || stmt_skip)
 
214
    drizzleclient_disconnect(drizzle);
 
215
    if (drizzleclient_reconnect(drizzle) || stmt_skip)
212
216
      goto end;
213
 
    if (net_write_command(net,(unsigned char) command, header, header_length,
 
217
    if (drizzleclient_net_write_command(net,(unsigned char) command, header, header_length,
214
218
        arg, arg_length))
215
219
    {
216
 
      drizzle_set_error(drizzle, CR_SERVER_GONE_ERROR, sqlstate_get_unknown());
 
220
      drizzleclient_set_error(drizzle, CR_SERVER_GONE_ERROR, drizzleclient_sqlstate_get_unknown());
217
221
      goto end;
218
222
    }
219
223
  }
220
224
  result=0;
221
225
  if (!skip_check)
222
 
    result= ((drizzle->packet_length=cli_safe_read(drizzle)) == packet_error ?
 
226
    result= ((drizzle->packet_length=drizzleclient_cli_safe_read(drizzle)) == packet_error ?
223
227
       1 : 0);
224
228
end:
225
229
  return(result);
226
230
}
227
231
 
228
 
void free_old_query(DRIZZLE *drizzle)
 
232
void drizzleclient_free_old_query(DRIZZLE *drizzle)
229
233
{
230
234
  if (drizzle->fields)
231
235
  {
253
257
 
254
258
 
255
259
void
256
 
drizzle_free_result(DRIZZLE_RES *result)
 
260
drizzleclient_free_result(DRIZZLE_RES *result)
257
261
{
258
262
  if (result)
259
263
  {
270
274
          *drizzle->unbuffered_fetch_owner= true;
271
275
      }
272
276
    }
273
 
    free_rows(result->data);
 
277
    drizzleclient_free_rows(result->data);
274
278
    /* TODO: free result->fields */
275
279
    if (result->row)
276
280
      free((unsigned char*) result->row);
283
287
 
284
288
/* Read all rows (fields or data) from server */
285
289
 
286
 
DRIZZLE_DATA *cli_read_rows(DRIZZLE *drizzle, DRIZZLE_FIELD *DRIZZLE_FIELDs, uint32_t fields)
 
290
DRIZZLE_DATA *drizzleclient_cli_read_rows(DRIZZLE *drizzle, DRIZZLE_FIELD *DRIZZLE_FIELDs, uint32_t fields)
287
291
{
288
292
  uint32_t  field;
289
293
  uint32_t pkt_len;
294
298
  DRIZZLE_ROWS **prev_ptr,*cur;
295
299
  NET *net = &drizzle->net;
296
300
 
297
 
  if ((pkt_len= cli_safe_read(drizzle)) == packet_error)
 
301
  if ((pkt_len= drizzleclient_cli_safe_read(drizzle)) == packet_error)
298
302
    return(0);
299
303
  if (!(result=(DRIZZLE_DATA*) malloc(sizeof(DRIZZLE_DATA))))
300
304
  {
301
 
    drizzle_set_error(drizzle, CR_OUT_OF_MEMORY,
302
 
                      sqlstate_get_unknown());
 
305
    drizzleclient_set_error(drizzle, CR_OUT_OF_MEMORY,
 
306
                      drizzleclient_sqlstate_get_unknown());
303
307
    return(0);
304
308
  }
305
309
  memset(result, 0, sizeof(DRIZZLE_DATA));
311
315
    The last EOF packet is either a 254 (0xFE) character followed by 1-7 status bytes.
312
316
 
313
317
    This doesn't conflict with normal usage of 254 which stands for a
314
 
    string where the length of the string is 8 bytes. (see net_field_length())
 
318
    string where the length of the string is 8 bytes. (see drizzleclient_net_field_length())
315
319
  */
316
320
 
317
321
  while (*(cp=net->read_pos) != DRIZZLE_PROTOCOL_NO_MORE_DATA || pkt_len >= 8)
320
324
    if (!(cur= (DRIZZLE_ROWS*) malloc(sizeof(DRIZZLE_ROWS))) ||
321
325
        !(cur->data= ((DRIZZLE_ROW) malloc((fields+1)*sizeof(char *)+pkt_len))))
322
326
    {
323
 
      free_rows(result);
324
 
      drizzle_set_error(drizzle, CR_OUT_OF_MEMORY, sqlstate_get_unknown());
 
327
      drizzleclient_free_rows(result);
 
328
      drizzleclient_set_error(drizzle, CR_OUT_OF_MEMORY, drizzleclient_sqlstate_get_unknown());
325
329
      return(0);
326
330
    }
327
331
    *prev_ptr=cur;
330
334
    end_to=to+pkt_len-1;
331
335
    for (field=0 ; field < fields ; field++)
332
336
    {
333
 
      if ((len= net_field_length(&cp)) == NULL_LENGTH)
 
337
      if ((len= drizzleclient_net_field_length(&cp)) == NULL_LENGTH)
334
338
      {            /* null field */
335
339
        cur->data[field] = 0;
336
340
      }
339
343
        cur->data[field] = to;
340
344
        if (len > (uint32_t) (end_to - to))
341
345
        {
342
 
          free_rows(result);
343
 
          drizzle_set_error(drizzle, CR_MALFORMED_PACKET,
344
 
                            sqlstate_get_unknown());
 
346
          drizzleclient_free_rows(result);
 
347
          drizzleclient_set_error(drizzle, CR_MALFORMED_PACKET,
 
348
                            drizzleclient_sqlstate_get_unknown());
345
349
          return(0);
346
350
        }
347
351
        memcpy(to, cp, len);
356
360
      }
357
361
    }
358
362
    cur->data[field]=to;      /* End of last field */
359
 
    if ((pkt_len=cli_safe_read(drizzle)) == packet_error)
 
363
    if ((pkt_len=drizzleclient_cli_safe_read(drizzle)) == packet_error)
360
364
    {
361
 
      free_rows(result);
 
365
      drizzleclient_free_rows(result);
362
366
      return(0);
363
367
    }
364
368
  }
385
389
  unsigned char *pos, *prev_pos, *end_pos;
386
390
  NET *net= &drizzle->net;
387
391
 
388
 
  if ((pkt_len=cli_safe_read(drizzle)) == packet_error)
 
392
  if ((pkt_len=drizzleclient_cli_safe_read(drizzle)) == packet_error)
389
393
    return -1;
390
394
  if (pkt_len <= 8 && net->read_pos[0] == DRIZZLE_PROTOCOL_NO_MORE_DATA)
391
395
  {
401
405
  end_pos=pos+pkt_len;
402
406
  for (field=0 ; field < fields ; field++)
403
407
  {
404
 
    if ((len= net_field_length(&pos)) == NULL_LENGTH)
 
408
    if ((len= drizzleclient_net_field_length(&pos)) == NULL_LENGTH)
405
409
    {            /* null field */
406
410
      row[field] = 0;
407
411
      *lengths++=0;
410
414
    {
411
415
      if (len > (uint32_t) (end_pos - pos))
412
416
      {
413
 
        drizzle_set_error(drizzle, CR_UNKNOWN_ERROR,
414
 
                          sqlstate_get_unknown());
 
417
        drizzleclient_set_error(drizzle, CR_UNKNOWN_ERROR,
 
418
                          drizzleclient_sqlstate_get_unknown());
415
419
        return -1;
416
420
      }
417
421
      row[field] = (char*) pos;
433
437
**************************************************************************/
434
438
 
435
439
DRIZZLE_ROW
436
 
drizzle_fetch_row(DRIZZLE_RES *res)
 
440
drizzleclient_fetch_row(DRIZZLE_RES *res)
437
441
{
438
442
  if (!res->data)
439
443
  {            /* Unbufferred fetch */
442
446
      DRIZZLE *drizzle= res->handle;
443
447
      if (drizzle->status != DRIZZLE_STATUS_USE_RESULT)
444
448
      {
445
 
        drizzle_set_error(drizzle,
 
449
        drizzleclient_set_error(drizzle,
446
450
                          res->unbuffered_fetch_cancelled ?
447
451
                          CR_FETCH_CANCELED : CR_COMMANDS_OUT_OF_SYNC,
448
 
                          sqlstate_get_unknown());
 
452
                          drizzleclient_sqlstate_get_unknown());
449
453
      }
450
454
      else if (!(read_one_row(drizzle, res->field_count, res->row, res->lengths)))
451
455
      {
460
464
      */
461
465
      if (drizzle->unbuffered_fetch_owner == &res->unbuffered_fetch_cancelled)
462
466
        drizzle->unbuffered_fetch_owner= 0;
463
 
      /* Don't clear handle in drizzle_free_result */
 
467
      /* Don't clear handle in drizzleclient_free_result */
464
468
      res->handle=0;
465
469
    }
466
470
    return((DRIZZLE_ROW) NULL);
480
484
 
481
485
/**************************************************************************
482
486
  Get column lengths of the current row
483
 
  If one uses drizzle_use_result, res->lengths contains the length information,
 
487
  If one uses drizzleclient_use_result, res->lengths contains the length information,
484
488
  else the lengths are calculated from the offset between pointers.
485
489
**************************************************************************/
486
490
 
487
491
uint32_t *
488
 
drizzle_fetch_lengths(DRIZZLE_RES *res)
 
492
drizzleclient_fetch_lengths(DRIZZLE_RES *res)
489
493
{
490
494
  DRIZZLE_ROW column;
491
495
 
498
502
 
499
503
 
500
504
int
501
 
drizzle_options(DRIZZLE *drizzle,enum drizzle_option option, const void *arg)
 
505
drizzleclient_options(DRIZZLE *drizzle,enum drizzle_option option, const void *arg)
502
506
{
503
507
  switch (option) {
504
508
  case DRIZZLE_OPT_CONNECT_TIMEOUT:
514
518
    drizzle->options.compress= 1;      /* Remember for connect */
515
519
    drizzle->options.client_flag|= CLIENT_COMPRESS;
516
520
    break;
517
 
  case DRIZZLE_OPT_LOCAL_INFILE:      /* Allow LOAD DATA LOCAL ?*/
518
 
    if (!arg || (*(uint32_t*) arg) ? 1 : 0)
519
 
      drizzle->options.client_flag|= CLIENT_LOCAL_FILES;
520
 
    else
521
 
      drizzle->options.client_flag&= ~CLIENT_LOCAL_FILES;
522
 
    break;
523
521
  case DRIZZLE_READ_DEFAULT_FILE:
524
522
    if (drizzle->options.my_cnf_file != NULL)
525
523
      free(drizzle->options.my_cnf_file);
526
 
    drizzle->options.my_cnf_file=strdup(arg);
 
524
    drizzle->options.my_cnf_file=strdup((char *)arg);
527
525
    break;
528
526
  case DRIZZLE_READ_DEFAULT_GROUP:
529
527
    if (drizzle->options.my_cnf_group != NULL)
530
528
      free(drizzle->options.my_cnf_group);
531
 
    drizzle->options.my_cnf_group=strdup(arg);
 
529
    drizzle->options.my_cnf_group=strdup((char *)arg);
532
530
    break;
533
531
  case DRIZZLE_OPT_PROTOCOL:
534
532
    break;
537
535
    drizzle->options.methods_to_use= option;
538
536
    break;
539
537
  case DRIZZLE_SET_CLIENT_IP:
540
 
    drizzle->options.client_ip= strdup(arg);
 
538
    drizzle->options.client_ip= strdup((char *)arg);
541
539
    break;
542
540
  case DRIZZLE_SECURE_AUTH:
543
541
    drizzle->options.secure_auth= *(const bool *) arg;
567
565
****************************************************************************/
568
566
 
569
567
/* DRIZZLE_RES */
570
 
uint64_t drizzle_num_rows(const DRIZZLE_RES *res)
 
568
uint64_t drizzleclient_num_rows(const DRIZZLE_RES *res)
571
569
{
572
570
  return res->row_count;
573
571
}
574
572
 
575
 
unsigned int drizzle_num_fields(const DRIZZLE_RES *res)
 
573
unsigned int drizzleclient_num_fields(const DRIZZLE_RES *res)
576
574
{
577
575
  return res->field_count;
578
576
}
582
580
  Get version number for server in a form easy to test on
583
581
 
584
582
  SYNOPSIS
585
 
    drizzle_get_server_version()
 
583
    drizzleclient_get_server_version()
586
584
    drizzle Connection
587
585
 
588
586
  EXAMPLE
589
587
    4.1.0-alfa ->  40100
590
 
 
 
588
 
591
589
  NOTES
592
590
    We will ensure that a newer server always has a bigger number.
593
591
 
596
594
*/
597
595
 
598
596
uint32_t
599
 
drizzle_get_server_version(const DRIZZLE *drizzle)
 
597
drizzleclient_get_server_version(const DRIZZLE *drizzle)
600
598
{
601
599
  uint32_t major, minor, version;
602
600
  char *pos= drizzle->server_version, *end_pos;