~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/* Copyright (C) 2000-2003 MySQL AB
2
3
   This program is free software; you can redistribute it and/or modify
4
   it under the terms of the GNU General Public License as published by
5
   the Free Software Foundation; version 2 of the License.
6
7
   This program is distributed in the hope that it will be useful,
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
   GNU General Public License for more details.
11
12
   You should have received a copy of the GNU General Public License
13
   along with this program; if not, write to the Free Software
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
16
/*
17
  This file is included by both libmysql.c (the MySQL client C API)
18
  and the mysqld server to connect to another MYSQL server.
19
20
  The differences for the two cases are:
21
22
  - Things that only works for the client:
23
  - Trying to automaticly determinate user name if not supplied to
24
    mysql_real_connect()
25
  - Support for reading local file with LOAD DATA LOCAL
26
  - SHARED memory handling
27
  - Protection against sigpipe
28
  - Prepared statements
29
  
30
  - Things that only works for the server
31
  - Alarm handling on connect
32
  
33
  In all other cases, the code should be idential for the client and
34
  server.
35
*/ 
36
37
#include <my_global.h>
38
77.1.39 by Monty Taylor
More mysql->drizzle renaming.
39
#include "drizzle.h"
1 by brian
clean slate
40
41
#include <netdb.h>
42
43
/* Remove client convenience wrappers */
44
#undef max_allowed_packet
45
#undef net_buffer_length
46
47
#define CLI_MYSQL_REAL_CONNECT STDCALL mysql_real_connect
77.1.57 by Monty Taylor
Removed dual-compile needs on client.c. Get the symbols now from libdrizzle.
48
1 by brian
clean slate
49
#include <my_sys.h>
50
#include <mysys_err.h>
51
#include <m_string.h>
52
#include <m_ctype.h>
77.1.39 by Monty Taylor
More mysql->drizzle renaming.
53
#include "drizzle_version.h"
1 by brian
clean slate
54
#include "mysqld_error.h"
55
#include "errmsg.h"
56
#include <violite.h>
57
#include <my_pthread.h>				/* because of signal()	*/
58
59
#include <sys/stat.h>
60
#include <signal.h>
61
#include <time.h>
62
#ifdef	 HAVE_PWD_H
63
#include <pwd.h>
64
#endif
94 by Brian Aker
DOS removal. DOS... hard to believe aye?
65
1 by brian
clean slate
66
#include <sys/socket.h>
67
#include <netinet/in.h>
68
#include <arpa/inet.h>
69
#include <netdb.h>
70
#ifdef HAVE_SELECT_H
71
#  include <select.h>
72
#endif
73
#ifdef HAVE_SYS_SELECT_H
74
#include <sys/select.h>
75
#endif
94 by Brian Aker
DOS removal. DOS... hard to believe aye?
76
77.1.57 by Monty Taylor
Removed dual-compile needs on client.c. Get the symbols now from libdrizzle.
77
#include <sys/un.h>
1 by brian
clean slate
78
79
#include <errno.h>
80
#define SOCKET_ERROR -1
81
82
#define CONNECT_TIMEOUT 0
83
84
#include "client_settings.h"
85
#include <sql_common.h>
86
87
uint		mysql_port=0;
88
char		*mysql_unix_port= 0;
89
const char	*unknown_sqlstate= "HY000";
90
const char	*not_error_sqlstate= "00000";
91
const char	*cant_connect_sqlstate= "08001";
92
93
static void mysql_close_free_options(MYSQL *mysql);
94
static void mysql_close_free(MYSQL *mysql);
95
96
static int wait_for_data(my_socket fd, uint timeout);
97
98
CHARSET_INFO *default_client_charset_info = &my_charset_latin1;
99
100
/* Server error code and message */
101
unsigned int mysql_server_last_errno;
102
char mysql_server_last_error[MYSQL_ERRMSG_SIZE];
103
104
/****************************************************************************
105
  A modified version of connect().  my_connect() allows you to specify
106
  a timeout value, in seconds, that we should wait until we
107
  derermine we can't connect to a particular host.  If timeout is 0,
108
  my_connect() will behave exactly like connect().
109
110
  Base version coded by Steve Bernacki, Jr. <steve@navinet.net>
111
*****************************************************************************/
112
113
int my_connect(my_socket fd, const struct sockaddr *name, uint namelen,
114
	       uint timeout)
115
{
116
  int flags, res, s_err;
117
118
  /*
119
    If they passed us a timeout of zero, we should behave
120
    exactly like the normal connect() call does.
121
  */
122
123
  if (timeout == 0)
124
    return connect(fd, (struct sockaddr*) name, namelen);
125
126
  flags = fcntl(fd, F_GETFL, 0);	  /* Set socket to not block */
127
#ifdef O_NONBLOCK
128
  fcntl(fd, F_SETFL, flags | O_NONBLOCK);  /* and save the flags..  */
129
#endif
130
131
  res= connect(fd, (struct sockaddr*) name, namelen);
132
  s_err= errno;			/* Save the error... */
133
  fcntl(fd, F_SETFL, flags);
134
  if ((res != 0) && (s_err != EINPROGRESS))
135
  {
136
    errno= s_err;			/* Restore it */
137
    return(-1);
138
  }
139
  if (res == 0)				/* Connected quickly! */
140
    return(0);
141
  return wait_for_data(fd, timeout);
142
}
143
144
145
/*
146
  Wait up to timeout seconds for a connection to be established.
147
148
  We prefer to do this with poll() as there is no limitations with this.
149
  If not, we will use select()
150
*/
151
152
static int wait_for_data(my_socket fd, uint timeout)
153
{
154
#ifdef HAVE_POLL
155
  struct pollfd ufds;
156
  int res;
157
158
  ufds.fd= fd;
159
  ufds.events= POLLIN | POLLPRI;
160
  if (!(res= poll(&ufds, 1, (int) timeout*1000)))
161
  {
162
    errno= EINTR;
163
    return -1;
164
  }
165
  if (res < 0 || !(ufds.revents & (POLLIN | POLLPRI)))
166
    return -1;
167
  return 0;
168
#else
169
  SOCKOPT_OPTLEN_TYPE s_err_size = sizeof(uint);
170
  fd_set sfds;
171
  struct timeval tv;
172
  time_t start_time, now_time;
173
  int res, s_err;
174
175
  if (fd >= FD_SETSIZE)				/* Check if wrong error */
176
    return 0;					/* Can't use timeout */
177
178
  /*
179
    Our connection is "in progress."  We can use the select() call to wait
180
    up to a specified period of time for the connection to suceed.
181
    If select() returns 0 (after waiting howevermany seconds), our socket
182
    never became writable (host is probably unreachable.)  Otherwise, if
183
    select() returns 1, then one of two conditions exist:
184
   
185
    1. An error occured.  We use getsockopt() to check for this.
186
    2. The connection was set up sucessfully: getsockopt() will
187
    return 0 as an error.
188
   
189
    Thanks goes to Andrew Gierth <andrew@erlenstar.demon.co.uk>
190
    who posted this method of timing out a connect() in
191
    comp.unix.programmer on August 15th, 1997.
192
  */
193
194
  FD_ZERO(&sfds);
195
  FD_SET(fd, &sfds);
196
  /*
197
    select could be interrupted by a signal, and if it is, 
198
    the timeout should be adjusted and the select restarted
199
    to work around OSes that don't restart select and 
200
    implementations of select that don't adjust tv upon
201
    failure to reflect the time remaining
202
   */
203
  start_time= my_time(0);
204
  for (;;)
205
  {
206
    tv.tv_sec = (long) timeout;
207
    tv.tv_usec = 0;
28.1.35 by Monty Taylor
Removed all references to THREAD.
208
#if defined(HPUX10)
1 by brian
clean slate
209
    if ((res = select(fd+1, NULL, (int*) &sfds, NULL, &tv)) > 0)
210
      break;
211
#else
212
    if ((res = select(fd+1, NULL, &sfds, NULL, &tv)) > 0)
213
      break;
214
#endif
215
    if (res == 0)					/* timeout */
216
      return -1;
217
    now_time= my_time(0);
218
    timeout-= (uint) (now_time - start_time);
219
    if (errno != EINTR || (int) timeout <= 0)
220
      return -1;
221
  }
222
223
  /*
224
    select() returned something more interesting than zero, let's
225
    see if we have any errors.  If the next two statements pass,
226
    we've got an open socket!
227
  */
228
229
  s_err=0;
230
  if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (char*) &s_err, &s_err_size) != 0)
231
    return(-1);
232
233
  if (s_err)
234
  {						/* getsockopt could succeed */
235
    errno = s_err;
236
    return(-1);					/* but return an error... */
237
  }
238
  return (0);					/* ok */
239
#endif /* HAVE_POLL */
240
}
241
242
/**
243
  Set the internal error message to mysql handler
244
245
  @param mysql    connection handle (client side)
246
  @param errcode  CR_ error code, passed to ER macro to get
247
                  error text
248
  @parma sqlstate SQL standard sqlstate
249
*/
250
251
void set_mysql_error(MYSQL *mysql, int errcode, const char *sqlstate)
252
{
253
  NET *net;
51.3.5 by Jay Pipes
Merged in from trunk.
254
  assert(mysql != 0);
1 by brian
clean slate
255
256
  if (mysql)
257
  {
258
    net= &mysql->net;
259
    net->last_errno= errcode;
260
    strmov(net->last_error, ER(errcode));
261
    strmov(net->sqlstate, sqlstate);
262
  }
263
  else
264
  {
265
    mysql_server_last_errno= errcode;
266
    strmov(mysql_server_last_error, ER(errcode));
267
  }
51.3.5 by Jay Pipes
Merged in from trunk.
268
  return;
1 by brian
clean slate
269
}
270
271
/**
272
  Clear possible error state of struct NET
273
274
  @param net  clear the state of the argument
275
*/
276
277
void net_clear_error(NET *net)
278
{
279
  net->last_errno= 0;
280
  net->last_error[0]= '\0';
281
  strmov(net->sqlstate, not_error_sqlstate);
282
}
283
284
/**
285
  Set an error message on the client.
286
287
  @param mysql     connection handle
288
  @param errcode   CR_* errcode, for client errors
289
  @param sqlstate  SQL standard sql state, unknown_sqlstate for the
290
                   majority of client errors.
291
  @param format    error message template, in sprintf format
292
  @param ...       variable number of arguments
293
*/
294
295
static void set_mysql_extended_error(MYSQL *mysql, int errcode,
296
                                     const char *sqlstate,
297
                                     const char *format, ...)
298
{
299
  NET *net;
300
  va_list args;
51.3.5 by Jay Pipes
Merged in from trunk.
301
  assert(mysql != 0);
1 by brian
clean slate
302
303
  net= &mysql->net;
304
  net->last_errno= errcode;
305
  va_start(args, format);
77.1.18 by Monty Taylor
Removed my_vsnprintf and my_snprintf.
306
  vsnprintf(net->last_error, sizeof(net->last_error)-1,
1 by brian
clean slate
307
               format, args);
308
  va_end(args);
309
  strmov(net->sqlstate, sqlstate);
310
51.3.5 by Jay Pipes
Merged in from trunk.
311
  return;
1 by brian
clean slate
312
}
313
314
/*****************************************************************************
315
  Read a packet from server. Give error message if socket was down
316
  or packet is an error message
317
*****************************************************************************/
318
164 by Brian Aker
Commit cleanup of export types.
319
uint32_t cli_safe_read(MYSQL *mysql)
1 by brian
clean slate
320
{
321
  NET *net= &mysql->net;
322
  ulong len=0;
323
  init_sigpipe_variables
324
325
  /* Don't give sigpipe errors if the client doesn't want them */
326
  set_sigpipe(mysql);
327
  if (net->vio != 0)
328
    len=my_net_read(net);
329
  reset_sigpipe(mysql);
330
331
  if (len == packet_error || len == 0)
332
  {
333
#ifdef MYSQL_SERVER
334
    if (net->vio && vio_was_interrupted(net->vio))
335
      return (packet_error);
336
#endif /*MYSQL_SERVER*/
337
    end_server(mysql);
338
    set_mysql_error(mysql, net->last_errno == ER_NET_PACKET_TOO_LARGE ?
339
                    CR_NET_PACKET_TOO_LARGE: CR_SERVER_LOST, unknown_sqlstate);
340
    return (packet_error);
341
  }
342
  if (net->read_pos[0] == 255)
343
  {
344
    if (len > 3)
345
    {
346
      char *pos=(char*) net->read_pos+1;
347
      net->last_errno=uint2korr(pos);
348
      pos+=2;
349
      len-=2;
350
      if (protocol_41(mysql) && pos[0] == '#')
351
      {
352
	strmake(net->sqlstate, pos+1, SQLSTATE_LENGTH);
353
	pos+= SQLSTATE_LENGTH+1;
354
      }
355
      else
356
      {
357
        /*
358
          The SQL state hasn't been received -- it should be reset to HY000
359
          (unknown error sql state).
360
        */
361
362
        strmov(net->sqlstate, unknown_sqlstate);
363
      }
364
365
      (void) strmake(net->last_error,(char*) pos,
366
		     min((uint) len,(uint) sizeof(net->last_error)-1));
367
    }
368
    else
369
      set_mysql_error(mysql, CR_UNKNOWN_ERROR, unknown_sqlstate);
370
    /*
371
      Cover a protocol design error: error packet does not
372
      contain the server status. Therefore, the client has no way
373
      to find out whether there are more result sets of
374
      a multiple-result-set statement pending. Luckily, in 5.0 an
375
      error always aborts execution of a statement, wherever it is
376
      a multi-statement or a stored procedure, so it should be
377
      safe to unconditionally turn off the flag here.
378
    */
379
    mysql->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
380
381
    return(packet_error);
382
  }
383
  return len;
384
}
385
386
void free_rows(MYSQL_DATA *cur)
387
{
388
  if (cur)
389
  {
390
    free_root(&cur->alloc,MYF(0));
391
    my_free((uchar*) cur,MYF(0));
392
  }
393
}
394
164 by Brian Aker
Commit cleanup of export types.
395
bool
1 by brian
clean slate
396
cli_advanced_command(MYSQL *mysql, enum enum_server_command command,
164 by Brian Aker
Commit cleanup of export types.
397
		     const unsigned char *header, uint32_t header_length,
398
		     const unsigned char *arg, uint32_t arg_length, bool skip_check)
1 by brian
clean slate
399
{
400
  NET *net= &mysql->net;
401
  my_bool result= 1;
402
  init_sigpipe_variables
163 by Brian Aker
Merge Monty's code.
403
  my_bool stmt_skip= false;
1 by brian
clean slate
404
405
  /* Don't give sigpipe errors if the client doesn't want them */
406
  set_sigpipe(mysql);
407
408
  if (mysql->net.vio == 0)
409
  {						/* Do reconnect if possible */
410
    if (mysql_reconnect(mysql) || stmt_skip)
51.3.5 by Jay Pipes
Merged in from trunk.
411
      return(1);
1 by brian
clean slate
412
  }
413
  if (mysql->status != MYSQL_STATUS_READY ||
414
      mysql->server_status & SERVER_MORE_RESULTS_EXISTS)
415
  {
416
    set_mysql_error(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
51.3.5 by Jay Pipes
Merged in from trunk.
417
    return(1);
1 by brian
clean slate
418
  }
419
420
  net_clear_error(net);
421
  mysql->info=0;
155 by Brian Aker
Removing a few "additional" ways of saying uint64_t
422
  mysql->affected_rows= ~(uint64_t) 0;
1 by brian
clean slate
423
  /*
424
    We don't want to clear the protocol buffer on COM_QUIT, because if
425
    the previous command was a shutdown command, we may have the
426
    response for the COM_QUIT already in the communication buffer
427
  */
428
  net_clear(&mysql->net, (command != COM_QUIT));
429
430
  if (net_write_command(net,(uchar) command, header, header_length,
431
			arg, arg_length))
432
  {
433
    if (net->last_errno == ER_NET_PACKET_TOO_LARGE)
434
    {
435
      set_mysql_error(mysql, CR_NET_PACKET_TOO_LARGE, unknown_sqlstate);
436
      goto end;
437
    }
438
    end_server(mysql);
439
    if (mysql_reconnect(mysql) || stmt_skip)
440
      goto end;
441
    if (net_write_command(net,(uchar) command, header, header_length,
442
			  arg, arg_length))
443
    {
444
      set_mysql_error(mysql, CR_SERVER_GONE_ERROR, unknown_sqlstate);
445
      goto end;
446
    }
447
  }
448
  result=0;
449
  if (!skip_check)
450
    result= ((mysql->packet_length=cli_safe_read(mysql)) == packet_error ?
451
	     1 : 0);
452
end:
453
  reset_sigpipe(mysql);
51.3.5 by Jay Pipes
Merged in from trunk.
454
  return(result);
1 by brian
clean slate
455
}
456
457
void free_old_query(MYSQL *mysql)
458
{
459
  if (mysql->fields)
460
    free_root(&mysql->field_alloc,MYF(0));
461
  init_alloc_root(&mysql->field_alloc,8192,0); /* Assume rowlength < 8192 */
462
  mysql->fields= 0;
463
  mysql->field_count= 0;			/* For API */
464
  mysql->warning_count= 0;
465
  mysql->info= 0;
51.3.5 by Jay Pipes
Merged in from trunk.
466
  return;
1 by brian
clean slate
467
}
468
469
/*
470
  Flush result set sent from server
471
*/
472
473
static void cli_flush_use_result(MYSQL *mysql)
474
{
475
  /* Clear the current execution status */
476
  for (;;)
477
  {
478
    ulong pkt_len;
479
    if ((pkt_len=cli_safe_read(mysql)) == packet_error)
480
      break;
481
    if (pkt_len <= 8 && mysql->net.read_pos[0] == 254)
482
    {
483
      if (protocol_41(mysql))
484
      {
485
        char *pos= (char*) mysql->net.read_pos + 1;
486
        mysql->warning_count=uint2korr(pos); pos+=2;
487
        mysql->server_status=uint2korr(pos); pos+=2;
488
      }
489
      break;                            /* End of data */
490
    }
491
  }
51.3.5 by Jay Pipes
Merged in from trunk.
492
  return;
1 by brian
clean slate
493
}
494
495
496
/**************************************************************************
497
  Shut down connection
498
**************************************************************************/
499
500
void end_server(MYSQL *mysql)
501
{
502
  int save_errno= errno;
503
  if (mysql->net.vio != 0)
504
  {
505
    init_sigpipe_variables
506
    set_sigpipe(mysql);
507
    vio_delete(mysql->net.vio);
508
    reset_sigpipe(mysql);
509
    mysql->net.vio= 0;          /* Marker */
510
  }
511
  net_end(&mysql->net);
512
  free_old_query(mysql);
513
  errno= save_errno;
51.3.5 by Jay Pipes
Merged in from trunk.
514
  return;
1 by brian
clean slate
515
}
516
517
518
void STDCALL
519
mysql_free_result(MYSQL_RES *result)
520
{
521
  if (result)
522
  {
523
    MYSQL *mysql= result->handle;
524
    if (mysql)
525
    {
526
      if (mysql->unbuffered_fetch_owner == &result->unbuffered_fetch_cancelled)
527
        mysql->unbuffered_fetch_owner= 0;
528
      if (mysql->status == MYSQL_STATUS_USE_RESULT)
529
      {
530
        (*mysql->methods->flush_use_result)(mysql);
531
        mysql->status=MYSQL_STATUS_READY;
532
        if (mysql->unbuffered_fetch_owner)
163 by Brian Aker
Merge Monty's code.
533
          *mysql->unbuffered_fetch_owner= true;
1 by brian
clean slate
534
      }
535
    }
536
    free_rows(result->data);
537
    if (result->fields)
538
      free_root(&result->field_alloc,MYF(0));
539
    if (result->row)
540
      my_free((uchar*) result->row,MYF(0));
541
    my_free((uchar*) result,MYF(0));
542
  }
51.3.5 by Jay Pipes
Merged in from trunk.
543
  return;
1 by brian
clean slate
544
}
545
546
/****************************************************************************
547
  Get options from my.cnf
548
****************************************************************************/
549
550
static const char *default_options[]=
551
{
552
  "port","socket","compress","password","pipe", "timeout", "user",
51.3.5 by Jay Pipes
Merged in from trunk.
553
  "init-command", "host", "database", "return-found-rows",
1 by brian
clean slate
554
  "ssl-key" ,"ssl-cert" ,"ssl-ca" ,"ssl-capath",
555
  "character-sets-dir", "default-character-set", "interactive-timeout",
556
  "connect-timeout", "local-infile", "disable-local-infile",
557
  "ssl-cipher", "max-allowed-packet", "protocol", "shared-memory-base-name",
558
  "multi-results", "multi-statements", "multi-queries", "secure-auth",
559
  "report-data-truncation",
560
  NullS
561
};
562
563
static TYPELIB option_types={array_elements(default_options)-1,
564
			     "options",default_options, NULL};
565
566
const char *sql_protocol_names_lib[] =
567
{ "TCP", "SOCKET", "PIPE", "MEMORY", NullS };
568
TYPELIB sql_protocol_typelib = {array_elements(sql_protocol_names_lib)-1,"",
569
				sql_protocol_names_lib, NULL};
570
571
static int add_init_command(struct st_mysql_options *options, const char *cmd)
572
{
573
  char *tmp;
574
575
  if (!options->init_commands)
576
  {
577
    options->init_commands= (DYNAMIC_ARRAY*)my_malloc(sizeof(DYNAMIC_ARRAY),
578
						      MYF(MY_WME));
579
    init_dynamic_array(options->init_commands,sizeof(char*),0,5 CALLER_INFO);
580
  }
581
582
  if (!(tmp= my_strdup(cmd,MYF(MY_WME))) ||
583
      insert_dynamic(options->init_commands, (uchar*)&tmp))
584
  {
585
    my_free(tmp, MYF(MY_ALLOW_ZERO_PTR));
586
    return 1;
587
  }
588
589
  return 0;
590
}
591
592
void mysql_read_default_options(struct st_mysql_options *options,
593
				const char *filename,const char *group)
594
{
595
  int argc;
596
  char *argv_buff[1],**argv;
597
  const char *groups[3];
598
599
  argc=1; argv=argv_buff; argv_buff[0]= (char*) "client";
600
  groups[0]= (char*) "client"; groups[1]= (char*) group; groups[2]=0;
601
602
  load_defaults(filename, groups, &argc, &argv);
603
  if (argc != 1)				/* If some default option */
604
  {
605
    char **option=argv;
606
    while (*++option)
607
    {
608
      if (option[0][0] == '-' && option[0][1] == '-')
609
      {
610
	char *end=strcend(*option,'=');
611
	char *opt_arg=0;
612
	if (*end)
613
	{
614
	  opt_arg=end+1;
615
	  *end=0;				/* Remove '=' */
616
	}
617
	/* Change all '_' in variable name to '-' */
618
	for (end= *option ; *(end= strcend(end,'_')) ; )
619
	  *end= '-';
620
	switch (find_type(*option+2,&option_types,2)) {
621
	case 1:				/* port */
622
	  if (opt_arg)
623
	    options->port=atoi(opt_arg);
624
	  break;
625
	case 2:				/* socket */
626
	  if (opt_arg)
627
	  {
628
	    my_free(options->unix_socket,MYF(MY_ALLOW_ZERO_PTR));
629
	    options->unix_socket=my_strdup(opt_arg,MYF(MY_WME));
630
	  }
631
	  break;
632
	case 3:				/* compress */
633
	  options->compress=1;
634
	  options->client_flag|= CLIENT_COMPRESS;
635
	  break;
636
	case 4:				/* password */
637
	  if (opt_arg)
638
	  {
639
	    my_free(options->password,MYF(MY_ALLOW_ZERO_PTR));
640
	    options->password=my_strdup(opt_arg,MYF(MY_WME));
641
	  }
642
	  break;
643
        case 5:
644
          options->protocol = MYSQL_PROTOCOL_PIPE;
645
	case 20:			/* connect_timeout */
646
	case 6:				/* timeout */
647
	  if (opt_arg)
648
	    options->connect_timeout=atoi(opt_arg);
649
	  break;
650
	case 7:				/* user */
651
	  if (opt_arg)
652
	  {
653
	    my_free(options->user,MYF(MY_ALLOW_ZERO_PTR));
654
	    options->user=my_strdup(opt_arg,MYF(MY_WME));
655
	  }
656
	  break;
657
	case 8:				/* init-command */
658
	  add_init_command(options,opt_arg);
659
	  break;
660
	case 9:				/* host */
661
	  if (opt_arg)
662
	  {
663
	    my_free(options->host,MYF(MY_ALLOW_ZERO_PTR));
664
	    options->host=my_strdup(opt_arg,MYF(MY_WME));
665
	  }
666
	  break;
667
	case 10:			/* database */
668
	  if (opt_arg)
669
	  {
670
	    my_free(options->db,MYF(MY_ALLOW_ZERO_PTR));
671
	    options->db=my_strdup(opt_arg,MYF(MY_WME));
672
	  }
673
	  break;
674
	case 12:			/* return-found-rows */
675
	  options->client_flag|=CLIENT_FOUND_ROWS;
676
	  break;
677
	case 13:				/* Ignore SSL options */
678
	case 14:
679
	case 15:
680
	case 16:
681
        case 23:
682
	  break;
683
	case 17:			/* charset-lib */
684
	  my_free(options->charset_dir,MYF(MY_ALLOW_ZERO_PTR));
685
          options->charset_dir = my_strdup(opt_arg, MYF(MY_WME));
686
	  break;
687
	case 18:
688
	  my_free(options->charset_name,MYF(MY_ALLOW_ZERO_PTR));
689
          options->charset_name = my_strdup(opt_arg, MYF(MY_WME));
690
	  break;
691
	case 19:				/* Interactive-timeout */
692
	  options->client_flag|= CLIENT_INTERACTIVE;
693
	  break;
694
	case 21:
695
	  if (!opt_arg || atoi(opt_arg) != 0)
696
	    options->client_flag|= CLIENT_LOCAL_FILES;
697
	  else
698
	    options->client_flag&= ~CLIENT_LOCAL_FILES;
699
	  break;
700
	case 22:
701
	  options->client_flag&= ~CLIENT_LOCAL_FILES;
702
          break;
703
	case 24: /* max-allowed-packet */
704
          if (opt_arg)
705
	    options->max_allowed_packet= atoi(opt_arg);
706
	  break;
707
        case 25: /* protocol */
708
          if ((options->protocol= find_type(opt_arg,
709
					    &sql_protocol_typelib,0)) <= 0)
710
          {
711
            fprintf(stderr, "Unknown option to protocol: %s\n", opt_arg);
712
            exit(1);
713
          }
714
          break;
715
        case 26: /* shared_memory_base_name */
716
#ifdef HAVE_SMEM
717
          if (options->shared_memory_base_name != def_shared_memory_base_name)
718
            my_free(options->shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
719
          options->shared_memory_base_name=my_strdup(opt_arg,MYF(MY_WME));
720
#endif
721
          break;
722
	case 27: /* multi-results */
723
	  options->client_flag|= CLIENT_MULTI_RESULTS;
724
	  break;
725
	case 28: /* multi-statements */
726
	case 29: /* multi-queries */
727
	  options->client_flag|= CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS;
728
	  break;
729
        case 30: /* secure-auth */
163 by Brian Aker
Merge Monty's code.
730
          options->secure_auth= true;
1 by brian
clean slate
731
          break;
732
        case 31: /* report-data-truncation */
733
          options->report_data_truncation= opt_arg ? test(atoi(opt_arg)) : 1;
734
          break;
735
	default:
51.3.5 by Jay Pipes
Merged in from trunk.
736
          break;
1 by brian
clean slate
737
	}
738
      }
739
    }
740
  }
741
  free_defaults(argv);
51.3.5 by Jay Pipes
Merged in from trunk.
742
  return;
1 by brian
clean slate
743
}
744
745
746
/**************************************************************************
747
  Get column lengths of the current row
748
  If one uses mysql_use_result, res->lengths contains the length information,
749
  else the lengths are calculated from the offset between pointers.
750
**************************************************************************/
751
164 by Brian Aker
Commit cleanup of export types.
752
static void cli_fetch_lengths(uint32_t *to, MYSQL_ROW column, uint32_t field_count)
1 by brian
clean slate
753
{ 
164 by Brian Aker
Commit cleanup of export types.
754
  uint32_t *prev_length;
1 by brian
clean slate
755
  char *start=0;
756
  MYSQL_ROW end;
757
758
  prev_length=0;				/* Keep gcc happy */
759
  for (end=column + field_count + 1 ; column != end ; column++, to++)
760
  {
761
    if (!*column)
762
    {
763
      *to= 0;					/* Null */
764
      continue;
765
    }
766
    if (start)					/* Found end of prev string */
767
      *prev_length= (ulong) (*column-start-1);
768
    start= *column;
769
    prev_length= to;
770
  }
771
}
772
773
/***************************************************************************
774
  Change field rows to field structs
775
***************************************************************************/
776
777
MYSQL_FIELD *
778
unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
779
	      my_bool default_value, uint server_capabilities)
780
{
781
  MYSQL_ROWS	*row;
782
  MYSQL_FIELD	*field,*result;
164 by Brian Aker
Commit cleanup of export types.
783
  uint32_t lengths[9];				/* Max of fields */
1 by brian
clean slate
784
785
  field= result= (MYSQL_FIELD*) alloc_root(alloc,
786
					   (uint) sizeof(*field)*fields);
787
  if (!result)
788
  {
789
    free_rows(data);				/* Free old data */
51.3.5 by Jay Pipes
Merged in from trunk.
790
    return(0);
1 by brian
clean slate
791
  }
792
  bzero((char*) field, (uint) sizeof(MYSQL_FIELD)*fields);
793
  if (server_capabilities & CLIENT_PROTOCOL_41)
794
  {
795
    /* server is 4.1, and returns the new field result format */
796
    for (row=data->data; row ; row = row->next,field++)
797
    {
798
      uchar *pos;
799
      /* fields count may be wrong */
51.3.5 by Jay Pipes
Merged in from trunk.
800
      assert((uint) (field - result) < fields);
1 by brian
clean slate
801
      cli_fetch_lengths(&lengths[0], row->data, default_value ? 8 : 7);
802
      field->catalog=   strmake_root(alloc,(char*) row->data[0], lengths[0]);
803
      field->db=        strmake_root(alloc,(char*) row->data[1], lengths[1]);
804
      field->table=     strmake_root(alloc,(char*) row->data[2], lengths[2]);
805
      field->org_table= strmake_root(alloc,(char*) row->data[3], lengths[3]);
806
      field->name=      strmake_root(alloc,(char*) row->data[4], lengths[4]);
807
      field->org_name=  strmake_root(alloc,(char*) row->data[5], lengths[5]);
808
809
      field->catalog_length=	lengths[0];
810
      field->db_length=		lengths[1];
811
      field->table_length=	lengths[2];
812
      field->org_table_length=	lengths[3];
813
      field->name_length=	lengths[4];
814
      field->org_name_length=	lengths[5];
815
816
      /* Unpack fixed length parts */
817
      pos= (uchar*) row->data[6];
818
      field->charsetnr= uint2korr(pos);
819
      field->length=	(uint) uint4korr(pos+2);
820
      field->type=	(enum enum_field_types) pos[6];
821
      field->flags=	uint2korr(pos+7);
822
      field->decimals=  (uint) pos[9];
823
824
      if (INTERNAL_NUM_FIELD(field))
825
        field->flags|= NUM_FLAG;
826
      if (default_value && row->data[7])
827
      {
828
        field->def=strmake_root(alloc,(char*) row->data[7], lengths[7]);
829
	field->def_length= lengths[7];
830
      }
831
      else
832
        field->def=0;
833
      field->max_length= 0;
834
    }
835
  }
836
#ifndef DELETE_SUPPORT_OF_4_0_PROTOCOL
837
  else
838
  {
839
    /* old protocol, for backward compatibility */
840
    for (row=data->data; row ; row = row->next,field++)
841
    {
842
      cli_fetch_lengths(&lengths[0], row->data, default_value ? 6 : 5);
843
      field->org_table= field->table=  strdup_root(alloc,(char*) row->data[0]);
844
      field->name=   strdup_root(alloc,(char*) row->data[1]);
845
      field->length= (uint) uint3korr(row->data[2]);
846
      field->type=   (enum enum_field_types) (uchar) row->data[3][0];
847
848
      field->catalog=(char*)  "";
849
      field->db=     (char*)  "";
850
      field->catalog_length= 0;
851
      field->db_length= 0;
852
      field->org_table_length=	field->table_length=	lengths[0];
853
      field->name_length=	lengths[1];
854
855
      if (server_capabilities & CLIENT_LONG_FLAG)
856
      {
857
        field->flags=   uint2korr(row->data[4]);
858
        field->decimals=(uint) (uchar) row->data[4][2];
859
      }
860
      else
861
      {
862
        field->flags=   (uint) (uchar) row->data[4][0];
863
        field->decimals=(uint) (uchar) row->data[4][1];
864
      }
865
      if (INTERNAL_NUM_FIELD(field))
866
        field->flags|= NUM_FLAG;
867
      if (default_value && row->data[5])
868
      {
869
        field->def=strdup_root(alloc,(char*) row->data[5]);
870
	field->def_length= lengths[5];
871
      }
872
      else
873
        field->def=0;
874
      field->max_length= 0;
875
    }
876
  }
877
#endif /* DELETE_SUPPORT_OF_4_0_PROTOCOL */
878
  free_rows(data);				/* Free old data */
51.3.5 by Jay Pipes
Merged in from trunk.
879
  return(result);
1 by brian
clean slate
880
}
881
882
/* Read all rows (fields or data) from server */
883
884
MYSQL_DATA *cli_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
885
			  unsigned int fields)
886
{
887
  uint	field;
888
  ulong pkt_len;
889
  ulong len;
890
  uchar *cp;
891
  char	*to, *end_to;
892
  MYSQL_DATA *result;
893
  MYSQL_ROWS **prev_ptr,*cur;
894
  NET *net = &mysql->net;
895
896
  if ((pkt_len= cli_safe_read(mysql)) == packet_error)
51.3.5 by Jay Pipes
Merged in from trunk.
897
    return(0);
1 by brian
clean slate
898
  if (!(result=(MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA),
899
				       MYF(MY_WME | MY_ZEROFILL))))
900
  {
901
    set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate);
51.3.5 by Jay Pipes
Merged in from trunk.
902
    return(0);
1 by brian
clean slate
903
  }
904
  init_alloc_root(&result->alloc,8192,0);	/* Assume rowlength < 8192 */
905
  result->alloc.min_malloc=sizeof(MYSQL_ROWS);
906
  prev_ptr= &result->data;
907
  result->rows=0;
908
  result->fields=fields;
909
910
  /*
911
    The last EOF packet is either a single 254 character or (in MySQL 4.1)
912
    254 followed by 1-7 status bytes.
913
914
    This doesn't conflict with normal usage of 254 which stands for a
915
    string where the length of the string is 8 bytes. (see net_field_length())
916
  */
917
918
  while (*(cp=net->read_pos) != 254 || pkt_len >= 8)
919
  {
920
    result->rows++;
921
    if (!(cur= (MYSQL_ROWS*) alloc_root(&result->alloc,
922
					sizeof(MYSQL_ROWS))) ||
923
	!(cur->data= ((MYSQL_ROW)
924
		      alloc_root(&result->alloc,
925
				 (fields+1)*sizeof(char *)+pkt_len))))
926
    {
927
      free_rows(result);
928
      set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate);
51.3.5 by Jay Pipes
Merged in from trunk.
929
      return(0);
1 by brian
clean slate
930
    }
931
    *prev_ptr=cur;
932
    prev_ptr= &cur->next;
933
    to= (char*) (cur->data+fields+1);
934
    end_to=to+pkt_len-1;
935
    for (field=0 ; field < fields ; field++)
936
    {
937
      if ((len=(ulong) net_field_length(&cp)) == NULL_LENGTH)
938
      {						/* null field */
939
	cur->data[field] = 0;
940
      }
941
      else
942
      {
943
	cur->data[field] = to;
944
        if (len > (ulong) (end_to - to))
945
        {
946
          free_rows(result);
947
          set_mysql_error(mysql, CR_MALFORMED_PACKET, unknown_sqlstate);
51.3.5 by Jay Pipes
Merged in from trunk.
948
          return(0);
1 by brian
clean slate
949
        }
950
	memcpy(to,(char*) cp,len); to[len]=0;
951
	to+=len+1;
952
	cp+=len;
953
	if (mysql_fields)
954
	{
955
	  if (mysql_fields[field].max_length < len)
956
	    mysql_fields[field].max_length=len;
957
	}
958
      }
959
    }
960
    cur->data[field]=to;			/* End of last field */
961
    if ((pkt_len=cli_safe_read(mysql)) == packet_error)
962
    {
963
      free_rows(result);
51.3.5 by Jay Pipes
Merged in from trunk.
964
      return(0);
1 by brian
clean slate
965
    }
966
  }
967
  *prev_ptr=0;					/* last pointer is null */
968
  if (pkt_len > 1)				/* MySQL 4.1 protocol */
969
  {
970
    mysql->warning_count= uint2korr(cp+1);
971
    mysql->server_status= uint2korr(cp+3);
972
  }
51.3.5 by Jay Pipes
Merged in from trunk.
973
  return(result);
1 by brian
clean slate
974
}
975
976
/*
977
  Read one row. Uses packet buffer as storage for fields.
978
  When next packet is read, the previous field values are destroyed
979
*/
980
981
164 by Brian Aker
Commit cleanup of export types.
982
static int32_t
983
read_one_row(MYSQL *mysql, uint32_t fields, MYSQL_ROW row, uint32_t *lengths)
1 by brian
clean slate
984
{
985
  uint field;
986
  ulong pkt_len,len;
987
  uchar *pos, *prev_pos, *end_pos;
988
  NET *net= &mysql->net;
989
990
  if ((pkt_len=cli_safe_read(mysql)) == packet_error)
991
    return -1;
992
  if (pkt_len <= 8 && net->read_pos[0] == 254)
993
  {
994
    if (pkt_len > 1)				/* MySQL 4.1 protocol */
995
    {
996
      mysql->warning_count= uint2korr(net->read_pos+1);
997
      mysql->server_status= uint2korr(net->read_pos+3);
998
    }
999
    return 1;				/* End of data */
1000
  }
1001
  prev_pos= 0;				/* allowed to write at packet[-1] */
1002
  pos=net->read_pos;
1003
  end_pos=pos+pkt_len;
1004
  for (field=0 ; field < fields ; field++)
1005
  {
1006
    if ((len=(ulong) net_field_length(&pos)) == NULL_LENGTH)
1007
    {						/* null field */
1008
      row[field] = 0;
1009
      *lengths++=0;
1010
    }
1011
    else
1012
    {
1013
      if (len > (ulong) (end_pos - pos))
1014
      {
1015
        set_mysql_error(mysql, CR_UNKNOWN_ERROR, unknown_sqlstate);
1016
        return -1;
1017
      }
1018
      row[field] = (char*) pos;
1019
      pos+=len;
1020
      *lengths++=len;
1021
    }
1022
    if (prev_pos)
1023
      *prev_pos=0;				/* Terminate prev field */
1024
    prev_pos=pos;
1025
  }
1026
  row[field]=(char*) prev_pos+1;		/* End of last field */
1027
  *prev_pos=0;					/* Terminate last field */
1028
  return 0;
1029
}
1030
1031
1032
/****************************************************************************
1033
  Init MySQL structure or allocate one
1034
****************************************************************************/
1035
1036
MYSQL * STDCALL
1037
mysql_init(MYSQL *mysql)
1038
{
1039
  if (mysql_server_init(0, NULL, NULL))
1040
    return 0;
1041
  if (!mysql)
1042
  {
1043
    if (!(mysql=(MYSQL*) my_malloc(sizeof(*mysql),MYF(MY_WME | MY_ZEROFILL))))
1044
    {
1045
      set_mysql_error(NULL, CR_OUT_OF_MEMORY, unknown_sqlstate);
1046
      return 0;
1047
    }
1048
    mysql->free_me=1;
1049
  }
1050
  else
1051
    bzero((char*) (mysql), sizeof(*(mysql)));
1052
  mysql->options.connect_timeout= CONNECT_TIMEOUT;
1053
  mysql->charset=default_client_charset_info;
1054
  strmov(mysql->net.sqlstate, not_error_sqlstate);
1055
1056
  /*
1057
    Only enable LOAD DATA INFILE by default if configured with
1058
    --enable-local-infile
1059
  */
1060
1061
#if defined(ENABLED_LOCAL_INFILE) && !defined(MYSQL_SERVER)
1062
  mysql->options.client_flag|= CLIENT_LOCAL_FILES;
1063
#endif
1064
1065
#ifdef HAVE_SMEM
1066
  mysql->options.shared_memory_base_name= (char*) def_shared_memory_base_name;
1067
#endif
1068
1069
  mysql->options.methods_to_use= MYSQL_OPT_GUESS_CONNECTION;
163 by Brian Aker
Merge Monty's code.
1070
  mysql->options.report_data_truncation= true;  /* default */
1 by brian
clean slate
1071
1072
  /*
1073
    By default we don't reconnect because it could silently corrupt data (after
1074
    reconnection you potentially lose table locks, user variables, session
1075
    variables (transactions but they are specifically dealt with in
1076
    mysql_reconnect()).
1077
    This is a change: < 5.0.3 mysql->reconnect was set to 1 by default.
1078
    How this change impacts existing apps:
1079
    - existing apps which relyed on the default will see a behaviour change;
1080
    they will have to set reconnect=1 after mysql_real_connect().
1081
    - existing apps which explicitely asked for reconnection (the only way they
1082
    could do it was by setting mysql.reconnect to 1 after mysql_real_connect())
1083
    will not see a behaviour change.
1084
    - existing apps which explicitely asked for no reconnection
1085
    (mysql.reconnect=0) will not see a behaviour change.
1086
  */
1087
  mysql->reconnect= 0;
1088
1089
  return mysql;
1090
}
1091
1092
1093
/*
1094
  Fill in SSL part of MYSQL structure and set 'use_ssl' flag.
1095
  NB! Errors are not reported until you do mysql_real_connect.
1096
*/
1097
1098
#define strdup_if_not_null(A) (A) == 0 ? 0 : my_strdup((A),MYF(MY_WME))
1099
1100
/*
1101
  Note that the mysql argument must be initialized with mysql_init()
1102
  before calling mysql_real_connect !
1103
*/
1104
164 by Brian Aker
Commit cleanup of export types.
1105
static bool cli_read_query_result(MYSQL *mysql);
1 by brian
clean slate
1106
static MYSQL_RES *cli_use_result(MYSQL *mysql);
1107
1108
static MYSQL_METHODS client_methods=
1109
{
1110
  cli_read_query_result,                       /* read_query_result */
1111
  cli_advanced_command,                        /* advanced_command */
1112
  cli_read_rows,                               /* read_rows */
1113
  cli_use_result,                              /* use_result */
1114
  cli_fetch_lengths,                           /* fetch_lengths */
47 by Brian Aker
First pass on removing binary protocol from client library.
1115
  cli_flush_use_result,                         /* flush_use_result */
48 by Brian Aker
Second pass on removing PS from client library
1116
#ifndef MYSQL_SERVER
1117
  cli_list_fields,                            /* list_fields */
1118
  cli_unbuffered_fetch,                        /* unbuffered_fetch */
1119
  cli_read_statistics,                         /* read_statistics */
1 by brian
clean slate
1120
  cli_read_query_result,                       /* next_result */
48 by Brian Aker
Second pass on removing PS from client library
1121
  cli_read_change_user_result,                 /* read_change_user_result */
77.1.54 by Monty Taylor
More warnings cleanups.
1122
#else
1123
  0,0,0,0,0
48 by Brian Aker
Second pass on removing PS from client library
1124
#endif
1 by brian
clean slate
1125
};
1126
1127
C_MODE_START
1128
int mysql_init_character_set(MYSQL *mysql)
1129
{
1130
  const char *default_collation_name;
1131
  
1132
  /* Set character set */
1133
  if (!mysql->options.charset_name)
1134
  {
1135
    default_collation_name= MYSQL_DEFAULT_COLLATION_NAME;
1136
    if (!(mysql->options.charset_name= 
1137
       my_strdup(MYSQL_DEFAULT_CHARSET_NAME,MYF(MY_WME))))
1138
    return 1;
1139
  }
1140
  else
1141
    default_collation_name= NULL;
1142
  
1143
  {
1144
    const char *save= charsets_dir;
1145
    if (mysql->options.charset_dir)
1146
      charsets_dir=mysql->options.charset_dir;
1147
    mysql->charset=get_charset_by_csname(mysql->options.charset_name,
1148
                                         MY_CS_PRIMARY, MYF(MY_WME));
1149
    if (mysql->charset && default_collation_name)
1150
    {
1151
      CHARSET_INFO *collation;
1152
      if ((collation= 
1153
           get_charset_by_name(default_collation_name, MYF(MY_WME))))
1154
      {
1155
        if (!my_charset_same(mysql->charset, collation))
1156
        {
1157
          my_printf_error(ER_UNKNOWN_ERROR, 
1158
                         "COLLATION %s is not valid for CHARACTER SET %s",
1159
                         MYF(0),
1160
                         default_collation_name, mysql->options.charset_name);
1161
          mysql->charset= NULL;
1162
        }
1163
        else
1164
        {
1165
          mysql->charset= collation;
1166
        }
1167
      }
1168
      else
1169
        mysql->charset= NULL;
1170
    }
1171
    charsets_dir= save;
1172
  }
1173
1174
  if (!mysql->charset)
1175
  {
1176
    if (mysql->options.charset_dir)
1177
      set_mysql_extended_error(mysql, CR_CANT_READ_CHARSET, unknown_sqlstate,
1178
                               ER(CR_CANT_READ_CHARSET),
1179
                               mysql->options.charset_name,
1180
                               mysql->options.charset_dir);
1181
    else
1182
    {
1183
      char cs_dir_name[FN_REFLEN];
1184
      get_charsets_dir(cs_dir_name);
1185
      set_mysql_extended_error(mysql, CR_CANT_READ_CHARSET, unknown_sqlstate,
1186
                               ER(CR_CANT_READ_CHARSET),
1187
                               mysql->options.charset_name,
1188
                               cs_dir_name);
1189
    }
1190
    return 1;
1191
  }
1192
  return 0;
1193
}
1194
C_MODE_END
1195
1196
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
1197
MYSQL * STDCALL
1 by brian
clean slate
1198
CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
1199
                       const char *passwd, const char *db,
164 by Brian Aker
Commit cleanup of export types.
1200
                       uint32_t port, const char *unix_socket, uint32_t client_flag)
1 by brian
clean slate
1201
{
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
1202
  char          buff[NAME_LEN+USERNAME_LENGTH+100];
1203
  char          *end,*host_info=NULL;
164 by Brian Aker
Commit cleanup of export types.
1204
  uint32_t         pkt_length;
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
1205
  NET           *net= &mysql->net;
1206
  struct        sockaddr_un UNIXaddr;
1 by brian
clean slate
1207
  init_sigpipe_variables
1208
1209
  /* Don't give sigpipe errors if the client doesn't want them */
1210
  set_sigpipe(mysql);
1211
  mysql->methods= &client_methods;
1212
  net->vio = 0;				/* If something goes wrong */
1213
  mysql->client_flag=0;			/* For handshake */
1214
1215
  /* use default options */
1216
  if (mysql->options.my_cnf_file || mysql->options.my_cnf_group)
1217
  {
1218
    mysql_read_default_options(&mysql->options,
1219
			       (mysql->options.my_cnf_file ?
1220
				mysql->options.my_cnf_file : "my"),
1221
			       mysql->options.my_cnf_group);
1222
    my_free(mysql->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR));
1223
    my_free(mysql->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR));
1224
    mysql->options.my_cnf_file=mysql->options.my_cnf_group=0;
1225
  }
1226
1227
  /* Some empty-string-tests are done because of ODBC */
1228
  if (!host || !host[0])
1229
    host=mysql->options.host;
1230
  if (!user || !user[0])
1231
  {
1232
    user=mysql->options.user;
1233
    if (!user)
1234
      user= "";
1235
  }
1236
  if (!passwd)
1237
  {
1238
    passwd=mysql->options.password;
1239
    if (!passwd)
1240
      passwd= "";
1241
  }
1242
  if (!db || !db[0])
1243
    db=mysql->options.db;
1244
  if (!port)
1245
    port=mysql->options.port;
1246
  if (!unix_socket)
1247
    unix_socket=mysql->options.unix_socket;
1248
1249
  mysql->server_status=SERVER_STATUS_AUTOCOMMIT;
1250
1251
  /*
1252
    Part 0: Grab a socket and connect it to the server
1253
  */
1254
#if defined(HAVE_SMEM)
1255
  if ((!mysql->options.protocol ||
1256
       mysql->options.protocol == MYSQL_PROTOCOL_MEMORY) &&
1257
      (!host || !strcmp(host,LOCAL_HOST)))
1258
  {
1259
    if ((create_shared_memory(mysql,net, mysql->options.connect_timeout)) ==
1260
	INVALID_HANDLE_VALUE)
1261
    {
1262
      if (mysql->options.protocol == MYSQL_PROTOCOL_MEMORY)
1263
	goto error;
1264
1265
      /*
1266
        Try also with PIPE or TCP/IP. Clear the error from
1267
        create_shared_memory().
1268
      */
1269
1270
      net_clear_error(net);
1271
    }
1272
    else
1273
    {
1274
      mysql->options.protocol=MYSQL_PROTOCOL_MEMORY;
1275
      unix_socket = 0;
1276
      host=mysql->options.shared_memory_base_name;
77.1.18 by Monty Taylor
Removed my_vsnprintf and my_snprintf.
1277
      snprintf(host_info=buff, sizeof(buff)-1,
1278
               ER(CR_SHARED_MEMORY_CONNECTION), host);
1 by brian
clean slate
1279
    }
1280
  }
1281
#endif /* HAVE_SMEM */
1282
  if (!net->vio &&
1283
      (!mysql->options.protocol ||
1284
       mysql->options.protocol == MYSQL_PROTOCOL_SOCKET) &&
1285
      (unix_socket || mysql_unix_port) &&
1286
      (!host || !strcmp(host,LOCAL_HOST)))
1287
  {
1288
    my_socket sock= socket(AF_UNIX, SOCK_STREAM, 0);
1289
    if (sock == SOCKET_ERROR)
1290
    {
1291
      set_mysql_extended_error(mysql, CR_SOCKET_CREATE_ERROR,
1292
                               unknown_sqlstate,
1293
                               ER(CR_SOCKET_CREATE_ERROR),
1294
                               socket_errno);
1295
      goto error;
1296
    }
1297
1298
    net->vio= vio_new(sock, VIO_TYPE_SOCKET,
1299
                      VIO_LOCALHOST | VIO_BUFFERED_READ);
1300
    if (!net->vio)
1301
    {
1302
      set_mysql_error(mysql, CR_CONN_UNKNOW_PROTOCOL, unknown_sqlstate);
1303
      closesocket(sock);
1304
      goto error;
1305
    }
1306
1307
    host= LOCAL_HOST;
1308
    if (!unix_socket)
1309
      unix_socket= mysql_unix_port;
1310
    host_info= (char*) ER(CR_LOCALHOST_CONNECTION);
1311
1312
    bzero((char*) &UNIXaddr, sizeof(UNIXaddr));
1313
    UNIXaddr.sun_family= AF_UNIX;
1314
    strmake(UNIXaddr.sun_path, unix_socket, sizeof(UNIXaddr.sun_path)-1);
1315
1316
    if (my_connect(sock, (struct sockaddr *) &UNIXaddr, sizeof(UNIXaddr),
1317
		   mysql->options.connect_timeout))
1318
    {
1319
      set_mysql_extended_error(mysql, CR_CONNECTION_ERROR,
1320
                               unknown_sqlstate,
1321
                               ER(CR_CONNECTION_ERROR),
1322
                               unix_socket, socket_errno);
1323
      vio_delete(net->vio);
1324
      net->vio= 0;
1325
      goto error;
1326
    }
1327
    mysql->options.protocol=MYSQL_PROTOCOL_SOCKET;
1328
  }
1329
  if (!net->vio &&
1330
      (!mysql->options.protocol ||
1331
       mysql->options.protocol == MYSQL_PROTOCOL_TCP))
1332
  {
1333
    struct addrinfo *res_lst, hints, *t_res;
1334
    int gai_errno;
1335
    char port_buf[NI_MAXSERV];
1336
1337
    unix_socket=0;				/* This is not used */
1338
1339
    if (!port)
1340
      port= mysql_port;
1341
1342
    if (!host)
1343
      host= LOCAL_HOST;
1344
77.1.18 by Monty Taylor
Removed my_vsnprintf and my_snprintf.
1345
    snprintf(host_info=buff, sizeof(buff)-1, ER(CR_TCP_CONNECTION), host);
1 by brian
clean slate
1346
1347
    memset(&hints, 0, sizeof(hints));
1348
    hints.ai_socktype= SOCK_STREAM;
1349
    hints.ai_protocol= IPPROTO_TCP;
1350
    hints.ai_family= AF_UNSPEC;
1351
77.1.18 by Monty Taylor
Removed my_vsnprintf and my_snprintf.
1352
    snprintf(port_buf, NI_MAXSERV, "%d", port);
1 by brian
clean slate
1353
    gai_errno= getaddrinfo(host, port_buf, &hints, &res_lst);
1354
1355
    if (gai_errno != 0) 
1356
    { 
1357
      set_mysql_extended_error(mysql, CR_UNKNOWN_HOST, unknown_sqlstate,
1358
                               ER(CR_UNKNOWN_HOST), host, errno);
1359
1360
      goto error;
1361
    }
1362
1363
    /* We only look at the first item (something to think about changing in the future) */
1364
    t_res= res_lst; 
1365
    {
1366
      my_socket sock= socket(t_res->ai_family, t_res->ai_socktype,
1367
                             t_res->ai_protocol);
1368
      if (sock == SOCKET_ERROR)
1369
      {
1370
        set_mysql_extended_error(mysql, CR_IPSOCK_ERROR, unknown_sqlstate,
1371
                                 ER(CR_IPSOCK_ERROR), socket_errno);
1372
        freeaddrinfo(res_lst);
1373
        goto error;
1374
      }
1375
1376
      net->vio= vio_new(sock, VIO_TYPE_TCPIP, VIO_BUFFERED_READ);
1377
      if (! net->vio )
1378
      {
1379
        set_mysql_error(mysql, CR_CONN_UNKNOW_PROTOCOL, unknown_sqlstate);
1380
        closesocket(sock);
1381
        freeaddrinfo(res_lst);
1382
        goto error;
1383
      }
1384
1385
      if (my_connect(sock, t_res->ai_addr, t_res->ai_addrlen,
1386
                     mysql->options.connect_timeout))
1387
      {
1388
        set_mysql_extended_error(mysql, CR_CONN_HOST_ERROR, unknown_sqlstate,
1389
                                 ER(CR_CONN_HOST_ERROR), host, socket_errno);
1390
        vio_delete(net->vio);
1391
        net->vio= 0;
1392
        freeaddrinfo(res_lst);
1393
        goto error;
1394
      }
1395
    }
1396
1397
    freeaddrinfo(res_lst);
1398
  }
1399
1400
  if (!net->vio)
1401
  {
1402
    set_mysql_error(mysql, CR_CONN_UNKNOW_PROTOCOL, unknown_sqlstate);
1403
    goto error;
1404
  }
1405
1406
  if (my_net_init(net, net->vio))
1407
  {
1408
    vio_delete(net->vio);
1409
    net->vio = 0;
1410
    set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate);
1411
    goto error;
1412
  }
163 by Brian Aker
Merge Monty's code.
1413
  vio_keepalive(net->vio,true);
1 by brian
clean slate
1414
1415
  /* If user set read_timeout, let it override the default */
1416
  if (mysql->options.read_timeout)
1417
    my_net_set_read_timeout(net, mysql->options.read_timeout);
1418
1419
  /* If user set write_timeout, let it override the default */
1420
  if (mysql->options.write_timeout)
1421
    my_net_set_write_timeout(net, mysql->options.write_timeout);
1422
1423
  if (mysql->options.max_allowed_packet)
1424
    net->max_packet_size= mysql->options.max_allowed_packet;
1425
1426
  /* Get version info */
1427
  mysql->protocol_version= PROTOCOL_VERSION;	/* Assume this */
1428
  if (mysql->options.connect_timeout &&
1429
      vio_poll_read(net->vio, mysql->options.connect_timeout))
1430
  {
1431
    set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
1432
                             ER(CR_SERVER_LOST_EXTENDED),
1433
                             "waiting for initial communication packet",
1434
                             errno);
1435
    goto error;
1436
  }
1437
1438
  /*
1439
    Part 1: Connection established, read and parse first packet
1440
  */
1441
1442
  if ((pkt_length=cli_safe_read(mysql)) == packet_error)
1443
  {
1444
    if (mysql->net.last_errno == CR_SERVER_LOST)
1445
      set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
1446
                               ER(CR_SERVER_LOST_EXTENDED),
1447
                               "reading initial communication packet",
1448
                               errno);
1449
    goto error;
1450
  }
1451
  /* Check if version of protocol matches current one */
1452
1453
  mysql->protocol_version= net->read_pos[0];
1454
  if (mysql->protocol_version != PROTOCOL_VERSION)
1455
  {
1456
    set_mysql_extended_error(mysql, CR_VERSION_ERROR, unknown_sqlstate,
1457
                             ER(CR_VERSION_ERROR), mysql->protocol_version,
1458
                             PROTOCOL_VERSION);
1459
    goto error;
1460
  }
1461
  end=strend((char*) net->read_pos+1);
1462
  mysql->thread_id=uint4korr(end+1);
1463
  end+=5;
1464
  /* 
1465
    Scramble is split into two parts because old clients does not understand
1466
    long scrambles; here goes the first part.
1467
  */
1468
  strmake(mysql->scramble, end, SCRAMBLE_LENGTH_323);
1469
  end+= SCRAMBLE_LENGTH_323+1;
1470
1471
  if (pkt_length >= (uint) (end+1 - (char*) net->read_pos))
1472
    mysql->server_capabilities=uint2korr(end);
1473
  if (pkt_length >= (uint) (end+18 - (char*) net->read_pos))
1474
  {
1475
    /* New protocol with 16 bytes to describe server characteristics */
1476
    mysql->server_language=end[2];
1477
    mysql->server_status=uint2korr(end+3);
1478
  }
1479
  end+= 18;
1480
  if (pkt_length >= (uint) (end + SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323 + 1 - 
1481
                           (char *) net->read_pos))
1482
    strmake(mysql->scramble+SCRAMBLE_LENGTH_323, end,
1483
            SCRAMBLE_LENGTH-SCRAMBLE_LENGTH_323);
1484
  else
1485
    mysql->server_capabilities&= ~CLIENT_SECURE_CONNECTION;
1486
1487
  if (mysql->options.secure_auth && passwd[0] &&
1488
      !(mysql->server_capabilities & CLIENT_SECURE_CONNECTION))
1489
  {
1490
    set_mysql_error(mysql, CR_SECURE_AUTH, unknown_sqlstate);
1491
    goto error;
1492
  }
1493
1494
  if (mysql_init_character_set(mysql))
1495
    goto error;
1496
1497
  /* Save connection information */
1498
  if (!my_multi_malloc(MYF(0),
1499
		       &mysql->host_info, (uint) strlen(host_info)+1,
1500
		       &mysql->host,      (uint) strlen(host)+1,
1501
		       &mysql->unix_socket,unix_socket ?
1502
		       (uint) strlen(unix_socket)+1 : (uint) 1,
1503
		       &mysql->server_version,
1504
		       (uint) (end - (char*) net->read_pos),
1505
		       NullS) ||
1506
      !(mysql->user=my_strdup(user,MYF(0))) ||
1507
      !(mysql->passwd=my_strdup(passwd,MYF(0))))
1508
  {
1509
    set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate);
1510
    goto error;
1511
  }
1512
  strmov(mysql->host_info,host_info);
1513
  strmov(mysql->host,host);
1514
  if (unix_socket)
1515
    strmov(mysql->unix_socket,unix_socket);
1516
  else
1517
    mysql->unix_socket=0;
1518
  strmov(mysql->server_version,(char*) net->read_pos+1);
1519
  mysql->port=port;
1520
1521
  /*
1522
    Part 2: format and send client info to the server for access check
1523
  */
1524
  
1525
  client_flag|=mysql->options.client_flag;
1526
  client_flag|=CLIENT_CAPABILITIES;
1527
  if (client_flag & CLIENT_MULTI_STATEMENTS)
1528
    client_flag|= CLIENT_MULTI_RESULTS;
1529
1530
  if (db)
1531
    client_flag|=CLIENT_CONNECT_WITH_DB;
1532
1533
  /* Remove options that server doesn't support */
1534
  client_flag= ((client_flag &
1535
		 ~(CLIENT_COMPRESS | CLIENT_SSL | CLIENT_PROTOCOL_41)) |
1536
		(client_flag & mysql->server_capabilities));
1537
  client_flag&= ~CLIENT_COMPRESS;
1538
1539
  if (client_flag & CLIENT_PROTOCOL_41)
1540
  {
1541
    /* 4.1 server and 4.1 client has a 32 byte option flag */
1542
    int4store(buff,client_flag);
1543
    int4store(buff+4, net->max_packet_size);
1544
    buff[8]= (char) mysql->charset->number;
1545
    bzero(buff+9, 32-9);
1546
    end= buff+32;
1547
  }
1548
  else
1549
  {
1550
    int2store(buff,client_flag);
1551
    int3store(buff+2,net->max_packet_size);
1552
    end= buff+5;
1553
  }
1554
  mysql->client_flag=client_flag;
1555
1556
  /* This needs to be changed as it's not useful with big packets */
1557
  if (user && user[0])
1558
    strmake(end,user,USERNAME_LENGTH);          /* Max user name */
1559
  else
1560
    read_user_name((char*) end);
1561
1562
  /* We have to handle different version of handshake here */
1563
#ifdef _CUSTOMCONFIG_
1564
#include "_cust_libmysql.h"
1565
#endif
1566
  end= strend(end) + 1;
1567
  if (passwd[0])
1568
  {
1569
    {
1570
      *end++= SCRAMBLE_LENGTH;
1571
      scramble(end, mysql->scramble, passwd);
1572
      end+= SCRAMBLE_LENGTH;
1573
    }
1574
  }
1575
  else
1576
    *end++= '\0';                               /* empty password */
1577
1578
  /* Add database if needed */
1579
  if (db && (mysql->server_capabilities & CLIENT_CONNECT_WITH_DB))
1580
  {
1581
    end= strmake(end, db, NAME_LEN) + 1;
1582
    mysql->db= my_strdup(db,MYF(MY_WME));
1583
    db= 0;
1584
  }
1585
  /* Write authentication package */
1586
  if (my_net_write(net, (uchar*) buff, (size_t) (end-buff)) || net_flush(net))
1587
  {
1588
    set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
1589
                             ER(CR_SERVER_LOST_EXTENDED),
1590
                             "sending authentication information",
1591
                             errno);
1592
    goto error;
1593
  }
1594
  
1595
  /*
1596
    Part 3: Authorization data's been sent. Now server can reply with
1597
    OK-packet, or re-request scrambled password.
1598
  */
1599
1600
  if ((pkt_length=cli_safe_read(mysql)) == packet_error)
1601
  {
1602
    if (mysql->net.last_errno == CR_SERVER_LOST)
1603
      set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
1604
                               ER(CR_SERVER_LOST_EXTENDED),
1605
                               "reading authorization packet",
1606
                               errno);
1607
    goto error;
1608
  }
1609
1610
  if (client_flag & CLIENT_COMPRESS)		/* We will use compression */
1611
    net->compress=1;
1612
1613
1614
  if (db && mysql_select_db(mysql, db))
1615
  {
1616
    if (mysql->net.last_errno == CR_SERVER_LOST)
1617
        set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
1618
                                 ER(CR_SERVER_LOST_EXTENDED),
1619
                                 "Setting intital database",
1620
                                 errno);
1621
    goto error;
1622
  }
1623
1624
  if (mysql->options.init_commands)
1625
  {
1626
    DYNAMIC_ARRAY *init_commands= mysql->options.init_commands;
1627
    char **ptr= (char**)init_commands->buffer;
1628
    char **end_command= ptr + init_commands->elements;
1629
1630
    my_bool reconnect=mysql->reconnect;
1631
    mysql->reconnect=0;
1632
1633
    for (; ptr < end_command; ptr++)
1634
    {
1635
      MYSQL_RES *res;
1636
      if (mysql_real_query(mysql,*ptr, (ulong) strlen(*ptr)))
1637
	goto error;
1638
      if (mysql->fields)
1639
      {
1640
	if (!(res= cli_use_result(mysql)))
1641
	  goto error;
1642
	mysql_free_result(res);
1643
      }
1644
    }
1645
    mysql->reconnect=reconnect;
1646
  }
1647
1648
  reset_sigpipe(mysql);
51.3.5 by Jay Pipes
Merged in from trunk.
1649
  return(mysql);
1 by brian
clean slate
1650
1651
error:
1652
  reset_sigpipe(mysql);
1653
  {
1654
    /* Free alloced memory */
1655
    end_server(mysql);
1656
    mysql_close_free(mysql);
1657
    if (!(((ulong) client_flag) & CLIENT_REMEMBER_OPTIONS))
1658
      mysql_close_free_options(mysql);
1659
  }
51.3.5 by Jay Pipes
Merged in from trunk.
1660
  return(0);
1 by brian
clean slate
1661
}
1662
1663
1664
my_bool mysql_reconnect(MYSQL *mysql)
1665
{
1666
  MYSQL tmp_mysql;
51.3.5 by Jay Pipes
Merged in from trunk.
1667
  assert(mysql);
1 by brian
clean slate
1668
1669
  if (!mysql->reconnect ||
1670
      (mysql->server_status & SERVER_STATUS_IN_TRANS) || !mysql->host_info)
1671
  {
1672
    /* Allow reconnect next time */
1673
    mysql->server_status&= ~SERVER_STATUS_IN_TRANS;
1674
    set_mysql_error(mysql, CR_SERVER_GONE_ERROR, unknown_sqlstate);
51.3.5 by Jay Pipes
Merged in from trunk.
1675
    return(1);
1 by brian
clean slate
1676
  }
1677
  mysql_init(&tmp_mysql);
1678
  tmp_mysql.options= mysql->options;
1679
  tmp_mysql.options.my_cnf_file= tmp_mysql.options.my_cnf_group= 0;
1680
1681
  if (!mysql_real_connect(&tmp_mysql,mysql->host,mysql->user,mysql->passwd,
1682
			  mysql->db, mysql->port, mysql->unix_socket,
1683
			  mysql->client_flag | CLIENT_REMEMBER_OPTIONS))
1684
  {
1685
    mysql->net.last_errno= tmp_mysql.net.last_errno;
1686
    strmov(mysql->net.last_error, tmp_mysql.net.last_error);
1687
    strmov(mysql->net.sqlstate, tmp_mysql.net.sqlstate);
51.3.5 by Jay Pipes
Merged in from trunk.
1688
    return(1);
1 by brian
clean slate
1689
  }
1690
  if (mysql_set_character_set(&tmp_mysql, mysql->charset->csname))
1691
  {
1692
    bzero((char*) &tmp_mysql.options,sizeof(tmp_mysql.options));
1693
    mysql_close(&tmp_mysql);
1694
    mysql->net.last_errno= tmp_mysql.net.last_errno;
1695
    strmov(mysql->net.last_error, tmp_mysql.net.last_error);
1696
    strmov(mysql->net.sqlstate, tmp_mysql.net.sqlstate);
51.3.5 by Jay Pipes
Merged in from trunk.
1697
    return(1);
1 by brian
clean slate
1698
  }
1699
1700
  tmp_mysql.reconnect= 1;
1701
  tmp_mysql.free_me= mysql->free_me;
1702
1703
  /* Don't free options as these are now used in tmp_mysql */
1704
  bzero((char*) &mysql->options,sizeof(mysql->options));
1705
  mysql->free_me=0;
1706
  mysql_close(mysql);
1707
  *mysql=tmp_mysql;
1708
  net_clear(&mysql->net, 1);
155 by Brian Aker
Removing a few "additional" ways of saying uint64_t
1709
  mysql->affected_rows= ~(uint64_t) 0;
51.3.5 by Jay Pipes
Merged in from trunk.
1710
  return(0);
1 by brian
clean slate
1711
}
1712
1713
1714
/**************************************************************************
1715
  Set current database
1716
**************************************************************************/
1717
1718
int STDCALL
1719
mysql_select_db(MYSQL *mysql, const char *db)
1720
{
1721
  int error;
1722
1723
  if ((error=simple_command(mysql,COM_INIT_DB, (const uchar*) db,
1724
                            (ulong) strlen(db),0)))
51.3.5 by Jay Pipes
Merged in from trunk.
1725
    return(error);
1 by brian
clean slate
1726
  my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR));
1727
  mysql->db=my_strdup(db,MYF(MY_WME));
51.3.5 by Jay Pipes
Merged in from trunk.
1728
  return(0);
1 by brian
clean slate
1729
}
1730
1731
1732
/*************************************************************************
1733
  Send a QUIT to the server and close the connection
1734
  If handle is alloced by mysql connect free it.
1735
*************************************************************************/
1736
1737
static void mysql_close_free_options(MYSQL *mysql)
1738
{
1739
  my_free(mysql->options.user,MYF(MY_ALLOW_ZERO_PTR));
1740
  my_free(mysql->options.host,MYF(MY_ALLOW_ZERO_PTR));
1741
  my_free(mysql->options.password,MYF(MY_ALLOW_ZERO_PTR));
1742
  my_free(mysql->options.unix_socket,MYF(MY_ALLOW_ZERO_PTR));
1743
  my_free(mysql->options.db,MYF(MY_ALLOW_ZERO_PTR));
1744
  my_free(mysql->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR));
1745
  my_free(mysql->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR));
1746
  my_free(mysql->options.charset_dir,MYF(MY_ALLOW_ZERO_PTR));
1747
  my_free(mysql->options.charset_name,MYF(MY_ALLOW_ZERO_PTR));
1748
  my_free(mysql->options.client_ip,MYF(MY_ALLOW_ZERO_PTR));
1749
  if (mysql->options.init_commands)
1750
  {
1751
    DYNAMIC_ARRAY *init_commands= mysql->options.init_commands;
1752
    char **ptr= (char**)init_commands->buffer;
1753
    char **end= ptr + init_commands->elements;
1754
    for (; ptr<end; ptr++)
1755
      my_free(*ptr,MYF(MY_WME));
1756
    delete_dynamic(init_commands);
1757
    my_free((char*)init_commands,MYF(MY_WME));
1758
  }
1759
#ifdef HAVE_SMEM
1760
  if (mysql->options.shared_memory_base_name != def_shared_memory_base_name)
1761
    my_free(mysql->options.shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
1762
#endif /* HAVE_SMEM */
1763
  bzero((char*) &mysql->options,sizeof(mysql->options));
51.3.5 by Jay Pipes
Merged in from trunk.
1764
  return;
1 by brian
clean slate
1765
}
1766
1767
1768
static void mysql_close_free(MYSQL *mysql)
1769
{
1770
  my_free((uchar*) mysql->host_info,MYF(MY_ALLOW_ZERO_PTR));
1771
  my_free(mysql->user,MYF(MY_ALLOW_ZERO_PTR));
1772
  my_free(mysql->passwd,MYF(MY_ALLOW_ZERO_PTR));
1773
  my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR));
1774
  my_free(mysql->info_buffer,MYF(MY_ALLOW_ZERO_PTR));
1775
  mysql->info_buffer= 0;
48 by Brian Aker
Second pass on removing PS from client library
1776
1 by brian
clean slate
1777
  /* Clear pointers for better safety */
1778
  mysql->host_info= mysql->user= mysql->passwd= mysql->db= 0;
1779
}
1780
1781
1782
void STDCALL mysql_close(MYSQL *mysql)
1783
{
1784
  if (mysql)					/* Some simple safety */
1785
  {
1786
    /* If connection is still up, send a QUIT message */
1787
    if (mysql->net.vio != 0)
1788
    {
1789
      free_old_query(mysql);
1790
      mysql->status=MYSQL_STATUS_READY; /* Force command */
1791
      mysql->reconnect=0;
1792
      simple_command(mysql,COM_QUIT,(uchar*) 0,0,1);
1793
      end_server(mysql);			/* Sets mysql->net.vio= 0 */
1794
    }
1795
    mysql_close_free_options(mysql);
1796
    mysql_close_free(mysql);
1797
    if (mysql->free_me)
1798
      my_free((uchar*) mysql,MYF(0));
1799
  }
51.3.5 by Jay Pipes
Merged in from trunk.
1800
  return;
1 by brian
clean slate
1801
}
1802
1803
164 by Brian Aker
Commit cleanup of export types.
1804
static bool cli_read_query_result(MYSQL *mysql)
1 by brian
clean slate
1805
{
1806
  uchar *pos;
1807
  ulong field_count;
1808
  MYSQL_DATA *fields;
1809
  ulong length;
1810
1811
  if ((length = cli_safe_read(mysql)) == packet_error)
51.3.5 by Jay Pipes
Merged in from trunk.
1812
    return(1);
1 by brian
clean slate
1813
  free_old_query(mysql);		/* Free old result */
1814
#ifdef MYSQL_CLIENT			/* Avoid warn of unused labels*/
1815
get_info:
1816
#endif
1817
  pos=(uchar*) mysql->net.read_pos;
1818
  if ((field_count= net_field_length(&pos)) == 0)
1819
  {
1820
    mysql->affected_rows= net_field_length_ll(&pos);
1821
    mysql->insert_id=	  net_field_length_ll(&pos);
1822
    if (protocol_41(mysql))
1823
    {
1824
      mysql->server_status=uint2korr(pos); pos+=2;
1825
      mysql->warning_count=uint2korr(pos); pos+=2;
1826
    }
1827
    else if (mysql->server_capabilities & CLIENT_TRANSACTIONS)
1828
    {
1829
      /* MySQL 4.0 protocol */
1830
      mysql->server_status=uint2korr(pos); pos+=2;
1831
      mysql->warning_count= 0;
1832
    }
1833
    if (pos < mysql->net.read_pos+length && net_field_length(&pos))
1834
      mysql->info=(char*) pos;
51.3.5 by Jay Pipes
Merged in from trunk.
1835
    return(0);
1 by brian
clean slate
1836
  }
1837
#ifdef MYSQL_CLIENT
1838
  if (field_count == NULL_LENGTH)		/* LOAD DATA LOCAL INFILE */
1839
  {
1840
    int error;
1841
1842
    if (!(mysql->options.client_flag & CLIENT_LOCAL_FILES))
1843
    {
1844
      set_mysql_error(mysql, CR_MALFORMED_PACKET, unknown_sqlstate);
51.3.5 by Jay Pipes
Merged in from trunk.
1845
      return(1);
1 by brian
clean slate
1846
    }   
1847
1848
    error= handle_local_infile(mysql,(char*) pos);
1849
    if ((length= cli_safe_read(mysql)) == packet_error || error)
51.3.5 by Jay Pipes
Merged in from trunk.
1850
      return(1);
1 by brian
clean slate
1851
    goto get_info;				/* Get info packet */
1852
  }
1853
#endif
1854
  if (!(mysql->server_status & SERVER_STATUS_AUTOCOMMIT))
1855
    mysql->server_status|= SERVER_STATUS_IN_TRANS;
1856
1857
  if (!(fields=cli_read_rows(mysql,(MYSQL_FIELD*)0, protocol_41(mysql) ? 7:5)))
51.3.5 by Jay Pipes
Merged in from trunk.
1858
    return(1);
1 by brian
clean slate
1859
  if (!(mysql->fields=unpack_fields(fields,&mysql->field_alloc,
1860
				    (uint) field_count,0,
1861
				    mysql->server_capabilities)))
51.3.5 by Jay Pipes
Merged in from trunk.
1862
    return(1);
1 by brian
clean slate
1863
  mysql->status= MYSQL_STATUS_GET_RESULT;
1864
  mysql->field_count= (uint) field_count;
51.3.5 by Jay Pipes
Merged in from trunk.
1865
  return(0);
1 by brian
clean slate
1866
}
1867
1868
1869
/*
1870
  Send the query and return so we can do something else.
1871
  Needs to be followed by mysql_read_query_result() when we want to
1872
  finish processing it.
1873
*/
1874
164 by Brian Aker
Commit cleanup of export types.
1875
int32_t STDCALL
1876
mysql_send_query(MYSQL* mysql, const char* query, uint32_t length)
1 by brian
clean slate
1877
{
51.3.5 by Jay Pipes
Merged in from trunk.
1878
  return(simple_command(mysql, COM_QUERY, (uchar*) query, length, 1));
1 by brian
clean slate
1879
}
1880
1881
164 by Brian Aker
Commit cleanup of export types.
1882
int32_t STDCALL
1883
mysql_real_query(MYSQL *mysql, const char *query, uint32_t length)
1 by brian
clean slate
1884
{
1885
  if (mysql_send_query(mysql,query,length))
51.3.5 by Jay Pipes
Merged in from trunk.
1886
    return(1);
1887
  return((int) (*mysql->methods->read_query_result)(mysql));
1 by brian
clean slate
1888
}
1889
1890
1891
/**************************************************************************
1892
  Alloc result struct for buffered results. All rows are read to buffer.
1893
  mysql_data_seek may be used.
1894
**************************************************************************/
1895
1896
MYSQL_RES * STDCALL mysql_store_result(MYSQL *mysql)
1897
{
1898
  MYSQL_RES *result;
1899
1900
  if (!mysql->fields)
51.3.5 by Jay Pipes
Merged in from trunk.
1901
    return(0);
1 by brian
clean slate
1902
  if (mysql->status != MYSQL_STATUS_GET_RESULT)
1903
  {
1904
    set_mysql_error(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
51.3.5 by Jay Pipes
Merged in from trunk.
1905
    return(0);
1 by brian
clean slate
1906
  }
1907
  mysql->status=MYSQL_STATUS_READY;		/* server is ready */
1908
  if (!(result=(MYSQL_RES*) my_malloc((uint) (sizeof(MYSQL_RES)+
1909
					      sizeof(ulong) *
1910
					      mysql->field_count),
1911
				      MYF(MY_WME | MY_ZEROFILL))))
1912
  {
1913
    set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate);
51.3.5 by Jay Pipes
Merged in from trunk.
1914
    return(0);
1 by brian
clean slate
1915
  }
1916
  result->methods= mysql->methods;
164 by Brian Aker
Commit cleanup of export types.
1917
  result->eof= 1;				/* Marker for buffered */
1918
  result->lengths= (uint32_t*) (result+1);
1 by brian
clean slate
1919
  if (!(result->data=
1920
	(*mysql->methods->read_rows)(mysql,mysql->fields,mysql->field_count)))
1921
  {
1922
    my_free((uchar*) result,MYF(0));
51.3.5 by Jay Pipes
Merged in from trunk.
1923
    return(0);
1 by brian
clean slate
1924
  }
1925
  mysql->affected_rows= result->row_count= result->data->rows;
1926
  result->data_cursor=	result->data->data;
1927
  result->fields=	mysql->fields;
1928
  result->field_alloc=	mysql->field_alloc;
1929
  result->field_count=	mysql->field_count;
1930
  /* The rest of result members is bzeroed in malloc */
1931
  mysql->fields=0;				/* fields is now in result */
1932
  clear_alloc_root(&mysql->field_alloc);
1933
  /* just in case this was mistakenly called after mysql_stmt_execute() */
1934
  mysql->unbuffered_fetch_owner= 0;
51.3.5 by Jay Pipes
Merged in from trunk.
1935
  return(result);				/* Data fetched */
1 by brian
clean slate
1936
}
1937
1938
1939
/**************************************************************************
1940
  Alloc struct for use with unbuffered reads. Data is fetched by domand
1941
  when calling to mysql_fetch_row.
1942
  mysql_data_seek is a noop.
1943
1944
  No other queries may be specified with the same MYSQL handle.
1945
  There shouldn't be much processing per row because mysql server shouldn't
1946
  have to wait for the client (and will not wait more than 30 sec/packet).
1947
**************************************************************************/
1948
1949
static MYSQL_RES * cli_use_result(MYSQL *mysql)
1950
{
1951
  MYSQL_RES *result;
1952
1953
  if (!mysql->fields)
51.3.5 by Jay Pipes
Merged in from trunk.
1954
    return(0);
1 by brian
clean slate
1955
  if (mysql->status != MYSQL_STATUS_GET_RESULT)
1956
  {
1957
    set_mysql_error(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
51.3.5 by Jay Pipes
Merged in from trunk.
1958
    return(0);
1 by brian
clean slate
1959
  }
1960
  if (!(result=(MYSQL_RES*) my_malloc(sizeof(*result)+
1961
				      sizeof(ulong)*mysql->field_count,
1962
				      MYF(MY_WME | MY_ZEROFILL))))
51.3.5 by Jay Pipes
Merged in from trunk.
1963
    return(0);
164 by Brian Aker
Commit cleanup of export types.
1964
  result->lengths=(uint32_t*) (result+1);
1 by brian
clean slate
1965
  result->methods= mysql->methods;
1966
  if (!(result->row=(MYSQL_ROW)
1967
	my_malloc(sizeof(result->row[0])*(mysql->field_count+1), MYF(MY_WME))))
1968
  {					/* Ptrs: to one row */
1969
    my_free((uchar*) result,MYF(0));
51.3.5 by Jay Pipes
Merged in from trunk.
1970
    return(0);
1 by brian
clean slate
1971
  }
1972
  result->fields=	mysql->fields;
1973
  result->field_alloc=	mysql->field_alloc;
1974
  result->field_count=	mysql->field_count;
1975
  result->current_field=0;
1976
  result->handle=	mysql;
1977
  result->current_row=	0;
1978
  mysql->fields=0;			/* fields is now in result */
1979
  clear_alloc_root(&mysql->field_alloc);
1980
  mysql->status=MYSQL_STATUS_USE_RESULT;
1981
  mysql->unbuffered_fetch_owner= &result->unbuffered_fetch_cancelled;
51.3.5 by Jay Pipes
Merged in from trunk.
1982
  return(result);			/* Data is read to be fetched */
1 by brian
clean slate
1983
}
1984
1985
1986
/**************************************************************************
1987
  Return next row of the query results
1988
**************************************************************************/
1989
1990
MYSQL_ROW STDCALL
1991
mysql_fetch_row(MYSQL_RES *res)
1992
{
1993
  if (!res->data)
1994
  {						/* Unbufferred fetch */
1995
    if (!res->eof)
1996
    {
1997
      MYSQL *mysql= res->handle;
1998
      if (mysql->status != MYSQL_STATUS_USE_RESULT)
1999
      {
2000
        set_mysql_error(mysql,
2001
                        res->unbuffered_fetch_cancelled ? 
2002
                        CR_FETCH_CANCELED : CR_COMMANDS_OUT_OF_SYNC,
2003
                        unknown_sqlstate);
2004
      }
2005
      else if (!(read_one_row(mysql, res->field_count, res->row, res->lengths)))
2006
      {
2007
	res->row_count++;
51.3.5 by Jay Pipes
Merged in from trunk.
2008
	return(res->current_row=res->row);
1 by brian
clean slate
2009
      }
2010
      res->eof=1;
2011
      mysql->status=MYSQL_STATUS_READY;
2012
      /*
2013
        Reset only if owner points to us: there is a chance that somebody
2014
        started new query after mysql_stmt_close():
2015
      */
2016
      if (mysql->unbuffered_fetch_owner == &res->unbuffered_fetch_cancelled)
2017
        mysql->unbuffered_fetch_owner= 0;
2018
      /* Don't clear handle in mysql_free_result */
2019
      res->handle=0;
2020
    }
51.3.5 by Jay Pipes
Merged in from trunk.
2021
    return((MYSQL_ROW) NULL);
1 by brian
clean slate
2022
  }
2023
  {
2024
    MYSQL_ROW tmp;
2025
    if (!res->data_cursor)
2026
    {
51.3.5 by Jay Pipes
Merged in from trunk.
2027
      return(res->current_row=(MYSQL_ROW) NULL);
1 by brian
clean slate
2028
    }
2029
    tmp = res->data_cursor->data;
2030
    res->data_cursor = res->data_cursor->next;
51.3.5 by Jay Pipes
Merged in from trunk.
2031
    return(res->current_row=tmp);
1 by brian
clean slate
2032
  }
2033
}
2034
2035
2036
/**************************************************************************
2037
  Get column lengths of the current row
2038
  If one uses mysql_use_result, res->lengths contains the length information,
2039
  else the lengths are calculated from the offset between pointers.
2040
**************************************************************************/
2041
164 by Brian Aker
Commit cleanup of export types.
2042
uint32_t * STDCALL
1 by brian
clean slate
2043
mysql_fetch_lengths(MYSQL_RES *res)
2044
{
2045
  MYSQL_ROW column;
2046
2047
  if (!(column=res->current_row))
2048
    return 0;					/* Something is wrong */
2049
  if (res->data)
2050
    (*res->methods->fetch_lengths)(res->lengths, column, res->field_count);
2051
  return res->lengths;
2052
}
2053
2054
2055
int STDCALL
2056
mysql_options(MYSQL *mysql,enum mysql_option option, const void *arg)
2057
{
2058
  switch (option) {
2059
  case MYSQL_OPT_CONNECT_TIMEOUT:
2060
    mysql->options.connect_timeout= *(uint*) arg;
2061
    break;
2062
  case MYSQL_OPT_READ_TIMEOUT:
2063
    mysql->options.read_timeout= *(uint*) arg;
2064
    break;
2065
  case MYSQL_OPT_WRITE_TIMEOUT:
2066
    mysql->options.write_timeout= *(uint*) arg;
2067
    break;
2068
  case MYSQL_OPT_COMPRESS:
2069
    mysql->options.compress= 1;			/* Remember for connect */
2070
    mysql->options.client_flag|= CLIENT_COMPRESS;
2071
    break;
2072
  case MYSQL_OPT_NAMED_PIPE:			/* This option is depricated */
2073
    mysql->options.protocol=MYSQL_PROTOCOL_PIPE; /* Force named pipe */
2074
    break;
2075
  case MYSQL_OPT_LOCAL_INFILE:			/* Allow LOAD DATA LOCAL ?*/
2076
    if (!arg || test(*(uint*) arg))
2077
      mysql->options.client_flag|= CLIENT_LOCAL_FILES;
2078
    else
2079
      mysql->options.client_flag&= ~CLIENT_LOCAL_FILES;
2080
    break;
2081
  case MYSQL_INIT_COMMAND:
2082
    add_init_command(&mysql->options,arg);
2083
    break;
2084
  case MYSQL_READ_DEFAULT_FILE:
2085
    my_free(mysql->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR));
2086
    mysql->options.my_cnf_file=my_strdup(arg,MYF(MY_WME));
2087
    break;
2088
  case MYSQL_READ_DEFAULT_GROUP:
2089
    my_free(mysql->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR));
2090
    mysql->options.my_cnf_group=my_strdup(arg,MYF(MY_WME));
2091
    break;
2092
  case MYSQL_SET_CHARSET_DIR:
2093
    my_free(mysql->options.charset_dir,MYF(MY_ALLOW_ZERO_PTR));
2094
    mysql->options.charset_dir=my_strdup(arg,MYF(MY_WME));
2095
    break;
2096
  case MYSQL_SET_CHARSET_NAME:
2097
    my_free(mysql->options.charset_name,MYF(MY_ALLOW_ZERO_PTR));
2098
    mysql->options.charset_name=my_strdup(arg,MYF(MY_WME));
2099
    break;
2100
  case MYSQL_OPT_PROTOCOL:
2101
    mysql->options.protocol= *(uint*) arg;
2102
    break;
2103
  case MYSQL_SHARED_MEMORY_BASE_NAME:
2104
#ifdef HAVE_SMEM
2105
    if (mysql->options.shared_memory_base_name != def_shared_memory_base_name)
2106
      my_free(mysql->options.shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
2107
    mysql->options.shared_memory_base_name=my_strdup(arg,MYF(MY_WME));
2108
#endif
2109
    break;
2110
  case MYSQL_OPT_USE_REMOTE_CONNECTION:
2111
  case MYSQL_OPT_USE_EMBEDDED_CONNECTION:
2112
  case MYSQL_OPT_GUESS_CONNECTION:
2113
    mysql->options.methods_to_use= option;
2114
    break;
2115
  case MYSQL_SET_CLIENT_IP:
2116
    mysql->options.client_ip= my_strdup(arg, MYF(MY_WME));
2117
    break;
2118
  case MYSQL_SECURE_AUTH:
2119
    mysql->options.secure_auth= *(my_bool *) arg;
2120
    break;
2121
  case MYSQL_REPORT_DATA_TRUNCATION:
2122
    mysql->options.report_data_truncation= test(*(my_bool *) arg);
2123
    break;
2124
  case MYSQL_OPT_RECONNECT:
2125
    mysql->reconnect= *(my_bool *) arg;
2126
    break;
2127
  case MYSQL_OPT_SSL_VERIFY_SERVER_CERT:
2128
    if (*(my_bool*) arg)
2129
      mysql->options.client_flag|= CLIENT_SSL_VERIFY_SERVER_CERT;
2130
    else
2131
      mysql->options.client_flag&= ~CLIENT_SSL_VERIFY_SERVER_CERT;
2132
    break;
2133
  default:
51.3.5 by Jay Pipes
Merged in from trunk.
2134
    return(1);
1 by brian
clean slate
2135
  }
51.3.5 by Jay Pipes
Merged in from trunk.
2136
  return(0);
1 by brian
clean slate
2137
}
2138
2139
2140
/****************************************************************************
2141
  Functions to get information from the MySQL structure
2142
  These are functions to make shared libraries more usable.
2143
****************************************************************************/
2144
2145
/* MYSQL_RES */
155 by Brian Aker
Removing a few "additional" ways of saying uint64_t
2146
uint64_t STDCALL mysql_num_rows(MYSQL_RES *res)
1 by brian
clean slate
2147
{
2148
  return res->row_count;
2149
}
2150
2151
unsigned int STDCALL mysql_num_fields(MYSQL_RES *res)
2152
{
2153
  return res->field_count;
2154
}
2155
2156
uint STDCALL mysql_errno(MYSQL *mysql)
2157
{
2158
  return mysql ? mysql->net.last_errno : mysql_server_last_errno;
2159
}
2160
2161
2162
const char * STDCALL mysql_error(MYSQL *mysql)
2163
{
2164
  return mysql ? mysql->net.last_error : mysql_server_last_error;
2165
}
2166
2167
2168
/*
2169
  Get version number for server in a form easy to test on
2170
2171
  SYNOPSIS
2172
    mysql_get_server_version()
2173
    mysql		Connection
2174
2175
  EXAMPLE
2176
    4.1.0-alfa ->  40100
2177
  
2178
  NOTES
2179
    We will ensure that a newer server always has a bigger number.
2180
2181
  RETURN
2182
   Signed number > 323000
2183
*/
2184
164 by Brian Aker
Commit cleanup of export types.
2185
uint32_t STDCALL
1 by brian
clean slate
2186
mysql_get_server_version(MYSQL *mysql)
2187
{
2188
  uint major, minor, version;
2189
  char *pos= mysql->server_version, *end_pos;
2190
  major=   (uint) strtoul(pos, &end_pos, 10);	pos=end_pos+1;
2191
  minor=   (uint) strtoul(pos, &end_pos, 10);	pos=end_pos+1;
2192
  version= (uint) strtoul(pos, &end_pos, 10);
2193
  return (ulong) major*10000L+(ulong) (minor*100+version);
2194
}
2195
2196
2197
/* 
2198
   mysql_set_character_set function sends SET NAMES cs_name to
2199
   the server (which changes character_set_client, character_set_result
2200
   and character_set_connection) and updates mysql->charset so other
2201
   functions like mysql_real_escape will work correctly.
2202
*/
2203
int STDCALL mysql_set_character_set(MYSQL *mysql, const char *cs_name)
2204
{
2205
  struct charset_info_st *cs;
2206
  const char *save_csdir= charsets_dir;
2207
2208
  if (mysql->options.charset_dir)
2209
    charsets_dir= mysql->options.charset_dir;
2210
2211
  if (strlen(cs_name) < MY_CS_NAME_SIZE &&
2212
     (cs= get_charset_by_csname(cs_name, MY_CS_PRIMARY, MYF(0))))
2213
  {
2214
    char buff[MY_CS_NAME_SIZE + 10];
2215
    charsets_dir= save_csdir;
2216
    /* Skip execution of "SET NAMES" for pre-4.1 servers */
2217
    if (mysql_get_server_version(mysql) < 40100)
2218
      return 0;
2219
    sprintf(buff, "SET NAMES %s", cs_name);
2220
    if (!mysql_real_query(mysql, buff, strlen(buff)))
2221
    {
2222
      mysql->charset= cs;
2223
    }
2224
  }
2225
  else
2226
  {
2227
    char cs_dir_name[FN_REFLEN];
2228
    get_charsets_dir(cs_dir_name);
2229
    set_mysql_extended_error(mysql, CR_CANT_READ_CHARSET, unknown_sqlstate,
2230
                             ER(CR_CANT_READ_CHARSET), cs_name, cs_dir_name);
2231
  }
2232
  charsets_dir= save_csdir;
2233
  return mysql->net.last_errno;
2234
}
2235
2236