~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to libmysql/client.c

  • Committer: Monty Taylor
  • Date: 2008-07-02 14:35:48 UTC
  • mto: This revision was merged to the branch mainline in revision 51.
  • Revision ID: monty@inaugust.com-20080702143548-onj30ry0sugr01uw
Removed all references to THREAD.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 
 *
4
 
 *  Copyright (C) 2008 Sun Microsystems, Inc.
5
 
 *
6
 
 *  This program is free software; you can redistribute it and/or modify
7
 
 *  it under the terms of the GNU General Public License as published by
8
 
 *  the Free Software Foundation; version 2 of the License.
9
 
 *
10
 
 *  This program is distributed in the hope that it will be useful,
11
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
 *  GNU General Public License for more details.
14
 
 *
15
 
 *  You should have received a copy of the GNU General Public License
16
 
 *  along with this program; if not, write to the Free Software
17
 
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
 
 */
 
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 */
19
15
 
20
16
/*
21
 
  This file is included by both libdrizzle.c (the DRIZZLE client C API)
22
 
  and the drizzled server to connect to another DRIZZLE server.
 
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.
23
19
 
24
20
  The differences for the two cases are:
25
21
 
26
22
  - Things that only works for the client:
27
23
  - Trying to automaticly determinate user name if not supplied to
28
 
    drizzle_connect()
 
24
    mysql_real_connect()
29
25
  - Support for reading local file with LOAD DATA LOCAL
30
26
  - SHARED memory handling
 
27
  - Protection against sigpipe
31
28
  - Prepared statements
32
 
 
 
29
  
33
30
  - Things that only works for the server
34
31
  - Alarm handling on connect
35
 
 
 
32
  
36
33
  In all other cases, the code should be idential for the client and
37
34
  server.
38
 
*/
39
 
 
40
 
#include <stdarg.h>
41
 
 
42
 
#include <libdrizzle/libdrizzle.h>
43
 
#include <libdrizzle/net_serv.h>
44
 
#include "libdrizzle_priv.h"
45
 
 
46
 
#include <sys/poll.h>
47
 
#include <sys/ioctl.h>
 
35
*/ 
 
36
 
 
37
#include <my_global.h>
 
38
 
 
39
#include "mysql.h"
48
40
 
49
41
#include <netdb.h>
50
42
 
52
44
#undef max_allowed_packet
53
45
#undef net_buffer_length
54
46
 
55
 
#include <libdrizzle/errmsg.h>
56
 
#include <vio/violite.h>
 
47
#ifdef EMBEDDED_LIBRARY
 
48
 
 
49
#undef MYSQL_SERVER
 
50
 
 
51
#ifndef MYSQL_CLIENT
 
52
#define MYSQL_CLIENT
 
53
#endif
 
54
 
 
55
#define CLI_MYSQL_REAL_CONNECT STDCALL cli_mysql_real_connect
 
56
 
 
57
#undef net_flush
 
58
my_bool net_flush(NET *net);
 
59
 
 
60
#else  /*EMBEDDED_LIBRARY*/
 
61
#define CLI_MYSQL_REAL_CONNECT STDCALL mysql_real_connect
 
62
#endif /*EMBEDDED_LIBRARY*/
 
63
#include <my_sys.h>
 
64
#include <mysys_err.h>
 
65
#include <m_string.h>
 
66
#include <m_ctype.h>
 
67
#include "mysql_version.h"
 
68
#include "mysqld_error.h"
 
69
#include "errmsg.h"
 
70
#include <violite.h>
 
71
#include <my_pthread.h>                         /* because of signal()  */
57
72
 
58
73
#include <sys/stat.h>
59
74
#include <signal.h>
60
75
#include <time.h>
61
 
#ifdef   HAVE_PWD_H
 
76
#ifdef   HAVE_PWD_H
62
77
#include <pwd.h>
63
78
#endif
64
 
 
 
79
#if !defined(MSDOS) && !defined(__WIN__)
65
80
#include <sys/socket.h>
66
81
#include <netinet/in.h>
67
82
#include <arpa/inet.h>
72
87
#ifdef HAVE_SYS_SELECT_H
73
88
#include <sys/select.h>
74
89
#endif
75
 
 
76
 
#include <sys/un.h>
77
 
 
 
90
#endif /*!defined(MSDOS) && !defined(__WIN__) */
 
91
#ifdef HAVE_SYS_UN_H
 
92
#  include <sys/un.h>
 
93
#endif
 
94
 
 
95
#if defined(MSDOS) || defined(__WIN__)
 
96
#define perror(A)
 
97
#else
78
98
#include <errno.h>
79
99
#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
 
 
93
 
 
94
 
#if defined(HAVE_GETPWUID) && defined(NO_GETPWUID_DECL)
95
 
struct passwd *getpwuid(uid_t);
96
 
char* getlogin(void);
97
 
#endif
98
 
 
99
 
 
 
100
#endif
 
101
 
 
102
#ifdef __WIN__
 
103
#define CONNECT_TIMEOUT 20
 
104
#else
 
105
#define CONNECT_TIMEOUT 0
 
106
#endif
 
107
 
 
108
#include "client_settings.h"
 
109
#include <sql_common.h>
 
110
 
 
111
uint            mysql_port=0;
 
112
char            *mysql_unix_port= 0;
 
113
const char      *unknown_sqlstate= "HY000";
 
114
const char      *not_error_sqlstate= "00000";
 
115
const char      *cant_connect_sqlstate= "08001";
 
116
#ifdef HAVE_SMEM
 
117
char             *shared_memory_base_name= 0;
 
118
const char      *def_shared_memory_base_name= default_shared_memory_base_name;
 
119
#endif
 
120
 
 
121
static void mysql_close_free_options(MYSQL *mysql);
 
122
static void mysql_close_free(MYSQL *mysql);
 
123
 
 
124
#if !(defined(__WIN__) || defined(__NETWARE__))
 
125
static int wait_for_data(my_socket fd, uint timeout);
 
126
#endif
 
127
 
 
128
CHARSET_INFO *default_client_charset_info = &my_charset_latin1;
 
129
 
 
130
/* Server error code and message */
 
131
unsigned int mysql_server_last_errno;
 
132
char mysql_server_last_error[MYSQL_ERRMSG_SIZE];
 
133
 
 
134
/****************************************************************************
 
135
  A modified version of connect().  my_connect() allows you to specify
 
136
  a timeout value, in seconds, that we should wait until we
 
137
  derermine we can't connect to a particular host.  If timeout is 0,
 
138
  my_connect() will behave exactly like connect().
 
139
 
 
140
  Base version coded by Steve Bernacki, Jr. <steve@navinet.net>
 
141
*****************************************************************************/
 
142
 
 
143
int my_connect(my_socket fd, const struct sockaddr *name, uint namelen,
 
144
               uint timeout)
 
145
{
 
146
#if defined(__WIN__) || defined(__NETWARE__)
 
147
  return connect(fd, (struct sockaddr*) name, namelen);
 
148
#else
 
149
  int flags, res, s_err;
 
150
 
 
151
  /*
 
152
    If they passed us a timeout of zero, we should behave
 
153
    exactly like the normal connect() call does.
 
154
  */
 
155
 
 
156
  if (timeout == 0)
 
157
    return connect(fd, (struct sockaddr*) name, namelen);
 
158
 
 
159
  flags = fcntl(fd, F_GETFL, 0);          /* Set socket to not block */
 
160
#ifdef O_NONBLOCK
 
161
  fcntl(fd, F_SETFL, flags | O_NONBLOCK);  /* and save the flags..  */
 
162
#endif
 
163
 
 
164
  res= connect(fd, (struct sockaddr*) name, namelen);
 
165
  s_err= errno;                 /* Save the error... */
 
166
  fcntl(fd, F_SETFL, flags);
 
167
  if ((res != 0) && (s_err != EINPROGRESS))
 
168
  {
 
169
    errno= s_err;                       /* Restore it */
 
170
    return(-1);
 
171
  }
 
172
  if (res == 0)                         /* Connected quickly! */
 
173
    return(0);
 
174
  return wait_for_data(fd, timeout);
 
175
#endif
 
176
}
 
177
 
 
178
 
 
179
/*
 
180
  Wait up to timeout seconds for a connection to be established.
 
181
 
 
182
  We prefer to do this with poll() as there is no limitations with this.
 
183
  If not, we will use select()
 
184
*/
 
185
 
 
186
#if !(defined(__WIN__) || defined(__NETWARE__))
 
187
 
 
188
static int wait_for_data(my_socket fd, uint timeout)
 
189
{
 
190
#ifdef HAVE_POLL
 
191
  struct pollfd ufds;
 
192
  int res;
 
193
 
 
194
  ufds.fd= fd;
 
195
  ufds.events= POLLIN | POLLPRI;
 
196
  if (!(res= poll(&ufds, 1, (int) timeout*1000)))
 
197
  {
 
198
    errno= EINTR;
 
199
    return -1;
 
200
  }
 
201
  if (res < 0 || !(ufds.revents & (POLLIN | POLLPRI)))
 
202
    return -1;
 
203
  return 0;
 
204
#else
 
205
  SOCKOPT_OPTLEN_TYPE s_err_size = sizeof(uint);
 
206
  fd_set sfds;
 
207
  struct timeval tv;
 
208
  time_t start_time, now_time;
 
209
  int res, s_err;
 
210
 
 
211
  if (fd >= FD_SETSIZE)                         /* Check if wrong error */
 
212
    return 0;                                   /* Can't use timeout */
 
213
 
 
214
  /*
 
215
    Our connection is "in progress."  We can use the select() call to wait
 
216
    up to a specified period of time for the connection to suceed.
 
217
    If select() returns 0 (after waiting howevermany seconds), our socket
 
218
    never became writable (host is probably unreachable.)  Otherwise, if
 
219
    select() returns 1, then one of two conditions exist:
 
220
   
 
221
    1. An error occured.  We use getsockopt() to check for this.
 
222
    2. The connection was set up sucessfully: getsockopt() will
 
223
    return 0 as an error.
 
224
   
 
225
    Thanks goes to Andrew Gierth <andrew@erlenstar.demon.co.uk>
 
226
    who posted this method of timing out a connect() in
 
227
    comp.unix.programmer on August 15th, 1997.
 
228
  */
 
229
 
 
230
  FD_ZERO(&sfds);
 
231
  FD_SET(fd, &sfds);
 
232
  /*
 
233
    select could be interrupted by a signal, and if it is, 
 
234
    the timeout should be adjusted and the select restarted
 
235
    to work around OSes that don't restart select and 
 
236
    implementations of select that don't adjust tv upon
 
237
    failure to reflect the time remaining
 
238
   */
 
239
  start_time= my_time(0);
 
240
  for (;;)
 
241
  {
 
242
    tv.tv_sec = (long) timeout;
 
243
    tv.tv_usec = 0;
 
244
#if defined(HPUX10)
 
245
    if ((res = select(fd+1, NULL, (int*) &sfds, NULL, &tv)) > 0)
 
246
      break;
 
247
#else
 
248
    if ((res = select(fd+1, NULL, &sfds, NULL, &tv)) > 0)
 
249
      break;
 
250
#endif
 
251
    if (res == 0)                                       /* timeout */
 
252
      return -1;
 
253
    now_time= my_time(0);
 
254
    timeout-= (uint) (now_time - start_time);
 
255
    if (errno != EINTR || (int) timeout <= 0)
 
256
      return -1;
 
257
  }
 
258
 
 
259
  /*
 
260
    select() returned something more interesting than zero, let's
 
261
    see if we have any errors.  If the next two statements pass,
 
262
    we've got an open socket!
 
263
  */
 
264
 
 
265
  s_err=0;
 
266
  if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (char*) &s_err, &s_err_size) != 0)
 
267
    return(-1);
 
268
 
 
269
  if (s_err)
 
270
  {                                             /* getsockopt could succeed */
 
271
    errno = s_err;
 
272
    return(-1);                                 /* but return an error... */
 
273
  }
 
274
  return (0);                                   /* ok */
 
275
#endif /* HAVE_POLL */
 
276
}
 
277
#endif /* defined(__WIN__) || defined(__NETWARE__) */
 
278
 
 
279
/**
 
280
  Set the internal error message to mysql handler
 
281
 
 
282
  @param mysql    connection handle (client side)
 
283
  @param errcode  CR_ error code, passed to ER macro to get
 
284
                  error text
 
285
  @parma sqlstate SQL standard sqlstate
 
286
*/
 
287
 
 
288
void set_mysql_error(MYSQL *mysql, int errcode, const char *sqlstate)
 
289
{
 
290
  NET *net;
 
291
  DBUG_ENTER("set_mysql_error");
 
292
  DBUG_PRINT("enter", ("error :%d '%s'", errcode, ER(errcode)));
 
293
  DBUG_ASSERT(mysql != 0);
 
294
 
 
295
  if (mysql)
 
296
  {
 
297
    net= &mysql->net;
 
298
    net->last_errno= errcode;
 
299
    strmov(net->last_error, ER(errcode));
 
300
    strmov(net->sqlstate, sqlstate);
 
301
  }
 
302
  else
 
303
  {
 
304
    mysql_server_last_errno= errcode;
 
305
    strmov(mysql_server_last_error, ER(errcode));
 
306
  }
 
307
  DBUG_VOID_RETURN;
 
308
}
 
309
 
 
310
/**
 
311
  Clear possible error state of struct NET
 
312
 
 
313
  @param net  clear the state of the argument
 
314
*/
 
315
 
 
316
void net_clear_error(NET *net)
 
317
{
 
318
  net->last_errno= 0;
 
319
  net->last_error[0]= '\0';
 
320
  strmov(net->sqlstate, not_error_sqlstate);
 
321
}
 
322
 
 
323
/**
 
324
  Set an error message on the client.
 
325
 
 
326
  @param mysql     connection handle
 
327
  @param errcode   CR_* errcode, for client errors
 
328
  @param sqlstate  SQL standard sql state, unknown_sqlstate for the
 
329
                   majority of client errors.
 
330
  @param format    error message template, in sprintf format
 
331
  @param ...       variable number of arguments
 
332
*/
 
333
 
 
334
static void set_mysql_extended_error(MYSQL *mysql, int errcode,
 
335
                                     const char *sqlstate,
 
336
                                     const char *format, ...)
 
337
{
 
338
  NET *net;
 
339
  va_list args;
 
340
  DBUG_ENTER("set_mysql_extended_error");
 
341
  DBUG_PRINT("enter", ("error :%d '%s'", errcode, format));
 
342
  DBUG_ASSERT(mysql != 0);
 
343
 
 
344
  net= &mysql->net;
 
345
  net->last_errno= errcode;
 
346
  va_start(args, format);
 
347
  my_vsnprintf(net->last_error, sizeof(net->last_error)-1,
 
348
               format, args);
 
349
  va_end(args);
 
350
  strmov(net->sqlstate, sqlstate);
 
351
 
 
352
  DBUG_VOID_RETURN;
 
353
}
 
354
 
 
355
 
 
356
 
 
357
/*
 
358
  Create a named pipe connection
 
359
*/
 
360
 
 
361
#ifdef __WIN__
 
362
 
 
363
HANDLE create_named_pipe(MYSQL *mysql, uint connect_timeout, char **arg_host,
 
364
                         char **arg_unix_socket)
 
365
{
 
366
  HANDLE hPipe=INVALID_HANDLE_VALUE;
 
367
  char pipe_name[1024];
 
368
  DWORD dwMode;
 
369
  int i;
 
370
  my_bool testing_named_pipes=0;
 
371
  char *host= *arg_host, *unix_socket= *arg_unix_socket;
 
372
 
 
373
  if ( ! unix_socket || (unix_socket)[0] == 0x00)
 
374
    unix_socket = mysql_unix_port;
 
375
  if (!host || !strcmp(host,LOCAL_HOST))
 
376
    host=LOCAL_HOST_NAMEDPIPE;
 
377
 
 
378
  
 
379
  pipe_name[sizeof(pipe_name)-1]= 0;            /* Safety if too long string */
 
380
  strxnmov(pipe_name, sizeof(pipe_name)-1, "\\\\", host, "\\pipe\\",
 
381
           unix_socket, NullS);
 
382
  DBUG_PRINT("info",("Server name: '%s'.  Named Pipe: %s", host, unix_socket));
 
383
 
 
384
  for (i=0 ; i < 100 ; i++)                     /* Don't retry forever */
 
385
  {
 
386
    if ((hPipe = CreateFile(pipe_name,
 
387
                            GENERIC_READ | GENERIC_WRITE,
 
388
                            0,
 
389
                            NULL,
 
390
                            OPEN_EXISTING,
 
391
                            0,
 
392
                            NULL )) != INVALID_HANDLE_VALUE)
 
393
      break;
 
394
    if (GetLastError() != ERROR_PIPE_BUSY)
 
395
    {
 
396
      set_mysql_extended_error(mysql, CR_NAMEDPIPEOPEN_ERROR,
 
397
                               unknown_sqlstate, ER(CR_NAMEDPIPEOPEN_ERROR),
 
398
                               host, unix_socket, (ulong) GetLastError());
 
399
      return INVALID_HANDLE_VALUE;
 
400
    }
 
401
    /* wait for for an other instance */
 
402
    if (! WaitNamedPipe(pipe_name, connect_timeout*1000) )
 
403
    {
 
404
      set_mysql_extended_error(mysql, CR_NAMEDPIPEWAIT_ERROR, unknown_sqlstate,
 
405
                               ER(CR_NAMEDPIPEWAIT_ERROR),
 
406
                               host, unix_socket, (ulong) GetLastError());
 
407
      return INVALID_HANDLE_VALUE;
 
408
    }
 
409
  }
 
410
  if (hPipe == INVALID_HANDLE_VALUE)
 
411
  {
 
412
    set_mysql_extended_error(mysql, CR_NAMEDPIPEOPEN_ERROR, unknown_sqlstate,
 
413
                             ER(CR_NAMEDPIPEOPEN_ERROR), host, unix_socket,
 
414
                             (ulong) GetLastError());
 
415
    return INVALID_HANDLE_VALUE;
 
416
  }
 
417
  dwMode = PIPE_READMODE_BYTE | PIPE_WAIT;
 
418
  if ( !SetNamedPipeHandleState(hPipe, &dwMode, NULL, NULL) )
 
419
  {
 
420
    CloseHandle( hPipe );
 
421
    set_mysql_extended_error(mysql, CR_NAMEDPIPESETSTATE_ERROR,
 
422
                             unknown_sqlstate, ER(CR_NAMEDPIPESETSTATE_ERROR),
 
423
                             host, unix_socket, (ulong) GetLastError());
 
424
    return INVALID_HANDLE_VALUE;
 
425
  }
 
426
  *arg_host=host ; *arg_unix_socket=unix_socket;        /* connect arg */
 
427
  return (hPipe);
 
428
}
 
429
#endif
 
430
 
 
431
 
 
432
/*
 
433
  Create new shared memory connection, return handler of connection
 
434
 
 
435
  SYNOPSIS
 
436
    create_shared_memory()
 
437
    mysql               Pointer of mysql structure
 
438
    net                 Pointer of net structure
 
439
    connect_timeout     Timeout of connection
 
440
*/
 
441
 
 
442
#ifdef HAVE_SMEM
 
443
HANDLE create_shared_memory(MYSQL *mysql,NET *net, uint connect_timeout)
 
444
{
 
445
  ulong smem_buffer_length = shared_memory_buffer_length + 4;
 
446
  /*
 
447
    event_connect_request is event object for start connection actions
 
448
    event_connect_answer is event object for confirm, that server put data
 
449
    handle_connect_file_map is file-mapping object, use for create shared
 
450
    memory
 
451
    handle_connect_map is pointer on shared memory
 
452
    handle_map is pointer on shared memory for client
 
453
    event_server_wrote,
 
454
    event_server_read,
 
455
    event_client_wrote,
 
456
    event_client_read are events for transfer data between server and client
 
457
    handle_file_map is file-mapping object, use for create shared memory
 
458
  */
 
459
  HANDLE event_connect_request = NULL;
 
460
  HANDLE event_connect_answer = NULL;
 
461
  HANDLE handle_connect_file_map = NULL;
 
462
  char *handle_connect_map = NULL;
 
463
 
 
464
  char *handle_map = NULL;
 
465
  HANDLE event_server_wrote = NULL;
 
466
  HANDLE event_server_read = NULL;
 
467
  HANDLE event_client_wrote = NULL;
 
468
  HANDLE event_client_read = NULL;
 
469
  HANDLE event_conn_closed = NULL;
 
470
  HANDLE handle_file_map = NULL;
 
471
  ulong connect_number;
 
472
  char connect_number_char[22], *p;
 
473
  char *tmp= NULL;
 
474
  char *suffix_pos;
 
475
  DWORD error_allow = 0;
 
476
  DWORD error_code = 0;
 
477
  DWORD event_access_rights= SYNCHRONIZE | EVENT_MODIFY_STATE;
 
478
  char *shared_memory_base_name = mysql->options.shared_memory_base_name;
 
479
 
 
480
  /*
 
481
     get enough space base-name + '_' + longest suffix we might ever send
 
482
   */
 
483
  if (!(tmp= (char *)my_malloc(strlen(shared_memory_base_name) + 32L, MYF(MY_FAE))))
 
484
    goto err;
 
485
 
 
486
  /*
 
487
    The name of event and file-mapping events create agree next rule:
 
488
    shared_memory_base_name+unique_part
 
489
    Where:
 
490
    shared_memory_base_name is unique value for each server
 
491
    unique_part is uniquel value for each object (events and file-mapping)
 
492
  */
 
493
  suffix_pos = strxmov(tmp, "Global\\", shared_memory_base_name, "_", NullS);
 
494
  strmov(suffix_pos, "CONNECT_REQUEST");
 
495
  if (!(event_connect_request= OpenEvent(event_access_rights, FALSE, tmp)))
 
496
  {
 
497
    error_allow = CR_SHARED_MEMORY_CONNECT_REQUEST_ERROR;
 
498
    goto err;
 
499
  }
 
500
  strmov(suffix_pos, "CONNECT_ANSWER");
 
501
  if (!(event_connect_answer= OpenEvent(event_access_rights,FALSE,tmp)))
 
502
  {
 
503
    error_allow = CR_SHARED_MEMORY_CONNECT_ANSWER_ERROR;
 
504
    goto err;
 
505
  }
 
506
  strmov(suffix_pos, "CONNECT_DATA");
 
507
  if (!(handle_connect_file_map= OpenFileMapping(FILE_MAP_WRITE,FALSE,tmp)))
 
508
  {
 
509
    error_allow = CR_SHARED_MEMORY_CONNECT_FILE_MAP_ERROR;
 
510
    goto err;
 
511
  }
 
512
  if (!(handle_connect_map= MapViewOfFile(handle_connect_file_map,
 
513
                                          FILE_MAP_WRITE,0,0,sizeof(DWORD))))
 
514
  {
 
515
    error_allow = CR_SHARED_MEMORY_CONNECT_MAP_ERROR;
 
516
    goto err;
 
517
  }
 
518
 
 
519
  /* Send to server request of connection */
 
520
  if (!SetEvent(event_connect_request))
 
521
  {
 
522
    error_allow = CR_SHARED_MEMORY_CONNECT_SET_ERROR;
 
523
    goto err;
 
524
  }
 
525
 
 
526
  /* Wait of answer from server */
 
527
  if (WaitForSingleObject(event_connect_answer,connect_timeout*1000) !=
 
528
      WAIT_OBJECT_0)
 
529
  {
 
530
    error_allow = CR_SHARED_MEMORY_CONNECT_ABANDONED_ERROR;
 
531
    goto err;
 
532
  }
 
533
 
 
534
  /* Get number of connection */
 
535
  connect_number = uint4korr(handle_connect_map);/*WAX2*/
 
536
  p= int10_to_str(connect_number, connect_number_char, 10);
 
537
 
 
538
  /*
 
539
    The name of event and file-mapping events create agree next rule:
 
540
    shared_memory_base_name+unique_part+number_of_connection
 
541
 
 
542
    Where:
 
543
    shared_memory_base_name is uniquel value for each server
 
544
    unique_part is uniquel value for each object (events and file-mapping)
 
545
    number_of_connection is number of connection between server and client
 
546
  */
 
547
  suffix_pos = strxmov(tmp, "Global\\", shared_memory_base_name, "_", connect_number_char,
 
548
                       "_", NullS);
 
549
  strmov(suffix_pos, "DATA");
 
550
  if ((handle_file_map = OpenFileMapping(FILE_MAP_WRITE,FALSE,tmp)) == NULL)
 
551
  {
 
552
    error_allow = CR_SHARED_MEMORY_FILE_MAP_ERROR;
 
553
    goto err2;
 
554
  }
 
555
  if ((handle_map = MapViewOfFile(handle_file_map,FILE_MAP_WRITE,0,0,
 
556
                                  smem_buffer_length)) == NULL)
 
557
  {
 
558
    error_allow = CR_SHARED_MEMORY_MAP_ERROR;
 
559
    goto err2;
 
560
  }
 
561
 
 
562
  strmov(suffix_pos, "SERVER_WROTE");
 
563
  if ((event_server_wrote = OpenEvent(event_access_rights,FALSE,tmp)) == NULL)
 
564
  {
 
565
    error_allow = CR_SHARED_MEMORY_EVENT_ERROR;
 
566
    goto err2;
 
567
  }
 
568
 
 
569
  strmov(suffix_pos, "SERVER_READ");
 
570
  if ((event_server_read = OpenEvent(event_access_rights,FALSE,tmp)) == NULL)
 
571
  {
 
572
    error_allow = CR_SHARED_MEMORY_EVENT_ERROR;
 
573
    goto err2;
 
574
  }
 
575
 
 
576
  strmov(suffix_pos, "CLIENT_WROTE");
 
577
  if ((event_client_wrote = OpenEvent(event_access_rights,FALSE,tmp)) == NULL)
 
578
  {
 
579
    error_allow = CR_SHARED_MEMORY_EVENT_ERROR;
 
580
    goto err2;
 
581
  }
 
582
 
 
583
  strmov(suffix_pos, "CLIENT_READ");
 
584
  if ((event_client_read = OpenEvent(event_access_rights,FALSE,tmp)) == NULL)
 
585
  {
 
586
    error_allow = CR_SHARED_MEMORY_EVENT_ERROR;
 
587
    goto err2;
 
588
  }
 
589
 
 
590
  strmov(suffix_pos, "CONNECTION_CLOSED");
 
591
  if ((event_conn_closed = OpenEvent(event_access_rights,FALSE,tmp)) == NULL)
 
592
  {
 
593
    error_allow = CR_SHARED_MEMORY_EVENT_ERROR;
 
594
    goto err2;
 
595
  }
 
596
  /*
 
597
    Set event that server should send data
 
598
  */
 
599
  SetEvent(event_server_read);
 
600
 
 
601
err2:
 
602
  if (error_allow == 0)
 
603
  {
 
604
    net->vio= vio_new_win32shared_memory(net,handle_file_map,handle_map,
 
605
                                         event_server_wrote,
 
606
                                         event_server_read,event_client_wrote,
 
607
                                         event_client_read,event_conn_closed);
 
608
  }
 
609
  else
 
610
  {
 
611
    error_code = GetLastError();
 
612
    if (event_server_read)
 
613
      CloseHandle(event_server_read);
 
614
    if (event_server_wrote)
 
615
      CloseHandle(event_server_wrote);
 
616
    if (event_client_read)
 
617
      CloseHandle(event_client_read);
 
618
    if (event_client_wrote)
 
619
      CloseHandle(event_client_wrote);
 
620
    if (event_conn_closed)
 
621
      CloseHandle(event_conn_closed);
 
622
    if (handle_map)
 
623
      UnmapViewOfFile(handle_map);
 
624
    if (handle_file_map)
 
625
      CloseHandle(handle_file_map);
 
626
  }
 
627
err:
 
628
  if (tmp)
 
629
    my_free(tmp, MYF(0));
 
630
  if (error_allow)
 
631
    error_code = GetLastError();
 
632
  if (event_connect_request)
 
633
    CloseHandle(event_connect_request);
 
634
  if (event_connect_answer)
 
635
    CloseHandle(event_connect_answer);
 
636
  if (handle_connect_map)
 
637
    UnmapViewOfFile(handle_connect_map);
 
638
  if (handle_connect_file_map)
 
639
    CloseHandle(handle_connect_file_map);
 
640
  if (error_allow)
 
641
  {
 
642
    if (error_allow == CR_SHARED_MEMORY_EVENT_ERROR)
 
643
      set_mysql_extended_error(mysql, error_allow, unknown_sqlstate,
 
644
                               ER(error_allow), suffix_pos, error_code);
 
645
    else
 
646
      set_mysql_extended_error(mysql, error_allow, unknown_sqlstate,
 
647
                               ER(error_allow), error_code);
 
648
    return(INVALID_HANDLE_VALUE);
 
649
  }
 
650
  return(handle_map);
 
651
}
 
652
#endif
100
653
 
101
654
/*****************************************************************************
102
655
  Read a packet from server. Give error message if socket was down
103
656
  or packet is an error message
104
657
*****************************************************************************/
105
658
 
106
 
uint32_t cli_safe_read(DRIZZLE *drizzle)
 
659
ulong
 
660
cli_safe_read(MYSQL *mysql)
107
661
{
108
 
  NET *net= &drizzle->net;
109
 
  uint32_t len=0;
 
662
  NET *net= &mysql->net;
 
663
  ulong len=0;
 
664
  init_sigpipe_variables
110
665
 
 
666
  /* Don't give sigpipe errors if the client doesn't want them */
 
667
  set_sigpipe(mysql);
111
668
  if (net->vio != 0)
112
669
    len=my_net_read(net);
 
670
  reset_sigpipe(mysql);
113
671
 
114
672
  if (len == packet_error || len == 0)
115
673
  {
116
 
#ifdef DRIZZLE_SERVER
 
674
    DBUG_PRINT("error",("Wrong connection or packet. fd: %s  len: %lu",
 
675
                        vio_description(net->vio),len));
 
676
#ifdef MYSQL_SERVER
117
677
    if (net->vio && vio_was_interrupted(net->vio))
118
678
      return (packet_error);
119
 
#endif /*DRIZZLE_SERVER*/
120
 
    drizzle_disconnect(drizzle);
121
 
    drizzle_set_error(drizzle, net->last_errno == CR_NET_PACKET_TOO_LARGE ?
122
 
                      CR_NET_PACKET_TOO_LARGE : CR_SERVER_LOST,
123
 
                      sqlstate_get_unknown());
 
679
#endif /*MYSQL_SERVER*/
 
680
    end_server(mysql);
 
681
    set_mysql_error(mysql, net->last_errno == ER_NET_PACKET_TOO_LARGE ?
 
682
                    CR_NET_PACKET_TOO_LARGE: CR_SERVER_LOST, unknown_sqlstate);
124
683
    return (packet_error);
125
684
  }
126
685
  if (net->read_pos[0] == 255)
131
690
      net->last_errno=uint2korr(pos);
132
691
      pos+=2;
133
692
      len-=2;
134
 
      if (pos[0] == '#')
 
693
      if (protocol_41(mysql) && pos[0] == '#')
135
694
      {
136
 
        strncpy(net->sqlstate, pos+1, SQLSTATE_LENGTH);
137
 
        pos+= SQLSTATE_LENGTH+1;
 
695
        strmake(net->sqlstate, pos+1, SQLSTATE_LENGTH);
 
696
        pos+= SQLSTATE_LENGTH+1;
138
697
      }
139
698
      else
140
699
      {
143
702
          (unknown error sql state).
144
703
        */
145
704
 
146
 
        strcpy(net->sqlstate, sqlstate_get_unknown());
 
705
        strmov(net->sqlstate, unknown_sqlstate);
147
706
      }
148
707
 
149
 
      strncpy(net->last_error,(char*) pos, min((uint32_t) len,
150
 
              (uint32_t) sizeof(net->last_error)-1));
 
708
      (void) strmake(net->last_error,(char*) pos,
 
709
                     min((uint) len,(uint) sizeof(net->last_error)-1));
151
710
    }
152
711
    else
153
 
      drizzle_set_error(drizzle, CR_UNKNOWN_ERROR, sqlstate_get_unknown());
 
712
      set_mysql_error(mysql, CR_UNKNOWN_ERROR, unknown_sqlstate);
154
713
    /*
155
714
      Cover a protocol design error: error packet does not
156
715
      contain the server status. Therefore, the client has no way
160
719
      a multi-statement or a stored procedure, so it should be
161
720
      safe to unconditionally turn off the flag here.
162
721
    */
163
 
    drizzle->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
 
722
    mysql->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
164
723
 
 
724
    DBUG_PRINT("error",("Got error: %d/%s (%s)",
 
725
                        net->last_errno,
 
726
                        net->sqlstate,
 
727
                        net->last_error));
165
728
    return(packet_error);
166
729
  }
167
730
  return len;
168
731
}
169
732
 
170
 
bool
171
 
cli_advanced_command(DRIZZLE *drizzle, enum enum_server_command command,
172
 
         const unsigned char *header, uint32_t header_length,
173
 
         const unsigned char *arg, uint32_t arg_length, bool skip_check)
174
 
{
175
 
  NET *net= &drizzle->net;
176
 
  bool result= 1;
177
 
  bool stmt_skip= false;
178
 
 
179
 
  if (drizzle->net.vio == 0)
180
 
  {            /* Do reconnect if possible */
181
 
    if (drizzle_reconnect(drizzle) || stmt_skip)
182
 
      return(1);
183
 
  }
184
 
  if (drizzle->status != DRIZZLE_STATUS_READY ||
185
 
      drizzle->server_status & SERVER_MORE_RESULTS_EXISTS)
186
 
  {
187
 
    drizzle_set_error(drizzle, CR_COMMANDS_OUT_OF_SYNC,
188
 
                      sqlstate_get_unknown());
189
 
    return(1);
 
733
void free_rows(MYSQL_DATA *cur)
 
734
{
 
735
  if (cur)
 
736
  {
 
737
    free_root(&cur->alloc,MYF(0));
 
738
    my_free((uchar*) cur,MYF(0));
 
739
  }
 
740
}
 
741
 
 
742
my_bool
 
743
cli_advanced_command(MYSQL *mysql, enum enum_server_command command,
 
744
                     const uchar *header, ulong header_length,
 
745
                     const uchar *arg, ulong arg_length, my_bool skip_check,
 
746
                     MYSQL_STMT *stmt)
 
747
{
 
748
  NET *net= &mysql->net;
 
749
  my_bool result= 1;
 
750
  init_sigpipe_variables
 
751
  my_bool stmt_skip= stmt ? stmt->state != MYSQL_STMT_INIT_DONE : FALSE;
 
752
  DBUG_ENTER("cli_advanced_command");
 
753
 
 
754
  /* Don't give sigpipe errors if the client doesn't want them */
 
755
  set_sigpipe(mysql);
 
756
 
 
757
  if (mysql->net.vio == 0)
 
758
  {                                             /* Do reconnect if possible */
 
759
    if (mysql_reconnect(mysql) || stmt_skip)
 
760
      DBUG_RETURN(1);
 
761
  }
 
762
  if (mysql->status != MYSQL_STATUS_READY ||
 
763
      mysql->server_status & SERVER_MORE_RESULTS_EXISTS)
 
764
  {
 
765
    DBUG_PRINT("error",("state: %d", mysql->status));
 
766
    set_mysql_error(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
 
767
    DBUG_RETURN(1);
190
768
  }
191
769
 
192
770
  net_clear_error(net);
193
 
  drizzle->info=0;
194
 
  drizzle->affected_rows= ~(uint64_t) 0;
 
771
  mysql->info=0;
 
772
  mysql->affected_rows= ~(my_ulonglong) 0;
195
773
  /*
196
774
    We don't want to clear the protocol buffer on COM_QUIT, because if
197
775
    the previous command was a shutdown command, we may have the
198
776
    response for the COM_QUIT already in the communication buffer
199
777
  */
200
 
  net_clear(&drizzle->net, (command != COM_QUIT));
 
778
  net_clear(&mysql->net, (command != COM_QUIT));
201
779
 
202
 
  if (net_write_command(net,(unsigned char) command, header, header_length,
203
 
      arg, arg_length))
 
780
  if (net_write_command(net,(uchar) command, header, header_length,
 
781
                        arg, arg_length))
204
782
  {
205
 
    if (net->last_errno == CR_NET_PACKET_TOO_LARGE)
 
783
    DBUG_PRINT("error",("Can't send command to server. Error: %d",
 
784
                        socket_errno));
 
785
    if (net->last_errno == ER_NET_PACKET_TOO_LARGE)
206
786
    {
207
 
      drizzle_set_error(drizzle, CR_NET_PACKET_TOO_LARGE, sqlstate_get_unknown());
 
787
      set_mysql_error(mysql, CR_NET_PACKET_TOO_LARGE, unknown_sqlstate);
208
788
      goto end;
209
789
    }
210
 
    drizzle_disconnect(drizzle);
211
 
    if (drizzle_reconnect(drizzle) || stmt_skip)
 
790
    end_server(mysql);
 
791
    if (mysql_reconnect(mysql) || stmt_skip)
212
792
      goto end;
213
 
    if (net_write_command(net,(unsigned char) command, header, header_length,
214
 
        arg, arg_length))
 
793
    if (net_write_command(net,(uchar) command, header, header_length,
 
794
                          arg, arg_length))
215
795
    {
216
 
      drizzle_set_error(drizzle, CR_SERVER_GONE_ERROR, sqlstate_get_unknown());
 
796
      set_mysql_error(mysql, CR_SERVER_GONE_ERROR, unknown_sqlstate);
217
797
      goto end;
218
798
    }
219
799
  }
220
800
  result=0;
221
801
  if (!skip_check)
222
 
    result= ((drizzle->packet_length=cli_safe_read(drizzle)) == packet_error ?
223
 
       1 : 0);
 
802
    result= ((mysql->packet_length=cli_safe_read(mysql)) == packet_error ?
 
803
             1 : 0);
224
804
end:
225
 
  return(result);
226
 
}
227
 
 
228
 
void free_old_query(DRIZZLE *drizzle)
229
 
{
230
 
  if (drizzle->fields)
231
 
  {
232
 
    /* TODO - we need to de-alloc field storage */
233
 
    free(drizzle->fields->catalog);
234
 
    free(drizzle->fields->db);
235
 
    free(drizzle->fields->table);
236
 
    free(drizzle->fields->org_table);
237
 
    free(drizzle->fields->name);
238
 
    free(drizzle->fields->org_name);
239
 
    free(drizzle->fields->def);
240
 
    free(drizzle->fields);
241
 
 
242
 
  }
243
 
  /* init_alloc_root(&drizzle->field_alloc,8192,0); */ /* Assume rowlength < 8192 */
244
 
  drizzle->fields= 0;
245
 
  drizzle->field_count= 0;      /* For API */
246
 
  drizzle->warning_count= 0;
247
 
  drizzle->info= 0;
248
 
  return;
249
 
}
250
 
 
251
 
 
252
 
 
253
 
 
254
 
 
255
 
void
256
 
drizzle_free_result(DRIZZLE_RES *result)
257
 
{
 
805
  reset_sigpipe(mysql);
 
806
  DBUG_PRINT("exit",("result: %d", result));
 
807
  DBUG_RETURN(result);
 
808
}
 
809
 
 
810
void free_old_query(MYSQL *mysql)
 
811
{
 
812
  DBUG_ENTER("free_old_query");
 
813
  if (mysql->fields)
 
814
    free_root(&mysql->field_alloc,MYF(0));
 
815
  init_alloc_root(&mysql->field_alloc,8192,0); /* Assume rowlength < 8192 */
 
816
  mysql->fields= 0;
 
817
  mysql->field_count= 0;                        /* For API */
 
818
  mysql->warning_count= 0;
 
819
  mysql->info= 0;
 
820
  DBUG_VOID_RETURN;
 
821
}
 
822
 
 
823
/*
 
824
  Flush result set sent from server
 
825
*/
 
826
 
 
827
static void cli_flush_use_result(MYSQL *mysql)
 
828
{
 
829
  /* Clear the current execution status */
 
830
  DBUG_ENTER("cli_flush_use_result");
 
831
  DBUG_PRINT("warning",("Not all packets read, clearing them"));
 
832
  for (;;)
 
833
  {
 
834
    ulong pkt_len;
 
835
    if ((pkt_len=cli_safe_read(mysql)) == packet_error)
 
836
      break;
 
837
    if (pkt_len <= 8 && mysql->net.read_pos[0] == 254)
 
838
    {
 
839
      if (protocol_41(mysql))
 
840
      {
 
841
        char *pos= (char*) mysql->net.read_pos + 1;
 
842
        mysql->warning_count=uint2korr(pos); pos+=2;
 
843
        mysql->server_status=uint2korr(pos); pos+=2;
 
844
      }
 
845
      break;                            /* End of data */
 
846
    }
 
847
  }
 
848
  DBUG_VOID_RETURN;
 
849
}
 
850
 
 
851
 
 
852
#ifdef __WIN__
 
853
static my_bool is_NT(void)
 
854
{
 
855
  char *os=getenv("OS");
 
856
  return (os && !strcmp(os, "Windows_NT")) ? 1 : 0;
 
857
}
 
858
#endif
 
859
 
 
860
 
 
861
#ifdef CHECK_LICENSE
 
862
/**
 
863
  Check server side variable 'license'.
 
864
 
 
865
  If the variable does not exist or does not contain 'Commercial',
 
866
  we're talking to non-commercial server from commercial client.
 
867
 
 
868
  @retval  0   success
 
869
  @retval  !0  network error or the server is not commercial.
 
870
               Error code is saved in mysql->net.last_errno.
 
871
*/
 
872
 
 
873
static int check_license(MYSQL *mysql)
 
874
{
 
875
  MYSQL_ROW row;
 
876
  MYSQL_RES *res;
 
877
  NET *net= &mysql->net;
 
878
  static const char query[]= "SELECT @@license";
 
879
  static const char required_license[]= STRINGIFY_ARG(LICENSE);
 
880
 
 
881
  if (mysql_real_query(mysql, query, sizeof(query)-1))
 
882
  {
 
883
    if (net->last_errno == ER_UNKNOWN_SYSTEM_VARIABLE)
 
884
    {
 
885
      set_mysql_extended_error(mysql, CR_WRONG_LICENSE, unknown_sqlstate,
 
886
                               ER(CR_WRONG_LICENSE), required_license);
 
887
    }
 
888
    return 1;
 
889
  }
 
890
  if (!(res= mysql_use_result(mysql)))
 
891
    return 1;
 
892
  row= mysql_fetch_row(res);
 
893
  /* 
 
894
    If no rows in result set, or column value is NULL (none of these
 
895
    two is ever true for server variables now), or column value
 
896
    mismatch, set wrong license error.
 
897
  */
 
898
  if (!net->last_errno &&
 
899
      (!row || !row[0] ||
 
900
       strncmp(row[0], required_license, sizeof(required_license))))
 
901
  {
 
902
    set_mysql_extended_error(mysql, CR_WRONG_LICENSE, unknown_sqlstate,
 
903
                             ER(CR_WRONG_LICENSE), required_license);
 
904
  }
 
905
  mysql_free_result(res);
 
906
  return net->last_errno;
 
907
}
 
908
#endif /* CHECK_LICENSE */
 
909
 
 
910
 
 
911
/**************************************************************************
 
912
  Shut down connection
 
913
**************************************************************************/
 
914
 
 
915
void end_server(MYSQL *mysql)
 
916
{
 
917
  int save_errno= errno;
 
918
  DBUG_ENTER("end_server");
 
919
  if (mysql->net.vio != 0)
 
920
  {
 
921
    init_sigpipe_variables
 
922
    DBUG_PRINT("info",("Net: %s", vio_description(mysql->net.vio)));
 
923
    set_sigpipe(mysql);
 
924
    vio_delete(mysql->net.vio);
 
925
    reset_sigpipe(mysql);
 
926
    mysql->net.vio= 0;          /* Marker */
 
927
  }
 
928
  net_end(&mysql->net);
 
929
  free_old_query(mysql);
 
930
  errno= save_errno;
 
931
  DBUG_VOID_RETURN;
 
932
}
 
933
 
 
934
 
 
935
void STDCALL
 
936
mysql_free_result(MYSQL_RES *result)
 
937
{
 
938
  DBUG_ENTER("mysql_free_result");
 
939
  DBUG_PRINT("enter",("mysql_res: 0x%lx", (long) result));
258
940
  if (result)
259
941
  {
260
 
    DRIZZLE *drizzle= result->handle;
261
 
    if (drizzle)
 
942
    MYSQL *mysql= result->handle;
 
943
    if (mysql)
262
944
    {
263
 
      if (drizzle->unbuffered_fetch_owner == &result->unbuffered_fetch_cancelled)
264
 
        drizzle->unbuffered_fetch_owner= 0;
265
 
      if (drizzle->status == DRIZZLE_STATUS_USE_RESULT)
 
945
      if (mysql->unbuffered_fetch_owner == &result->unbuffered_fetch_cancelled)
 
946
        mysql->unbuffered_fetch_owner= 0;
 
947
      if (mysql->status == MYSQL_STATUS_USE_RESULT)
266
948
      {
267
 
        (*drizzle->methods->flush_use_result)(drizzle);
268
 
        drizzle->status=DRIZZLE_STATUS_READY;
269
 
        if (drizzle->unbuffered_fetch_owner)
270
 
          *drizzle->unbuffered_fetch_owner= true;
 
949
        (*mysql->methods->flush_use_result)(mysql);
 
950
        mysql->status=MYSQL_STATUS_READY;
 
951
        if (mysql->unbuffered_fetch_owner)
 
952
          *mysql->unbuffered_fetch_owner= TRUE;
271
953
      }
272
954
    }
273
955
    free_rows(result->data);
274
 
    /* TODO: free result->fields */
 
956
    if (result->fields)
 
957
      free_root(&result->field_alloc,MYF(0));
275
958
    if (result->row)
276
 
      free((unsigned char*) result->row);
277
 
    free((unsigned char*) result);
278
 
  }
279
 
}
280
 
 
281
 
 
282
 
 
 
959
      my_free((uchar*) result->row,MYF(0));
 
960
    my_free((uchar*) result,MYF(0));
 
961
  }
 
962
  DBUG_VOID_RETURN;
 
963
}
 
964
 
 
965
/****************************************************************************
 
966
  Get options from my.cnf
 
967
****************************************************************************/
 
968
 
 
969
static const char *default_options[]=
 
970
{
 
971
  "port","socket","compress","password","pipe", "timeout", "user",
 
972
  "init-command", "host", "database", "debug", "return-found-rows",
 
973
  "ssl-key" ,"ssl-cert" ,"ssl-ca" ,"ssl-capath",
 
974
  "character-sets-dir", "default-character-set", "interactive-timeout",
 
975
  "connect-timeout", "local-infile", "disable-local-infile",
 
976
  "ssl-cipher", "max-allowed-packet", "protocol", "shared-memory-base-name",
 
977
  "multi-results", "multi-statements", "multi-queries", "secure-auth",
 
978
  "report-data-truncation",
 
979
  NullS
 
980
};
 
981
 
 
982
static TYPELIB option_types={array_elements(default_options)-1,
 
983
                             "options",default_options, NULL};
 
984
 
 
985
const char *sql_protocol_names_lib[] =
 
986
{ "TCP", "SOCKET", "PIPE", "MEMORY", NullS };
 
987
TYPELIB sql_protocol_typelib = {array_elements(sql_protocol_names_lib)-1,"",
 
988
                                sql_protocol_names_lib, NULL};
 
989
 
 
990
static int add_init_command(struct st_mysql_options *options, const char *cmd)
 
991
{
 
992
  char *tmp;
 
993
 
 
994
  if (!options->init_commands)
 
995
  {
 
996
    options->init_commands= (DYNAMIC_ARRAY*)my_malloc(sizeof(DYNAMIC_ARRAY),
 
997
                                                      MYF(MY_WME));
 
998
    init_dynamic_array(options->init_commands,sizeof(char*),0,5 CALLER_INFO);
 
999
  }
 
1000
 
 
1001
  if (!(tmp= my_strdup(cmd,MYF(MY_WME))) ||
 
1002
      insert_dynamic(options->init_commands, (uchar*)&tmp))
 
1003
  {
 
1004
    my_free(tmp, MYF(MY_ALLOW_ZERO_PTR));
 
1005
    return 1;
 
1006
  }
 
1007
 
 
1008
  return 0;
 
1009
}
 
1010
 
 
1011
void mysql_read_default_options(struct st_mysql_options *options,
 
1012
                                const char *filename,const char *group)
 
1013
{
 
1014
  int argc;
 
1015
  char *argv_buff[1],**argv;
 
1016
  const char *groups[3];
 
1017
  DBUG_ENTER("mysql_read_default_options");
 
1018
  DBUG_PRINT("enter",("file: %s  group: %s",filename,group ? group :"NULL"));
 
1019
 
 
1020
  argc=1; argv=argv_buff; argv_buff[0]= (char*) "client";
 
1021
  groups[0]= (char*) "client"; groups[1]= (char*) group; groups[2]=0;
 
1022
 
 
1023
  load_defaults(filename, groups, &argc, &argv);
 
1024
  if (argc != 1)                                /* If some default option */
 
1025
  {
 
1026
    char **option=argv;
 
1027
    while (*++option)
 
1028
    {
 
1029
      /* DBUG_PRINT("info",("option: %s",option[0])); */
 
1030
      if (option[0][0] == '-' && option[0][1] == '-')
 
1031
      {
 
1032
        char *end=strcend(*option,'=');
 
1033
        char *opt_arg=0;
 
1034
        if (*end)
 
1035
        {
 
1036
          opt_arg=end+1;
 
1037
          *end=0;                               /* Remove '=' */
 
1038
        }
 
1039
        /* Change all '_' in variable name to '-' */
 
1040
        for (end= *option ; *(end= strcend(end,'_')) ; )
 
1041
          *end= '-';
 
1042
        switch (find_type(*option+2,&option_types,2)) {
 
1043
        case 1:                         /* port */
 
1044
          if (opt_arg)
 
1045
            options->port=atoi(opt_arg);
 
1046
          break;
 
1047
        case 2:                         /* socket */
 
1048
          if (opt_arg)
 
1049
          {
 
1050
            my_free(options->unix_socket,MYF(MY_ALLOW_ZERO_PTR));
 
1051
            options->unix_socket=my_strdup(opt_arg,MYF(MY_WME));
 
1052
          }
 
1053
          break;
 
1054
        case 3:                         /* compress */
 
1055
          options->compress=1;
 
1056
          options->client_flag|= CLIENT_COMPRESS;
 
1057
          break;
 
1058
        case 4:                         /* password */
 
1059
          if (opt_arg)
 
1060
          {
 
1061
            my_free(options->password,MYF(MY_ALLOW_ZERO_PTR));
 
1062
            options->password=my_strdup(opt_arg,MYF(MY_WME));
 
1063
          }
 
1064
          break;
 
1065
        case 5:
 
1066
          options->protocol = MYSQL_PROTOCOL_PIPE;
 
1067
        case 20:                        /* connect_timeout */
 
1068
        case 6:                         /* timeout */
 
1069
          if (opt_arg)
 
1070
            options->connect_timeout=atoi(opt_arg);
 
1071
          break;
 
1072
        case 7:                         /* user */
 
1073
          if (opt_arg)
 
1074
          {
 
1075
            my_free(options->user,MYF(MY_ALLOW_ZERO_PTR));
 
1076
            options->user=my_strdup(opt_arg,MYF(MY_WME));
 
1077
          }
 
1078
          break;
 
1079
        case 8:                         /* init-command */
 
1080
          add_init_command(options,opt_arg);
 
1081
          break;
 
1082
        case 9:                         /* host */
 
1083
          if (opt_arg)
 
1084
          {
 
1085
            my_free(options->host,MYF(MY_ALLOW_ZERO_PTR));
 
1086
            options->host=my_strdup(opt_arg,MYF(MY_WME));
 
1087
          }
 
1088
          break;
 
1089
        case 10:                        /* database */
 
1090
          if (opt_arg)
 
1091
          {
 
1092
            my_free(options->db,MYF(MY_ALLOW_ZERO_PTR));
 
1093
            options->db=my_strdup(opt_arg,MYF(MY_WME));
 
1094
          }
 
1095
          break;
 
1096
        case 11:                        /* debug */
 
1097
#ifdef MYSQL_CLIENT
 
1098
          mysql_debug(opt_arg ? opt_arg : "d:t:o,/tmp/client.trace");
 
1099
          break;
 
1100
#endif
 
1101
        case 12:                        /* return-found-rows */
 
1102
          options->client_flag|=CLIENT_FOUND_ROWS;
 
1103
          break;
 
1104
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
 
1105
        case 13:                        /* ssl_key */
 
1106
          my_free(options->ssl_key, MYF(MY_ALLOW_ZERO_PTR));
 
1107
          options->ssl_key = my_strdup(opt_arg, MYF(MY_WME));
 
1108
          break;
 
1109
        case 14:                        /* ssl_cert */
 
1110
          my_free(options->ssl_cert, MYF(MY_ALLOW_ZERO_PTR));
 
1111
          options->ssl_cert = my_strdup(opt_arg, MYF(MY_WME));
 
1112
          break;
 
1113
        case 15:                        /* ssl_ca */
 
1114
          my_free(options->ssl_ca, MYF(MY_ALLOW_ZERO_PTR));
 
1115
          options->ssl_ca = my_strdup(opt_arg, MYF(MY_WME));
 
1116
          break;
 
1117
        case 16:                        /* ssl_capath */
 
1118
          my_free(options->ssl_capath, MYF(MY_ALLOW_ZERO_PTR));
 
1119
          options->ssl_capath = my_strdup(opt_arg, MYF(MY_WME));
 
1120
          break;
 
1121
        case 23:                        /* ssl_cipher */
 
1122
          my_free(options->ssl_cipher, MYF(MY_ALLOW_ZERO_PTR));
 
1123
          options->ssl_cipher= my_strdup(opt_arg, MYF(MY_WME));
 
1124
          break;
 
1125
#else
 
1126
        case 13:                                /* Ignore SSL options */
 
1127
        case 14:
 
1128
        case 15:
 
1129
        case 16:
 
1130
        case 23:
 
1131
          break;
 
1132
#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */
 
1133
        case 17:                        /* charset-lib */
 
1134
          my_free(options->charset_dir,MYF(MY_ALLOW_ZERO_PTR));
 
1135
          options->charset_dir = my_strdup(opt_arg, MYF(MY_WME));
 
1136
          break;
 
1137
        case 18:
 
1138
          my_free(options->charset_name,MYF(MY_ALLOW_ZERO_PTR));
 
1139
          options->charset_name = my_strdup(opt_arg, MYF(MY_WME));
 
1140
          break;
 
1141
        case 19:                                /* Interactive-timeout */
 
1142
          options->client_flag|= CLIENT_INTERACTIVE;
 
1143
          break;
 
1144
        case 21:
 
1145
          if (!opt_arg || atoi(opt_arg) != 0)
 
1146
            options->client_flag|= CLIENT_LOCAL_FILES;
 
1147
          else
 
1148
            options->client_flag&= ~CLIENT_LOCAL_FILES;
 
1149
          break;
 
1150
        case 22:
 
1151
          options->client_flag&= ~CLIENT_LOCAL_FILES;
 
1152
          break;
 
1153
        case 24: /* max-allowed-packet */
 
1154
          if (opt_arg)
 
1155
            options->max_allowed_packet= atoi(opt_arg);
 
1156
          break;
 
1157
        case 25: /* protocol */
 
1158
          if ((options->protocol= find_type(opt_arg,
 
1159
                                            &sql_protocol_typelib,0)) <= 0)
 
1160
          {
 
1161
            fprintf(stderr, "Unknown option to protocol: %s\n", opt_arg);
 
1162
            exit(1);
 
1163
          }
 
1164
          break;
 
1165
        case 26: /* shared_memory_base_name */
 
1166
#ifdef HAVE_SMEM
 
1167
          if (options->shared_memory_base_name != def_shared_memory_base_name)
 
1168
            my_free(options->shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
 
1169
          options->shared_memory_base_name=my_strdup(opt_arg,MYF(MY_WME));
 
1170
#endif
 
1171
          break;
 
1172
        case 27: /* multi-results */
 
1173
          options->client_flag|= CLIENT_MULTI_RESULTS;
 
1174
          break;
 
1175
        case 28: /* multi-statements */
 
1176
        case 29: /* multi-queries */
 
1177
          options->client_flag|= CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS;
 
1178
          break;
 
1179
        case 30: /* secure-auth */
 
1180
          options->secure_auth= TRUE;
 
1181
          break;
 
1182
        case 31: /* report-data-truncation */
 
1183
          options->report_data_truncation= opt_arg ? test(atoi(opt_arg)) : 1;
 
1184
          break;
 
1185
        default:
 
1186
          DBUG_PRINT("warning",("unknown option: %s",option[0]));
 
1187
        }
 
1188
      }
 
1189
    }
 
1190
  }
 
1191
  free_defaults(argv);
 
1192
  DBUG_VOID_RETURN;
 
1193
}
 
1194
 
 
1195
 
 
1196
/**************************************************************************
 
1197
  Get column lengths of the current row
 
1198
  If one uses mysql_use_result, res->lengths contains the length information,
 
1199
  else the lengths are calculated from the offset between pointers.
 
1200
**************************************************************************/
 
1201
 
 
1202
static void cli_fetch_lengths(ulong *to, MYSQL_ROW column,
 
1203
                              unsigned int field_count)
 
1204
 
1205
  ulong *prev_length;
 
1206
  char *start=0;
 
1207
  MYSQL_ROW end;
 
1208
 
 
1209
  prev_length=0;                                /* Keep gcc happy */
 
1210
  for (end=column + field_count + 1 ; column != end ; column++, to++)
 
1211
  {
 
1212
    if (!*column)
 
1213
    {
 
1214
      *to= 0;                                   /* Null */
 
1215
      continue;
 
1216
    }
 
1217
    if (start)                                  /* Found end of prev string */
 
1218
      *prev_length= (ulong) (*column-start-1);
 
1219
    start= *column;
 
1220
    prev_length= to;
 
1221
  }
 
1222
}
 
1223
 
 
1224
/***************************************************************************
 
1225
  Change field rows to field structs
 
1226
***************************************************************************/
 
1227
 
 
1228
MYSQL_FIELD *
 
1229
unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
 
1230
              my_bool default_value, uint server_capabilities)
 
1231
{
 
1232
  MYSQL_ROWS    *row;
 
1233
  MYSQL_FIELD   *field,*result;
 
1234
  ulong lengths[9];                             /* Max of fields */
 
1235
  DBUG_ENTER("unpack_fields");
 
1236
 
 
1237
  field= result= (MYSQL_FIELD*) alloc_root(alloc,
 
1238
                                           (uint) sizeof(*field)*fields);
 
1239
  if (!result)
 
1240
  {
 
1241
    free_rows(data);                            /* Free old data */
 
1242
    DBUG_RETURN(0);
 
1243
  }
 
1244
  bzero((char*) field, (uint) sizeof(MYSQL_FIELD)*fields);
 
1245
  if (server_capabilities & CLIENT_PROTOCOL_41)
 
1246
  {
 
1247
    /* server is 4.1, and returns the new field result format */
 
1248
    for (row=data->data; row ; row = row->next,field++)
 
1249
    {
 
1250
      uchar *pos;
 
1251
      /* fields count may be wrong */
 
1252
      DBUG_ASSERT((uint) (field - result) < fields);
 
1253
      cli_fetch_lengths(&lengths[0], row->data, default_value ? 8 : 7);
 
1254
      field->catalog=   strmake_root(alloc,(char*) row->data[0], lengths[0]);
 
1255
      field->db=        strmake_root(alloc,(char*) row->data[1], lengths[1]);
 
1256
      field->table=     strmake_root(alloc,(char*) row->data[2], lengths[2]);
 
1257
      field->org_table= strmake_root(alloc,(char*) row->data[3], lengths[3]);
 
1258
      field->name=      strmake_root(alloc,(char*) row->data[4], lengths[4]);
 
1259
      field->org_name=  strmake_root(alloc,(char*) row->data[5], lengths[5]);
 
1260
 
 
1261
      field->catalog_length=    lengths[0];
 
1262
      field->db_length=         lengths[1];
 
1263
      field->table_length=      lengths[2];
 
1264
      field->org_table_length=  lengths[3];
 
1265
      field->name_length=       lengths[4];
 
1266
      field->org_name_length=   lengths[5];
 
1267
 
 
1268
      /* Unpack fixed length parts */
 
1269
      pos= (uchar*) row->data[6];
 
1270
      field->charsetnr= uint2korr(pos);
 
1271
      field->length=    (uint) uint4korr(pos+2);
 
1272
      field->type=      (enum enum_field_types) pos[6];
 
1273
      field->flags=     uint2korr(pos+7);
 
1274
      field->decimals=  (uint) pos[9];
 
1275
 
 
1276
      if (INTERNAL_NUM_FIELD(field))
 
1277
        field->flags|= NUM_FLAG;
 
1278
      if (default_value && row->data[7])
 
1279
      {
 
1280
        field->def=strmake_root(alloc,(char*) row->data[7], lengths[7]);
 
1281
        field->def_length= lengths[7];
 
1282
      }
 
1283
      else
 
1284
        field->def=0;
 
1285
      field->max_length= 0;
 
1286
    }
 
1287
  }
 
1288
#ifndef DELETE_SUPPORT_OF_4_0_PROTOCOL
 
1289
  else
 
1290
  {
 
1291
    /* old protocol, for backward compatibility */
 
1292
    for (row=data->data; row ; row = row->next,field++)
 
1293
    {
 
1294
      cli_fetch_lengths(&lengths[0], row->data, default_value ? 6 : 5);
 
1295
      field->org_table= field->table=  strdup_root(alloc,(char*) row->data[0]);
 
1296
      field->name=   strdup_root(alloc,(char*) row->data[1]);
 
1297
      field->length= (uint) uint3korr(row->data[2]);
 
1298
      field->type=   (enum enum_field_types) (uchar) row->data[3][0];
 
1299
 
 
1300
      field->catalog=(char*)  "";
 
1301
      field->db=     (char*)  "";
 
1302
      field->catalog_length= 0;
 
1303
      field->db_length= 0;
 
1304
      field->org_table_length=  field->table_length=    lengths[0];
 
1305
      field->name_length=       lengths[1];
 
1306
 
 
1307
      if (server_capabilities & CLIENT_LONG_FLAG)
 
1308
      {
 
1309
        field->flags=   uint2korr(row->data[4]);
 
1310
        field->decimals=(uint) (uchar) row->data[4][2];
 
1311
      }
 
1312
      else
 
1313
      {
 
1314
        field->flags=   (uint) (uchar) row->data[4][0];
 
1315
        field->decimals=(uint) (uchar) row->data[4][1];
 
1316
      }
 
1317
      if (INTERNAL_NUM_FIELD(field))
 
1318
        field->flags|= NUM_FLAG;
 
1319
      if (default_value && row->data[5])
 
1320
      {
 
1321
        field->def=strdup_root(alloc,(char*) row->data[5]);
 
1322
        field->def_length= lengths[5];
 
1323
      }
 
1324
      else
 
1325
        field->def=0;
 
1326
      field->max_length= 0;
 
1327
    }
 
1328
  }
 
1329
#endif /* DELETE_SUPPORT_OF_4_0_PROTOCOL */
 
1330
  free_rows(data);                              /* Free old data */
 
1331
  DBUG_RETURN(result);
 
1332
}
283
1333
 
284
1334
/* Read all rows (fields or data) from server */
285
1335
 
286
 
DRIZZLE_DATA *cli_read_rows(DRIZZLE *drizzle, DRIZZLE_FIELD *DRIZZLE_FIELDs, uint32_t fields)
 
1336
MYSQL_DATA *cli_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
 
1337
                          unsigned int fields)
287
1338
{
288
 
  uint32_t  field;
289
 
  uint32_t pkt_len;
290
 
  uint32_t len;
291
 
  unsigned char *cp;
292
 
  char  *to, *end_to;
293
 
  DRIZZLE_DATA *result;
294
 
  DRIZZLE_ROWS **prev_ptr,*cur;
295
 
  NET *net = &drizzle->net;
 
1339
  uint  field;
 
1340
  ulong pkt_len;
 
1341
  ulong len;
 
1342
  uchar *cp;
 
1343
  char  *to, *end_to;
 
1344
  MYSQL_DATA *result;
 
1345
  MYSQL_ROWS **prev_ptr,*cur;
 
1346
  NET *net = &mysql->net;
 
1347
  DBUG_ENTER("cli_read_rows");
296
1348
 
297
 
  if ((pkt_len= cli_safe_read(drizzle)) == packet_error)
298
 
    return(0);
299
 
  if (!(result=(DRIZZLE_DATA*) malloc(sizeof(DRIZZLE_DATA))))
 
1349
  if ((pkt_len= cli_safe_read(mysql)) == packet_error)
 
1350
    DBUG_RETURN(0);
 
1351
  if (!(result=(MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA),
 
1352
                                       MYF(MY_WME | MY_ZEROFILL))))
300
1353
  {
301
 
    drizzle_set_error(drizzle, CR_OUT_OF_MEMORY,
302
 
                      sqlstate_get_unknown());
303
 
    return(0);
 
1354
    set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate);
 
1355
    DBUG_RETURN(0);
304
1356
  }
305
 
  memset(result, 0, sizeof(DRIZZLE_DATA));
 
1357
  init_alloc_root(&result->alloc,8192,0);       /* Assume rowlength < 8192 */
 
1358
  result->alloc.min_malloc=sizeof(MYSQL_ROWS);
306
1359
  prev_ptr= &result->data;
307
1360
  result->rows=0;
308
1361
  result->fields=fields;
309
1362
 
310
1363
  /*
311
 
    The last EOF packet is either a 254 (0xFE) character followed by 1-7 status bytes.
 
1364
    The last EOF packet is either a single 254 character or (in MySQL 4.1)
 
1365
    254 followed by 1-7 status bytes.
312
1366
 
313
1367
    This doesn't conflict with normal usage of 254 which stands for a
314
1368
    string where the length of the string is 8 bytes. (see net_field_length())
315
1369
  */
316
1370
 
317
 
  while (*(cp=net->read_pos) != DRIZZLE_PROTOCOL_NO_MORE_DATA || pkt_len >= 8)
 
1371
  while (*(cp=net->read_pos) != 254 || pkt_len >= 8)
318
1372
  {
319
1373
    result->rows++;
320
 
    if (!(cur= (DRIZZLE_ROWS*) malloc(sizeof(DRIZZLE_ROWS))) ||
321
 
        !(cur->data= ((DRIZZLE_ROW) malloc((fields+1)*sizeof(char *)+pkt_len))))
 
1374
    if (!(cur= (MYSQL_ROWS*) alloc_root(&result->alloc,
 
1375
                                        sizeof(MYSQL_ROWS))) ||
 
1376
        !(cur->data= ((MYSQL_ROW)
 
1377
                      alloc_root(&result->alloc,
 
1378
                                 (fields+1)*sizeof(char *)+pkt_len))))
322
1379
    {
323
1380
      free_rows(result);
324
 
      drizzle_set_error(drizzle, CR_OUT_OF_MEMORY, sqlstate_get_unknown());
325
 
      return(0);
 
1381
      set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate);
 
1382
      DBUG_RETURN(0);
326
1383
    }
327
1384
    *prev_ptr=cur;
328
1385
    prev_ptr= &cur->next;
330
1387
    end_to=to+pkt_len-1;
331
1388
    for (field=0 ; field < fields ; field++)
332
1389
    {
333
 
      if ((len= net_field_length(&cp)) == NULL_LENGTH)
334
 
      {            /* null field */
335
 
        cur->data[field] = 0;
 
1390
      if ((len=(ulong) net_field_length(&cp)) == NULL_LENGTH)
 
1391
      {                                         /* null field */
 
1392
        cur->data[field] = 0;
336
1393
      }
337
1394
      else
338
1395
      {
339
 
        cur->data[field] = to;
340
 
        if (len > (uint32_t) (end_to - to))
 
1396
        cur->data[field] = to;
 
1397
        if (len > (ulong) (end_to - to))
341
1398
        {
342
1399
          free_rows(result);
343
 
          drizzle_set_error(drizzle, CR_MALFORMED_PACKET,
344
 
                            sqlstate_get_unknown());
345
 
          return(0);
346
 
        }
347
 
        memcpy(to, cp, len);
348
 
        to[len]=0;
349
 
        to+=len+1;
350
 
        cp+=len;
351
 
        if (DRIZZLE_FIELDs)
352
 
        {
353
 
          if (DRIZZLE_FIELDs[field].max_length < len)
354
 
            DRIZZLE_FIELDs[field].max_length=len;
355
 
        }
 
1400
          set_mysql_error(mysql, CR_MALFORMED_PACKET, unknown_sqlstate);
 
1401
          DBUG_RETURN(0);
 
1402
        }
 
1403
        memcpy(to,(char*) cp,len); to[len]=0;
 
1404
        to+=len+1;
 
1405
        cp+=len;
 
1406
        if (mysql_fields)
 
1407
        {
 
1408
          if (mysql_fields[field].max_length < len)
 
1409
            mysql_fields[field].max_length=len;
 
1410
        }
356
1411
      }
357
1412
    }
358
 
    cur->data[field]=to;      /* End of last field */
359
 
    if ((pkt_len=cli_safe_read(drizzle)) == packet_error)
 
1413
    cur->data[field]=to;                        /* End of last field */
 
1414
    if ((pkt_len=cli_safe_read(mysql)) == packet_error)
360
1415
    {
361
1416
      free_rows(result);
362
 
      return(0);
 
1417
      DBUG_RETURN(0);
363
1418
    }
364
1419
  }
365
 
  *prev_ptr=0;          /* last pointer is null */
366
 
  if (pkt_len > 1)        /* DRIZZLE 4.1 protocol */
 
1420
  *prev_ptr=0;                                  /* last pointer is null */
 
1421
  if (pkt_len > 1)                              /* MySQL 4.1 protocol */
367
1422
  {
368
 
    drizzle->warning_count= uint2korr(cp+1);
369
 
    drizzle->server_status= uint2korr(cp+3);
 
1423
    mysql->warning_count= uint2korr(cp+1);
 
1424
    mysql->server_status= uint2korr(cp+3);
 
1425
    DBUG_PRINT("info",("status: %u  warning_count:  %u",
 
1426
                       mysql->server_status, mysql->warning_count));
370
1427
  }
371
 
  return(result);
 
1428
  DBUG_PRINT("exit", ("Got %lu rows", (ulong) result->rows));
 
1429
  DBUG_RETURN(result);
372
1430
}
373
1431
 
374
1432
/*
377
1435
*/
378
1436
 
379
1437
 
380
 
static int32_t
381
 
read_one_row(DRIZZLE *drizzle, uint32_t fields, DRIZZLE_ROW row, uint32_t *lengths)
 
1438
static int
 
1439
read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths)
382
1440
{
383
 
  uint32_t field;
384
 
  uint32_t pkt_len,len;
385
 
  unsigned char *pos, *prev_pos, *end_pos;
386
 
  NET *net= &drizzle->net;
 
1441
  uint field;
 
1442
  ulong pkt_len,len;
 
1443
  uchar *pos, *prev_pos, *end_pos;
 
1444
  NET *net= &mysql->net;
387
1445
 
388
 
  if ((pkt_len=cli_safe_read(drizzle)) == packet_error)
 
1446
  if ((pkt_len=cli_safe_read(mysql)) == packet_error)
389
1447
    return -1;
390
 
  if (pkt_len <= 8 && net->read_pos[0] == DRIZZLE_PROTOCOL_NO_MORE_DATA)
 
1448
  if (pkt_len <= 8 && net->read_pos[0] == 254)
391
1449
  {
392
 
    if (pkt_len > 1)        /* DRIZZLE 4.1 protocol */
 
1450
    if (pkt_len > 1)                            /* MySQL 4.1 protocol */
393
1451
    {
394
 
      drizzle->warning_count= uint2korr(net->read_pos+1);
395
 
      drizzle->server_status= uint2korr(net->read_pos+3);
 
1452
      mysql->warning_count= uint2korr(net->read_pos+1);
 
1453
      mysql->server_status= uint2korr(net->read_pos+3);
396
1454
    }
397
 
    return 1;        /* End of data */
 
1455
    return 1;                           /* End of data */
398
1456
  }
399
 
  prev_pos= 0;        /* allowed to write at packet[-1] */
 
1457
  prev_pos= 0;                          /* allowed to write at packet[-1] */
400
1458
  pos=net->read_pos;
401
1459
  end_pos=pos+pkt_len;
402
1460
  for (field=0 ; field < fields ; field++)
403
1461
  {
404
 
    if ((len= net_field_length(&pos)) == NULL_LENGTH)
405
 
    {            /* null field */
 
1462
    if ((len=(ulong) net_field_length(&pos)) == NULL_LENGTH)
 
1463
    {                                           /* null field */
406
1464
      row[field] = 0;
407
1465
      *lengths++=0;
408
1466
    }
409
1467
    else
410
1468
    {
411
 
      if (len > (uint32_t) (end_pos - pos))
 
1469
      if (len > (ulong) (end_pos - pos))
412
1470
      {
413
 
        drizzle_set_error(drizzle, CR_UNKNOWN_ERROR,
414
 
                          sqlstate_get_unknown());
 
1471
        set_mysql_error(mysql, CR_UNKNOWN_ERROR, unknown_sqlstate);
415
1472
        return -1;
416
1473
      }
417
1474
      row[field] = (char*) pos;
419
1476
      *lengths++=len;
420
1477
    }
421
1478
    if (prev_pos)
422
 
      *prev_pos=0;        /* Terminate prev field */
 
1479
      *prev_pos=0;                              /* Terminate prev field */
423
1480
    prev_pos=pos;
424
1481
  }
425
 
  row[field]=(char*) prev_pos+1;    /* End of last field */
426
 
  *prev_pos=0;          /* Terminate last field */
427
 
  return 0;
 
1482
  row[field]=(char*) prev_pos+1;                /* End of last field */
 
1483
  *prev_pos=0;                                  /* Terminate last field */
 
1484
  return 0;
 
1485
}
 
1486
 
 
1487
 
 
1488
/****************************************************************************
 
1489
  Init MySQL structure or allocate one
 
1490
****************************************************************************/
 
1491
 
 
1492
MYSQL * STDCALL
 
1493
mysql_init(MYSQL *mysql)
 
1494
{
 
1495
  if (mysql_server_init(0, NULL, NULL))
 
1496
    return 0;
 
1497
  if (!mysql)
 
1498
  {
 
1499
    if (!(mysql=(MYSQL*) my_malloc(sizeof(*mysql),MYF(MY_WME | MY_ZEROFILL))))
 
1500
    {
 
1501
      set_mysql_error(NULL, CR_OUT_OF_MEMORY, unknown_sqlstate);
 
1502
      return 0;
 
1503
    }
 
1504
    mysql->free_me=1;
 
1505
  }
 
1506
  else
 
1507
    bzero((char*) (mysql), sizeof(*(mysql)));
 
1508
  mysql->options.connect_timeout= CONNECT_TIMEOUT;
 
1509
  mysql->charset=default_client_charset_info;
 
1510
  strmov(mysql->net.sqlstate, not_error_sqlstate);
 
1511
 
 
1512
  /*
 
1513
    Only enable LOAD DATA INFILE by default if configured with
 
1514
    --enable-local-infile
 
1515
  */
 
1516
 
 
1517
#if defined(ENABLED_LOCAL_INFILE) && !defined(MYSQL_SERVER)
 
1518
  mysql->options.client_flag|= CLIENT_LOCAL_FILES;
 
1519
#endif
 
1520
 
 
1521
#ifdef HAVE_SMEM
 
1522
  mysql->options.shared_memory_base_name= (char*) def_shared_memory_base_name;
 
1523
#endif
 
1524
 
 
1525
  mysql->options.methods_to_use= MYSQL_OPT_GUESS_CONNECTION;
 
1526
  mysql->options.report_data_truncation= TRUE;  /* default */
 
1527
 
 
1528
  /*
 
1529
    By default we don't reconnect because it could silently corrupt data (after
 
1530
    reconnection you potentially lose table locks, user variables, session
 
1531
    variables (transactions but they are specifically dealt with in
 
1532
    mysql_reconnect()).
 
1533
    This is a change: < 5.0.3 mysql->reconnect was set to 1 by default.
 
1534
    How this change impacts existing apps:
 
1535
    - existing apps which relyed on the default will see a behaviour change;
 
1536
    they will have to set reconnect=1 after mysql_real_connect().
 
1537
    - existing apps which explicitely asked for reconnection (the only way they
 
1538
    could do it was by setting mysql.reconnect to 1 after mysql_real_connect())
 
1539
    will not see a behaviour change.
 
1540
    - existing apps which explicitely asked for no reconnection
 
1541
    (mysql.reconnect=0) will not see a behaviour change.
 
1542
  */
 
1543
  mysql->reconnect= 0;
 
1544
 
 
1545
  return mysql;
 
1546
}
 
1547
 
 
1548
 
 
1549
/*
 
1550
  Fill in SSL part of MYSQL structure and set 'use_ssl' flag.
 
1551
  NB! Errors are not reported until you do mysql_real_connect.
 
1552
*/
 
1553
 
 
1554
#define strdup_if_not_null(A) (A) == 0 ? 0 : my_strdup((A),MYF(MY_WME))
 
1555
 
 
1556
my_bool STDCALL
 
1557
mysql_ssl_set(MYSQL *mysql __attribute__((unused)) ,
 
1558
              const char *key __attribute__((unused)),
 
1559
              const char *cert __attribute__((unused)),
 
1560
              const char *ca __attribute__((unused)),
 
1561
              const char *capath __attribute__((unused)),
 
1562
              const char *cipher __attribute__((unused)))
 
1563
{
 
1564
  DBUG_ENTER("mysql_ssl_set");
 
1565
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
 
1566
  mysql->options.ssl_key=    strdup_if_not_null(key);
 
1567
  mysql->options.ssl_cert=   strdup_if_not_null(cert);
 
1568
  mysql->options.ssl_ca=     strdup_if_not_null(ca);
 
1569
  mysql->options.ssl_capath= strdup_if_not_null(capath);
 
1570
  mysql->options.ssl_cipher= strdup_if_not_null(cipher);
 
1571
#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */
 
1572
  DBUG_RETURN(0);
 
1573
}
 
1574
 
 
1575
 
 
1576
/*
 
1577
  Free strings in the SSL structure and clear 'use_ssl' flag.
 
1578
  NB! Errors are not reported until you do mysql_real_connect.
 
1579
*/
 
1580
 
 
1581
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
 
1582
 
 
1583
static void
 
1584
mysql_ssl_free(MYSQL *mysql __attribute__((unused)))
 
1585
{
 
1586
  struct st_VioSSLFd *ssl_fd= (struct st_VioSSLFd*) mysql->connector_fd;
 
1587
  DBUG_ENTER("mysql_ssl_free");
 
1588
 
 
1589
  my_free(mysql->options.ssl_key, MYF(MY_ALLOW_ZERO_PTR));
 
1590
  my_free(mysql->options.ssl_cert, MYF(MY_ALLOW_ZERO_PTR));
 
1591
  my_free(mysql->options.ssl_ca, MYF(MY_ALLOW_ZERO_PTR));
 
1592
  my_free(mysql->options.ssl_capath, MYF(MY_ALLOW_ZERO_PTR));
 
1593
  my_free(mysql->options.ssl_cipher, MYF(MY_ALLOW_ZERO_PTR));
 
1594
  if (ssl_fd)
 
1595
    SSL_CTX_free(ssl_fd->ssl_context);
 
1596
  my_free(mysql->connector_fd,MYF(MY_ALLOW_ZERO_PTR));
 
1597
  mysql->options.ssl_key = 0;
 
1598
  mysql->options.ssl_cert = 0;
 
1599
  mysql->options.ssl_ca = 0;
 
1600
  mysql->options.ssl_capath = 0;
 
1601
  mysql->options.ssl_cipher= 0;
 
1602
  mysql->options.use_ssl = FALSE;
 
1603
  mysql->connector_fd = 0;
 
1604
  DBUG_VOID_RETURN;
 
1605
}
 
1606
 
 
1607
#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */
 
1608
 
 
1609
/*
 
1610
  Return the SSL cipher (if any) used for current
 
1611
  connection to the server.
 
1612
 
 
1613
  SYNOPSYS
 
1614
    mysql_get_ssl_cipher()
 
1615
      mysql pointer to the mysql connection
 
1616
 
 
1617
*/
 
1618
 
 
1619
const char * STDCALL
 
1620
mysql_get_ssl_cipher(MYSQL *mysql __attribute__((unused)))
 
1621
{
 
1622
  DBUG_ENTER("mysql_get_ssl_cipher");
 
1623
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
 
1624
  if (mysql->net.vio && mysql->net.vio->ssl_arg)
 
1625
    DBUG_RETURN(SSL_get_cipher_name((SSL*)mysql->net.vio->ssl_arg));
 
1626
#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */
 
1627
  DBUG_RETURN(NULL);
 
1628
}
 
1629
 
 
1630
 
 
1631
/*
 
1632
  Check the server's (subject) Common Name against the
 
1633
  hostname we connected to
 
1634
 
 
1635
  SYNOPSIS
 
1636
  ssl_verify_server_cert()
 
1637
    vio              pointer to a SSL connected vio
 
1638
    server_hostname  name of the server that we connected to
 
1639
 
 
1640
  RETURN VALUES
 
1641
   0 Success
 
1642
   1 Failed to validate server
 
1643
 
 
1644
 */
 
1645
 
 
1646
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
 
1647
 
 
1648
static int ssl_verify_server_cert(Vio *vio, const char* server_hostname)
 
1649
{
 
1650
  SSL *ssl;
 
1651
  X509 *server_cert;
 
1652
  char *cp1, *cp2;
 
1653
  char buf[256];
 
1654
  DBUG_ENTER("ssl_verify_server_cert");
 
1655
  DBUG_PRINT("enter", ("server_hostname: %s", server_hostname));
 
1656
 
 
1657
  if (!(ssl= (SSL*)vio->ssl_arg))
 
1658
  {
 
1659
    DBUG_PRINT("error", ("No SSL pointer found"));
 
1660
    DBUG_RETURN(1);
 
1661
  }
 
1662
 
 
1663
  if (!server_hostname)
 
1664
  {
 
1665
    DBUG_PRINT("error", ("No server hostname supplied"));
 
1666
    DBUG_RETURN(1);
 
1667
  }
 
1668
 
 
1669
  if (!(server_cert= SSL_get_peer_certificate(ssl)))
 
1670
  {
 
1671
    DBUG_PRINT("error", ("Could not get server certificate"));
 
1672
    DBUG_RETURN(1);
 
1673
  }
 
1674
 
 
1675
  /*
 
1676
    We already know that the certificate exchanged was valid; the SSL library
 
1677
    handled that. Now we need to verify that the contents of the certificate
 
1678
    are what we expect.
 
1679
  */
 
1680
 
 
1681
  X509_NAME_oneline(X509_get_subject_name(server_cert), buf, sizeof(buf));
 
1682
  X509_free (server_cert);
 
1683
 
 
1684
  DBUG_PRINT("info", ("hostname in cert: %s", buf));
 
1685
  cp1= strstr(buf, "/CN=");
 
1686
  if (cp1)
 
1687
  {
 
1688
    cp1+= 4; /* Skip the "/CN=" that we found */
 
1689
    /* Search for next / which might be the delimiter for email */
 
1690
    cp2= strchr(cp1, '/');
 
1691
    if (cp2)
 
1692
      *cp2= '\0';
 
1693
    DBUG_PRINT("info", ("Server hostname in cert: %s", cp1));
 
1694
    if (!strcmp(cp1, server_hostname))
 
1695
    {
 
1696
      /* Success */
 
1697
      DBUG_RETURN(0);
 
1698
    }
 
1699
  }
 
1700
  DBUG_PRINT("error", ("SSL certificate validation failure"));
 
1701
  DBUG_RETURN(1);
 
1702
}
 
1703
 
 
1704
#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */
 
1705
 
 
1706
 
 
1707
/*
 
1708
  Note that the mysql argument must be initialized with mysql_init()
 
1709
  before calling mysql_real_connect !
 
1710
*/
 
1711
 
 
1712
static my_bool cli_read_query_result(MYSQL *mysql);
 
1713
static MYSQL_RES *cli_use_result(MYSQL *mysql);
 
1714
 
 
1715
static MYSQL_METHODS client_methods=
 
1716
{
 
1717
  cli_read_query_result,                       /* read_query_result */
 
1718
  cli_advanced_command,                        /* advanced_command */
 
1719
  cli_read_rows,                               /* read_rows */
 
1720
  cli_use_result,                              /* use_result */
 
1721
  cli_fetch_lengths,                           /* fetch_lengths */
 
1722
  cli_flush_use_result                         /* flush_use_result */
 
1723
#ifndef MYSQL_SERVER
 
1724
  ,cli_list_fields,                            /* list_fields */
 
1725
  cli_read_prepare_result,                     /* read_prepare_result */
 
1726
  cli_stmt_execute,                            /* stmt_execute */
 
1727
  cli_read_binary_rows,                        /* read_binary_rows */
 
1728
  cli_unbuffered_fetch,                        /* unbuffered_fetch */
 
1729
  NULL,                                        /* free_embedded_thd */
 
1730
  cli_read_statistics,                         /* read_statistics */
 
1731
  cli_read_query_result,                       /* next_result */
 
1732
  cli_read_change_user_result,                 /* read_change_user_result */
 
1733
  cli_read_binary_rows                         /* read_rows_from_cursor */
 
1734
#endif
 
1735
};
 
1736
 
 
1737
C_MODE_START
 
1738
int mysql_init_character_set(MYSQL *mysql)
 
1739
{
 
1740
  const char *default_collation_name;
 
1741
  
 
1742
  /* Set character set */
 
1743
  if (!mysql->options.charset_name)
 
1744
  {
 
1745
    default_collation_name= MYSQL_DEFAULT_COLLATION_NAME;
 
1746
    if (!(mysql->options.charset_name= 
 
1747
       my_strdup(MYSQL_DEFAULT_CHARSET_NAME,MYF(MY_WME))))
 
1748
    return 1;
 
1749
  }
 
1750
  else
 
1751
    default_collation_name= NULL;
 
1752
  
 
1753
  {
 
1754
    const char *save= charsets_dir;
 
1755
    if (mysql->options.charset_dir)
 
1756
      charsets_dir=mysql->options.charset_dir;
 
1757
    mysql->charset=get_charset_by_csname(mysql->options.charset_name,
 
1758
                                         MY_CS_PRIMARY, MYF(MY_WME));
 
1759
    if (mysql->charset && default_collation_name)
 
1760
    {
 
1761
      CHARSET_INFO *collation;
 
1762
      if ((collation= 
 
1763
           get_charset_by_name(default_collation_name, MYF(MY_WME))))
 
1764
      {
 
1765
        if (!my_charset_same(mysql->charset, collation))
 
1766
        {
 
1767
          my_printf_error(ER_UNKNOWN_ERROR, 
 
1768
                         "COLLATION %s is not valid for CHARACTER SET %s",
 
1769
                         MYF(0),
 
1770
                         default_collation_name, mysql->options.charset_name);
 
1771
          mysql->charset= NULL;
 
1772
        }
 
1773
        else
 
1774
        {
 
1775
          mysql->charset= collation;
 
1776
        }
 
1777
      }
 
1778
      else
 
1779
        mysql->charset= NULL;
 
1780
    }
 
1781
    charsets_dir= save;
 
1782
  }
 
1783
 
 
1784
  if (!mysql->charset)
 
1785
  {
 
1786
    if (mysql->options.charset_dir)
 
1787
      set_mysql_extended_error(mysql, CR_CANT_READ_CHARSET, unknown_sqlstate,
 
1788
                               ER(CR_CANT_READ_CHARSET),
 
1789
                               mysql->options.charset_name,
 
1790
                               mysql->options.charset_dir);
 
1791
    else
 
1792
    {
 
1793
      char cs_dir_name[FN_REFLEN];
 
1794
      get_charsets_dir(cs_dir_name);
 
1795
      set_mysql_extended_error(mysql, CR_CANT_READ_CHARSET, unknown_sqlstate,
 
1796
                               ER(CR_CANT_READ_CHARSET),
 
1797
                               mysql->options.charset_name,
 
1798
                               cs_dir_name);
 
1799
    }
 
1800
    return 1;
 
1801
  }
 
1802
  return 0;
 
1803
}
 
1804
C_MODE_END
 
1805
 
 
1806
 
 
1807
MYSQL * STDCALL 
 
1808
CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
 
1809
                       const char *passwd, const char *db,
 
1810
                       uint port, const char *unix_socket,ulong client_flag)
 
1811
{
 
1812
  char          buff[NAME_LEN+USERNAME_LENGTH+100];
 
1813
  char          *end,*host_info;
 
1814
  ulong         pkt_length;
 
1815
  NET           *net= &mysql->net;
 
1816
#ifdef MYSQL_SERVER
 
1817
  thr_alarm_t   alarmed;
 
1818
  ALARM         alarm_buff;
 
1819
#endif
 
1820
#ifdef __WIN__
 
1821
  HANDLE        hPipe=INVALID_HANDLE_VALUE;
 
1822
#endif
 
1823
#ifdef HAVE_SYS_UN_H
 
1824
  struct        sockaddr_un UNIXaddr;
 
1825
#endif
 
1826
  init_sigpipe_variables
 
1827
  DBUG_ENTER("mysql_real_connect");
 
1828
 
 
1829
  DBUG_PRINT("enter",("host: %s  db: %s  user: %s",
 
1830
                      host ? host : "(Null)",
 
1831
                      db ? db : "(Null)",
 
1832
                      user ? user : "(Null)"));
 
1833
 
 
1834
  /* Don't give sigpipe errors if the client doesn't want them */
 
1835
  set_sigpipe(mysql);
 
1836
  mysql->methods= &client_methods;
 
1837
  net->vio = 0;                         /* If something goes wrong */
 
1838
  mysql->client_flag=0;                 /* For handshake */
 
1839
 
 
1840
  /* use default options */
 
1841
  if (mysql->options.my_cnf_file || mysql->options.my_cnf_group)
 
1842
  {
 
1843
    mysql_read_default_options(&mysql->options,
 
1844
                               (mysql->options.my_cnf_file ?
 
1845
                                mysql->options.my_cnf_file : "my"),
 
1846
                               mysql->options.my_cnf_group);
 
1847
    my_free(mysql->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR));
 
1848
    my_free(mysql->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR));
 
1849
    mysql->options.my_cnf_file=mysql->options.my_cnf_group=0;
 
1850
  }
 
1851
 
 
1852
  /* Some empty-string-tests are done because of ODBC */
 
1853
  if (!host || !host[0])
 
1854
    host=mysql->options.host;
 
1855
  if (!user || !user[0])
 
1856
  {
 
1857
    user=mysql->options.user;
 
1858
    if (!user)
 
1859
      user= "";
 
1860
  }
 
1861
  if (!passwd)
 
1862
  {
 
1863
    passwd=mysql->options.password;
 
1864
#if !defined(DONT_USE_MYSQL_PWD) && !defined(MYSQL_SERVER)
 
1865
    if (!passwd)
 
1866
      passwd=getenv("MYSQL_PWD");               /* get it from environment */
 
1867
#endif
 
1868
    if (!passwd)
 
1869
      passwd= "";
 
1870
  }
 
1871
  if (!db || !db[0])
 
1872
    db=mysql->options.db;
 
1873
  if (!port)
 
1874
    port=mysql->options.port;
 
1875
  if (!unix_socket)
 
1876
    unix_socket=mysql->options.unix_socket;
 
1877
 
 
1878
  mysql->server_status=SERVER_STATUS_AUTOCOMMIT;
 
1879
 
 
1880
  /*
 
1881
    Part 0: Grab a socket and connect it to the server
 
1882
  */
 
1883
#if defined(HAVE_SMEM)
 
1884
  if ((!mysql->options.protocol ||
 
1885
       mysql->options.protocol == MYSQL_PROTOCOL_MEMORY) &&
 
1886
      (!host || !strcmp(host,LOCAL_HOST)))
 
1887
  {
 
1888
    if ((create_shared_memory(mysql,net, mysql->options.connect_timeout)) ==
 
1889
        INVALID_HANDLE_VALUE)
 
1890
    {
 
1891
      DBUG_PRINT("error",
 
1892
                 ("host: '%s'  socket: '%s'  shared memory: %s  have_tcpip: %d",
 
1893
                  host ? host : "<null>",
 
1894
                  unix_socket ? unix_socket : "<null>",
 
1895
                  (int) mysql->options.shared_memory_base_name,
 
1896
                  (int) have_tcpip));
 
1897
      if (mysql->options.protocol == MYSQL_PROTOCOL_MEMORY)
 
1898
        goto error;
 
1899
 
 
1900
      /*
 
1901
        Try also with PIPE or TCP/IP. Clear the error from
 
1902
        create_shared_memory().
 
1903
      */
 
1904
 
 
1905
      net_clear_error(net);
 
1906
    }
 
1907
    else
 
1908
    {
 
1909
      mysql->options.protocol=MYSQL_PROTOCOL_MEMORY;
 
1910
      unix_socket = 0;
 
1911
      host=mysql->options.shared_memory_base_name;
 
1912
      my_snprintf(host_info=buff, sizeof(buff)-1,
 
1913
                  ER(CR_SHARED_MEMORY_CONNECTION), host);
 
1914
    }
 
1915
  }
 
1916
#endif /* HAVE_SMEM */
 
1917
#if defined(HAVE_SYS_UN_H)
 
1918
  if (!net->vio &&
 
1919
      (!mysql->options.protocol ||
 
1920
       mysql->options.protocol == MYSQL_PROTOCOL_SOCKET) &&
 
1921
      (unix_socket || mysql_unix_port) &&
 
1922
      (!host || !strcmp(host,LOCAL_HOST)))
 
1923
  {
 
1924
    my_socket sock= socket(AF_UNIX, SOCK_STREAM, 0);
 
1925
    if (sock == SOCKET_ERROR)
 
1926
    {
 
1927
      set_mysql_extended_error(mysql, CR_SOCKET_CREATE_ERROR,
 
1928
                               unknown_sqlstate,
 
1929
                               ER(CR_SOCKET_CREATE_ERROR),
 
1930
                               socket_errno);
 
1931
      goto error;
 
1932
    }
 
1933
 
 
1934
    net->vio= vio_new(sock, VIO_TYPE_SOCKET,
 
1935
                      VIO_LOCALHOST | VIO_BUFFERED_READ);
 
1936
    if (!net->vio)
 
1937
    {
 
1938
      DBUG_PRINT("error",("Unknow protocol %d ", mysql->options.protocol));
 
1939
      set_mysql_error(mysql, CR_CONN_UNKNOW_PROTOCOL, unknown_sqlstate);
 
1940
      closesocket(sock);
 
1941
      goto error;
 
1942
    }
 
1943
 
 
1944
    host= LOCAL_HOST;
 
1945
    if (!unix_socket)
 
1946
      unix_socket= mysql_unix_port;
 
1947
    host_info= (char*) ER(CR_LOCALHOST_CONNECTION);
 
1948
    DBUG_PRINT("info", ("Using UNIX sock '%s'", unix_socket));
 
1949
 
 
1950
    bzero((char*) &UNIXaddr, sizeof(UNIXaddr));
 
1951
    UNIXaddr.sun_family= AF_UNIX;
 
1952
    strmake(UNIXaddr.sun_path, unix_socket, sizeof(UNIXaddr.sun_path)-1);
 
1953
 
 
1954
    if (my_connect(sock, (struct sockaddr *) &UNIXaddr, sizeof(UNIXaddr),
 
1955
                   mysql->options.connect_timeout))
 
1956
    {
 
1957
      DBUG_PRINT("error",("Got error %d on connect to local server",
 
1958
                          socket_errno));
 
1959
      set_mysql_extended_error(mysql, CR_CONNECTION_ERROR,
 
1960
                               unknown_sqlstate,
 
1961
                               ER(CR_CONNECTION_ERROR),
 
1962
                               unix_socket, socket_errno);
 
1963
      vio_delete(net->vio);
 
1964
      net->vio= 0;
 
1965
      goto error;
 
1966
    }
 
1967
    mysql->options.protocol=MYSQL_PROTOCOL_SOCKET;
 
1968
  }
 
1969
#elif defined(__WIN__)
 
1970
  if (!net->vio &&
 
1971
      (mysql->options.protocol == MYSQL_PROTOCOL_PIPE ||
 
1972
       (host && !strcmp(host,LOCAL_HOST_NAMEDPIPE)) ||
 
1973
       (! have_tcpip && (unix_socket || !host && is_NT()))))
 
1974
  {
 
1975
    if ((hPipe= create_named_pipe(mysql, mysql->options.connect_timeout,
 
1976
                                  (char**) &host, (char**) &unix_socket)) ==
 
1977
        INVALID_HANDLE_VALUE)
 
1978
    {
 
1979
      DBUG_PRINT("error",
 
1980
                 ("host: '%s'  socket: '%s'  have_tcpip: %d",
 
1981
                  host ? host : "<null>",
 
1982
                  unix_socket ? unix_socket : "<null>",
 
1983
                  (int) have_tcpip));
 
1984
      if (mysql->options.protocol == MYSQL_PROTOCOL_PIPE ||
 
1985
          (host && !strcmp(host,LOCAL_HOST_NAMEDPIPE)) ||
 
1986
          (unix_socket && !strcmp(unix_socket,MYSQL_NAMEDPIPE)))
 
1987
        goto error;
 
1988
      /* Try also with TCP/IP */
 
1989
    }
 
1990
    else
 
1991
    {
 
1992
      net->vio=vio_new_win32pipe(hPipe);
 
1993
      my_snprintf(host_info=buff, sizeof(buff)-1,
 
1994
                  ER(CR_NAMEDPIPE_CONNECTION), unix_socket);
 
1995
    }
 
1996
  }
 
1997
#endif
 
1998
  if (!net->vio &&
 
1999
      (!mysql->options.protocol ||
 
2000
       mysql->options.protocol == MYSQL_PROTOCOL_TCP))
 
2001
  {
 
2002
    struct addrinfo *res_lst, hints, *t_res;
 
2003
    int gai_errno;
 
2004
    char port_buf[NI_MAXSERV];
 
2005
 
 
2006
    unix_socket=0;                              /* This is not used */
 
2007
 
 
2008
    if (!port)
 
2009
      port= mysql_port;
 
2010
 
 
2011
    if (!host)
 
2012
      host= LOCAL_HOST;
 
2013
 
 
2014
    my_snprintf(host_info=buff, sizeof(buff)-1, ER(CR_TCP_CONNECTION), host);
 
2015
    DBUG_PRINT("info",("Server name: '%s'.  TCP sock: %d", host, port));
 
2016
#ifdef MYSQL_SERVER
 
2017
    thr_alarm_init(&alarmed);
 
2018
    thr_alarm(&alarmed, mysql->options.connect_timeout, &alarm_buff);
 
2019
#endif
 
2020
 
 
2021
    DBUG_PRINT("info",("IP '%s'", "client"));
 
2022
 
 
2023
#ifdef MYSQL_SERVER
 
2024
    thr_end_alarm(&alarmed);
 
2025
#endif
 
2026
 
 
2027
    memset(&hints, 0, sizeof(hints));
 
2028
    hints.ai_socktype= SOCK_STREAM;
 
2029
    hints.ai_protocol= IPPROTO_TCP;
 
2030
    hints.ai_family= AF_UNSPEC;
 
2031
 
 
2032
    DBUG_PRINT("info",("IPV6 getaddrinfo %s", host));
 
2033
    my_snprintf(port_buf, NI_MAXSERV, "%d", port);
 
2034
    gai_errno= getaddrinfo(host, port_buf, &hints, &res_lst);
 
2035
 
 
2036
    if (gai_errno != 0) 
 
2037
    { 
 
2038
      /* 
 
2039
        For DBUG we are keeping the right message but for client we default to
 
2040
        historical error message.
 
2041
      */
 
2042
      DBUG_PRINT("info",("IPV6 getaddrinfo error %d", gai_errno));
 
2043
      set_mysql_extended_error(mysql, CR_UNKNOWN_HOST, unknown_sqlstate,
 
2044
                               ER(CR_UNKNOWN_HOST), host, errno);
 
2045
 
 
2046
      goto error;
 
2047
    }
 
2048
 
 
2049
    /* We only look at the first item (something to think about changing in the future) */
 
2050
    t_res= res_lst; 
 
2051
    {
 
2052
      my_socket sock= socket(t_res->ai_family, t_res->ai_socktype,
 
2053
                             t_res->ai_protocol);
 
2054
      if (sock == SOCKET_ERROR)
 
2055
      {
 
2056
        set_mysql_extended_error(mysql, CR_IPSOCK_ERROR, unknown_sqlstate,
 
2057
                                 ER(CR_IPSOCK_ERROR), socket_errno);
 
2058
        freeaddrinfo(res_lst);
 
2059
        goto error;
 
2060
      }
 
2061
 
 
2062
      net->vio= vio_new(sock, VIO_TYPE_TCPIP, VIO_BUFFERED_READ);
 
2063
      if (! net->vio )
 
2064
      {
 
2065
        DBUG_PRINT("error",("Unknow protocol %d ", mysql->options.protocol));
 
2066
        set_mysql_error(mysql, CR_CONN_UNKNOW_PROTOCOL, unknown_sqlstate);
 
2067
        closesocket(sock);
 
2068
        freeaddrinfo(res_lst);
 
2069
        goto error;
 
2070
      }
 
2071
 
 
2072
      if (my_connect(sock, t_res->ai_addr, t_res->ai_addrlen,
 
2073
                     mysql->options.connect_timeout))
 
2074
      {
 
2075
        DBUG_PRINT("error",("Got error %d on connect to '%s'",socket_errno,
 
2076
                            host));
 
2077
        set_mysql_extended_error(mysql, CR_CONN_HOST_ERROR, unknown_sqlstate,
 
2078
                                 ER(CR_CONN_HOST_ERROR), host, socket_errno);
 
2079
        vio_delete(net->vio);
 
2080
        net->vio= 0;
 
2081
        freeaddrinfo(res_lst);
 
2082
        goto error;
 
2083
      }
 
2084
    }
 
2085
 
 
2086
    freeaddrinfo(res_lst);
 
2087
  }
 
2088
 
 
2089
  if (!net->vio)
 
2090
  {
 
2091
    DBUG_PRINT("error",("Unknow protocol %d ",mysql->options.protocol));
 
2092
    set_mysql_error(mysql, CR_CONN_UNKNOW_PROTOCOL, unknown_sqlstate);
 
2093
    goto error;
 
2094
  }
 
2095
 
 
2096
  if (my_net_init(net, net->vio))
 
2097
  {
 
2098
    vio_delete(net->vio);
 
2099
    net->vio = 0;
 
2100
    set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate);
 
2101
    goto error;
 
2102
  }
 
2103
  vio_keepalive(net->vio,TRUE);
 
2104
 
 
2105
  /* If user set read_timeout, let it override the default */
 
2106
  if (mysql->options.read_timeout)
 
2107
    my_net_set_read_timeout(net, mysql->options.read_timeout);
 
2108
 
 
2109
  /* If user set write_timeout, let it override the default */
 
2110
  if (mysql->options.write_timeout)
 
2111
    my_net_set_write_timeout(net, mysql->options.write_timeout);
 
2112
 
 
2113
  if (mysql->options.max_allowed_packet)
 
2114
    net->max_packet_size= mysql->options.max_allowed_packet;
 
2115
 
 
2116
  /* Get version info */
 
2117
  mysql->protocol_version= PROTOCOL_VERSION;    /* Assume this */
 
2118
  if (mysql->options.connect_timeout &&
 
2119
      vio_poll_read(net->vio, mysql->options.connect_timeout))
 
2120
  {
 
2121
    set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
 
2122
                             ER(CR_SERVER_LOST_EXTENDED),
 
2123
                             "waiting for initial communication packet",
 
2124
                             errno);
 
2125
    goto error;
 
2126
  }
 
2127
 
 
2128
  /*
 
2129
    Part 1: Connection established, read and parse first packet
 
2130
  */
 
2131
 
 
2132
  if ((pkt_length=cli_safe_read(mysql)) == packet_error)
 
2133
  {
 
2134
    if (mysql->net.last_errno == CR_SERVER_LOST)
 
2135
      set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
 
2136
                               ER(CR_SERVER_LOST_EXTENDED),
 
2137
                               "reading initial communication packet",
 
2138
                               errno);
 
2139
    goto error;
 
2140
  }
 
2141
  /* Check if version of protocol matches current one */
 
2142
 
 
2143
  mysql->protocol_version= net->read_pos[0];
 
2144
  DBUG_DUMP("packet",(uchar*) net->read_pos,10);
 
2145
  DBUG_PRINT("info",("mysql protocol version %d, server=%d",
 
2146
                     PROTOCOL_VERSION, mysql->protocol_version));
 
2147
  if (mysql->protocol_version != PROTOCOL_VERSION)
 
2148
  {
 
2149
    set_mysql_extended_error(mysql, CR_VERSION_ERROR, unknown_sqlstate,
 
2150
                             ER(CR_VERSION_ERROR), mysql->protocol_version,
 
2151
                             PROTOCOL_VERSION);
 
2152
    goto error;
 
2153
  }
 
2154
  end=strend((char*) net->read_pos+1);
 
2155
  mysql->thread_id=uint4korr(end+1);
 
2156
  end+=5;
 
2157
  /* 
 
2158
    Scramble is split into two parts because old clients does not understand
 
2159
    long scrambles; here goes the first part.
 
2160
  */
 
2161
  strmake(mysql->scramble, end, SCRAMBLE_LENGTH_323);
 
2162
  end+= SCRAMBLE_LENGTH_323+1;
 
2163
 
 
2164
  if (pkt_length >= (uint) (end+1 - (char*) net->read_pos))
 
2165
    mysql->server_capabilities=uint2korr(end);
 
2166
  if (pkt_length >= (uint) (end+18 - (char*) net->read_pos))
 
2167
  {
 
2168
    /* New protocol with 16 bytes to describe server characteristics */
 
2169
    mysql->server_language=end[2];
 
2170
    mysql->server_status=uint2korr(end+3);
 
2171
  }
 
2172
  end+= 18;
 
2173
  if (pkt_length >= (uint) (end + SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323 + 1 - 
 
2174
                           (char *) net->read_pos))
 
2175
    strmake(mysql->scramble+SCRAMBLE_LENGTH_323, end,
 
2176
            SCRAMBLE_LENGTH-SCRAMBLE_LENGTH_323);
 
2177
  else
 
2178
    mysql->server_capabilities&= ~CLIENT_SECURE_CONNECTION;
 
2179
 
 
2180
  if (mysql->options.secure_auth && passwd[0] &&
 
2181
      !(mysql->server_capabilities & CLIENT_SECURE_CONNECTION))
 
2182
  {
 
2183
    set_mysql_error(mysql, CR_SECURE_AUTH, unknown_sqlstate);
 
2184
    goto error;
 
2185
  }
 
2186
 
 
2187
  if (mysql_init_character_set(mysql))
 
2188
    goto error;
 
2189
 
 
2190
  /* Save connection information */
 
2191
  if (!my_multi_malloc(MYF(0),
 
2192
                       &mysql->host_info, (uint) strlen(host_info)+1,
 
2193
                       &mysql->host,      (uint) strlen(host)+1,
 
2194
                       &mysql->unix_socket,unix_socket ?
 
2195
                       (uint) strlen(unix_socket)+1 : (uint) 1,
 
2196
                       &mysql->server_version,
 
2197
                       (uint) (end - (char*) net->read_pos),
 
2198
                       NullS) ||
 
2199
      !(mysql->user=my_strdup(user,MYF(0))) ||
 
2200
      !(mysql->passwd=my_strdup(passwd,MYF(0))))
 
2201
  {
 
2202
    set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate);
 
2203
    goto error;
 
2204
  }
 
2205
  strmov(mysql->host_info,host_info);
 
2206
  strmov(mysql->host,host);
 
2207
  if (unix_socket)
 
2208
    strmov(mysql->unix_socket,unix_socket);
 
2209
  else
 
2210
    mysql->unix_socket=0;
 
2211
  strmov(mysql->server_version,(char*) net->read_pos+1);
 
2212
  mysql->port=port;
 
2213
 
 
2214
  /*
 
2215
    Part 2: format and send client info to the server for access check
 
2216
  */
 
2217
  
 
2218
  client_flag|=mysql->options.client_flag;
 
2219
  client_flag|=CLIENT_CAPABILITIES;
 
2220
  if (client_flag & CLIENT_MULTI_STATEMENTS)
 
2221
    client_flag|= CLIENT_MULTI_RESULTS;
 
2222
 
 
2223
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
 
2224
  if (mysql->options.ssl_key || mysql->options.ssl_cert ||
 
2225
      mysql->options.ssl_ca || mysql->options.ssl_capath ||
 
2226
      mysql->options.ssl_cipher)
 
2227
    mysql->options.use_ssl= 1;
 
2228
  if (mysql->options.use_ssl)
 
2229
    client_flag|=CLIENT_SSL;
 
2230
#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY*/
 
2231
  if (db)
 
2232
    client_flag|=CLIENT_CONNECT_WITH_DB;
 
2233
 
 
2234
  /* Remove options that server doesn't support */
 
2235
  client_flag= ((client_flag &
 
2236
                 ~(CLIENT_COMPRESS | CLIENT_SSL | CLIENT_PROTOCOL_41)) |
 
2237
                (client_flag & mysql->server_capabilities));
 
2238
  client_flag&= ~CLIENT_COMPRESS;
 
2239
 
 
2240
  if (client_flag & CLIENT_PROTOCOL_41)
 
2241
  {
 
2242
    /* 4.1 server and 4.1 client has a 32 byte option flag */
 
2243
    int4store(buff,client_flag);
 
2244
    int4store(buff+4, net->max_packet_size);
 
2245
    buff[8]= (char) mysql->charset->number;
 
2246
    bzero(buff+9, 32-9);
 
2247
    end= buff+32;
 
2248
  }
 
2249
  else
 
2250
  {
 
2251
    int2store(buff,client_flag);
 
2252
    int3store(buff+2,net->max_packet_size);
 
2253
    end= buff+5;
 
2254
  }
 
2255
  mysql->client_flag=client_flag;
 
2256
 
 
2257
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
 
2258
  if (client_flag & CLIENT_SSL)
 
2259
  {
 
2260
    /* Do the SSL layering. */
 
2261
    struct st_mysql_options *options= &mysql->options;
 
2262
    struct st_VioSSLFd *ssl_fd;
 
2263
 
 
2264
    /*
 
2265
      Send client_flag, max_packet_size - unencrypted otherwise
 
2266
      the server does not know we want to do SSL
 
2267
    */
 
2268
    if (my_net_write(net, (uchar*) buff, (uint) (end-buff)) || net_flush(net))
 
2269
    {
 
2270
      set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
 
2271
                               ER(CR_SERVER_LOST_EXTENDED),
 
2272
                               "sending connection information to server",
 
2273
                               errno);
 
2274
      goto error;
 
2275
    }
 
2276
 
 
2277
    /* Create the VioSSLConnectorFd - init SSL and load certs */
 
2278
    if (!(ssl_fd= new_VioSSLConnectorFd(options->ssl_key,
 
2279
                                        options->ssl_cert,
 
2280
                                        options->ssl_ca,
 
2281
                                        options->ssl_capath,
 
2282
                                        options->ssl_cipher)))
 
2283
    {
 
2284
      set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate);
 
2285
      goto error;
 
2286
    }
 
2287
    mysql->connector_fd= (void*)ssl_fd;
 
2288
 
 
2289
    /* Connect to the server */
 
2290
    DBUG_PRINT("info", ("IO layer change in progress..."));
 
2291
    if (sslconnect(ssl_fd, mysql->net.vio,
 
2292
                   (long) (mysql->options.connect_timeout)))
 
2293
    {
 
2294
      set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate);
 
2295
      goto error;
 
2296
    }
 
2297
    DBUG_PRINT("info", ("IO layer change done!"));
 
2298
 
 
2299
    /* Verify server cert */
 
2300
    if ((client_flag & CLIENT_SSL_VERIFY_SERVER_CERT) &&
 
2301
        ssl_verify_server_cert(mysql->net.vio, mysql->host))
 
2302
    {
 
2303
      set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate);
 
2304
      goto error;
 
2305
    }
 
2306
 
 
2307
  }
 
2308
#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */
 
2309
 
 
2310
  DBUG_PRINT("info",("Server version = '%s'  capabilites: %lu  status: %u  client_flag: %lu",
 
2311
                     mysql->server_version,mysql->server_capabilities,
 
2312
                     mysql->server_status, client_flag));
 
2313
  /* This needs to be changed as it's not useful with big packets */
 
2314
  if (user && user[0])
 
2315
    strmake(end,user,USERNAME_LENGTH);          /* Max user name */
 
2316
  else
 
2317
    read_user_name((char*) end);
 
2318
 
 
2319
  /* We have to handle different version of handshake here */
 
2320
#ifdef _CUSTOMCONFIG_
 
2321
#include "_cust_libmysql.h"
 
2322
#endif
 
2323
  DBUG_PRINT("info",("user: %s",end));
 
2324
  end= strend(end) + 1;
 
2325
  if (passwd[0])
 
2326
  {
 
2327
    if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
 
2328
    {
 
2329
      *end++= SCRAMBLE_LENGTH;
 
2330
      scramble(end, mysql->scramble, passwd);
 
2331
      end+= SCRAMBLE_LENGTH;
 
2332
    }
 
2333
    else
 
2334
    {
 
2335
      scramble_323(end, mysql->scramble, passwd);
 
2336
      end+= SCRAMBLE_LENGTH_323 + 1;
 
2337
    }
 
2338
  }
 
2339
  else
 
2340
    *end++= '\0';                               /* empty password */
 
2341
 
 
2342
  /* Add database if needed */
 
2343
  if (db && (mysql->server_capabilities & CLIENT_CONNECT_WITH_DB))
 
2344
  {
 
2345
    end= strmake(end, db, NAME_LEN) + 1;
 
2346
    mysql->db= my_strdup(db,MYF(MY_WME));
 
2347
    db= 0;
 
2348
  }
 
2349
  /* Write authentication package */
 
2350
  if (my_net_write(net, (uchar*) buff, (size_t) (end-buff)) || net_flush(net))
 
2351
  {
 
2352
    set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
 
2353
                             ER(CR_SERVER_LOST_EXTENDED),
 
2354
                             "sending authentication information",
 
2355
                             errno);
 
2356
    goto error;
 
2357
  }
 
2358
  
 
2359
  /*
 
2360
    Part 3: Authorization data's been sent. Now server can reply with
 
2361
    OK-packet, or re-request scrambled password.
 
2362
  */
 
2363
 
 
2364
  if ((pkt_length=cli_safe_read(mysql)) == packet_error)
 
2365
  {
 
2366
    if (mysql->net.last_errno == CR_SERVER_LOST)
 
2367
      set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
 
2368
                               ER(CR_SERVER_LOST_EXTENDED),
 
2369
                               "reading authorization packet",
 
2370
                               errno);
 
2371
    goto error;
 
2372
  }
 
2373
 
 
2374
  if (pkt_length == 1 && net->read_pos[0] == 254 && 
 
2375
      mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
 
2376
  {
 
2377
    /*
 
2378
      By sending this very specific reply server asks us to send scrambled
 
2379
      password in old format.
 
2380
    */
 
2381
    scramble_323(buff, mysql->scramble, passwd);
 
2382
    if (my_net_write(net, (uchar*) buff, SCRAMBLE_LENGTH_323 + 1) ||
 
2383
        net_flush(net))
 
2384
    {
 
2385
      set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
 
2386
                               ER(CR_SERVER_LOST_EXTENDED),
 
2387
                               "sending password information",
 
2388
                               errno);
 
2389
      goto error;
 
2390
    }
 
2391
    /* Read what server thinks about out new auth message report */
 
2392
    if (cli_safe_read(mysql) == packet_error)
 
2393
    {
 
2394
      if (mysql->net.last_errno == CR_SERVER_LOST)
 
2395
        set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
 
2396
                                 ER(CR_SERVER_LOST_EXTENDED),
 
2397
                                 "reading final connect information",
 
2398
                                 errno);
 
2399
      goto error;
 
2400
    }
 
2401
  }
 
2402
 
 
2403
  if (client_flag & CLIENT_COMPRESS)            /* We will use compression */
 
2404
    net->compress=1;
 
2405
 
 
2406
#ifdef CHECK_LICENSE 
 
2407
  if (check_license(mysql))
 
2408
    goto error;
 
2409
#endif
 
2410
 
 
2411
  if (db && mysql_select_db(mysql, db))
 
2412
  {
 
2413
    if (mysql->net.last_errno == CR_SERVER_LOST)
 
2414
        set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
 
2415
                                 ER(CR_SERVER_LOST_EXTENDED),
 
2416
                                 "Setting intital database",
 
2417
                                 errno);
 
2418
    goto error;
 
2419
  }
 
2420
 
 
2421
  if (mysql->options.init_commands)
 
2422
  {
 
2423
    DYNAMIC_ARRAY *init_commands= mysql->options.init_commands;
 
2424
    char **ptr= (char**)init_commands->buffer;
 
2425
    char **end_command= ptr + init_commands->elements;
 
2426
 
 
2427
    my_bool reconnect=mysql->reconnect;
 
2428
    mysql->reconnect=0;
 
2429
 
 
2430
    for (; ptr < end_command; ptr++)
 
2431
    {
 
2432
      MYSQL_RES *res;
 
2433
      if (mysql_real_query(mysql,*ptr, (ulong) strlen(*ptr)))
 
2434
        goto error;
 
2435
      if (mysql->fields)
 
2436
      {
 
2437
        if (!(res= cli_use_result(mysql)))
 
2438
          goto error;
 
2439
        mysql_free_result(res);
 
2440
      }
 
2441
    }
 
2442
    mysql->reconnect=reconnect;
 
2443
  }
 
2444
 
 
2445
  DBUG_PRINT("exit", ("Mysql handler: 0x%lx", (long) mysql));
 
2446
  reset_sigpipe(mysql);
 
2447
  DBUG_RETURN(mysql);
 
2448
 
 
2449
error:
 
2450
  reset_sigpipe(mysql);
 
2451
  DBUG_PRINT("error",("message: %u/%s (%s)",
 
2452
                      net->last_errno,
 
2453
                      net->sqlstate,
 
2454
                      net->last_error));
 
2455
  {
 
2456
    /* Free alloced memory */
 
2457
    end_server(mysql);
 
2458
    mysql_close_free(mysql);
 
2459
    if (!(((ulong) client_flag) & CLIENT_REMEMBER_OPTIONS))
 
2460
      mysql_close_free_options(mysql);
 
2461
  }
 
2462
  DBUG_RETURN(0);
 
2463
}
 
2464
 
 
2465
 
 
2466
my_bool mysql_reconnect(MYSQL *mysql)
 
2467
{
 
2468
  MYSQL tmp_mysql;
 
2469
  DBUG_ENTER("mysql_reconnect");
 
2470
  DBUG_ASSERT(mysql);
 
2471
  DBUG_PRINT("enter", ("mysql->reconnect: %d", mysql->reconnect));
 
2472
 
 
2473
  if (!mysql->reconnect ||
 
2474
      (mysql->server_status & SERVER_STATUS_IN_TRANS) || !mysql->host_info)
 
2475
  {
 
2476
    /* Allow reconnect next time */
 
2477
    mysql->server_status&= ~SERVER_STATUS_IN_TRANS;
 
2478
    set_mysql_error(mysql, CR_SERVER_GONE_ERROR, unknown_sqlstate);
 
2479
    DBUG_RETURN(1);
 
2480
  }
 
2481
  mysql_init(&tmp_mysql);
 
2482
  tmp_mysql.options= mysql->options;
 
2483
  tmp_mysql.options.my_cnf_file= tmp_mysql.options.my_cnf_group= 0;
 
2484
 
 
2485
  if (!mysql_real_connect(&tmp_mysql,mysql->host,mysql->user,mysql->passwd,
 
2486
                          mysql->db, mysql->port, mysql->unix_socket,
 
2487
                          mysql->client_flag | CLIENT_REMEMBER_OPTIONS))
 
2488
  {
 
2489
    mysql->net.last_errno= tmp_mysql.net.last_errno;
 
2490
    strmov(mysql->net.last_error, tmp_mysql.net.last_error);
 
2491
    strmov(mysql->net.sqlstate, tmp_mysql.net.sqlstate);
 
2492
    DBUG_RETURN(1);
 
2493
  }
 
2494
  if (mysql_set_character_set(&tmp_mysql, mysql->charset->csname))
 
2495
  {
 
2496
    DBUG_PRINT("error", ("mysql_set_character_set() failed"));
 
2497
    bzero((char*) &tmp_mysql.options,sizeof(tmp_mysql.options));
 
2498
    mysql_close(&tmp_mysql);
 
2499
    mysql->net.last_errno= tmp_mysql.net.last_errno;
 
2500
    strmov(mysql->net.last_error, tmp_mysql.net.last_error);
 
2501
    strmov(mysql->net.sqlstate, tmp_mysql.net.sqlstate);
 
2502
    DBUG_RETURN(1);
 
2503
  }
 
2504
 
 
2505
  DBUG_PRINT("info", ("reconnect succeded"));
 
2506
  tmp_mysql.reconnect= 1;
 
2507
  tmp_mysql.free_me= mysql->free_me;
 
2508
 
 
2509
  /*
 
2510
    For each stmt in mysql->stmts, move it to tmp_mysql if it is
 
2511
    in state MYSQL_STMT_INIT_DONE, otherwise close it.
 
2512
  */
 
2513
  {
 
2514
    LIST *element= mysql->stmts;
 
2515
    for (; element; element= element->next)
 
2516
    {
 
2517
      MYSQL_STMT *stmt= (MYSQL_STMT *) element->data;
 
2518
      if (stmt->state != MYSQL_STMT_INIT_DONE)
 
2519
      {
 
2520
        stmt->mysql= 0;
 
2521
        stmt->last_errno= CR_SERVER_LOST;
 
2522
        strmov(stmt->last_error, ER(CR_SERVER_LOST));
 
2523
        strmov(stmt->sqlstate, unknown_sqlstate);
 
2524
      }
 
2525
      else
 
2526
      {
 
2527
        tmp_mysql.stmts= list_add(tmp_mysql.stmts, &stmt->list);
 
2528
      }
 
2529
      /* No need to call list_delete for statement here */
 
2530
    }
 
2531
    mysql->stmts= NULL;
 
2532
  }
 
2533
 
 
2534
  /* Don't free options as these are now used in tmp_mysql */
 
2535
  bzero((char*) &mysql->options,sizeof(mysql->options));
 
2536
  mysql->free_me=0;
 
2537
  mysql_close(mysql);
 
2538
  *mysql=tmp_mysql;
 
2539
  net_clear(&mysql->net, 1);
 
2540
  mysql->affected_rows= ~(my_ulonglong) 0;
 
2541
  DBUG_RETURN(0);
 
2542
}
 
2543
 
 
2544
 
 
2545
/**************************************************************************
 
2546
  Set current database
 
2547
**************************************************************************/
 
2548
 
 
2549
int STDCALL
 
2550
mysql_select_db(MYSQL *mysql, const char *db)
 
2551
{
 
2552
  int error;
 
2553
  DBUG_ENTER("mysql_select_db");
 
2554
  DBUG_PRINT("enter",("db: '%s'",db));
 
2555
 
 
2556
  if ((error=simple_command(mysql,COM_INIT_DB, (const uchar*) db,
 
2557
                            (ulong) strlen(db),0)))
 
2558
    DBUG_RETURN(error);
 
2559
  my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR));
 
2560
  mysql->db=my_strdup(db,MYF(MY_WME));
 
2561
  DBUG_RETURN(0);
 
2562
}
 
2563
 
 
2564
 
 
2565
/*************************************************************************
 
2566
  Send a QUIT to the server and close the connection
 
2567
  If handle is alloced by mysql connect free it.
 
2568
*************************************************************************/
 
2569
 
 
2570
static void mysql_close_free_options(MYSQL *mysql)
 
2571
{
 
2572
  DBUG_ENTER("mysql_close_free_options");
 
2573
 
 
2574
  my_free(mysql->options.user,MYF(MY_ALLOW_ZERO_PTR));
 
2575
  my_free(mysql->options.host,MYF(MY_ALLOW_ZERO_PTR));
 
2576
  my_free(mysql->options.password,MYF(MY_ALLOW_ZERO_PTR));
 
2577
  my_free(mysql->options.unix_socket,MYF(MY_ALLOW_ZERO_PTR));
 
2578
  my_free(mysql->options.db,MYF(MY_ALLOW_ZERO_PTR));
 
2579
  my_free(mysql->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR));
 
2580
  my_free(mysql->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR));
 
2581
  my_free(mysql->options.charset_dir,MYF(MY_ALLOW_ZERO_PTR));
 
2582
  my_free(mysql->options.charset_name,MYF(MY_ALLOW_ZERO_PTR));
 
2583
  my_free(mysql->options.client_ip,MYF(MY_ALLOW_ZERO_PTR));
 
2584
  if (mysql->options.init_commands)
 
2585
  {
 
2586
    DYNAMIC_ARRAY *init_commands= mysql->options.init_commands;
 
2587
    char **ptr= (char**)init_commands->buffer;
 
2588
    char **end= ptr + init_commands->elements;
 
2589
    for (; ptr<end; ptr++)
 
2590
      my_free(*ptr,MYF(MY_WME));
 
2591
    delete_dynamic(init_commands);
 
2592
    my_free((char*)init_commands,MYF(MY_WME));
 
2593
  }
 
2594
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
 
2595
  mysql_ssl_free(mysql);
 
2596
#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */
 
2597
#ifdef HAVE_SMEM
 
2598
  if (mysql->options.shared_memory_base_name != def_shared_memory_base_name)
 
2599
    my_free(mysql->options.shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
 
2600
#endif /* HAVE_SMEM */
 
2601
  bzero((char*) &mysql->options,sizeof(mysql->options));
 
2602
  DBUG_VOID_RETURN;
 
2603
}
 
2604
 
 
2605
 
 
2606
static void mysql_close_free(MYSQL *mysql)
 
2607
{
 
2608
  my_free((uchar*) mysql->host_info,MYF(MY_ALLOW_ZERO_PTR));
 
2609
  my_free(mysql->user,MYF(MY_ALLOW_ZERO_PTR));
 
2610
  my_free(mysql->passwd,MYF(MY_ALLOW_ZERO_PTR));
 
2611
  my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR));
 
2612
#if defined(EMBEDDED_LIBRARY) || MYSQL_VERSION_ID >= 50100
 
2613
  my_free(mysql->info_buffer,MYF(MY_ALLOW_ZERO_PTR));
 
2614
  mysql->info_buffer= 0;
 
2615
#endif
 
2616
  /* Clear pointers for better safety */
 
2617
  mysql->host_info= mysql->user= mysql->passwd= mysql->db= 0;
 
2618
}
 
2619
 
 
2620
 
 
2621
/*
 
2622
  Clear connection pointer of every statement: this is necessary
 
2623
  to give error on attempt to use a prepared statement of closed
 
2624
  connection.
 
2625
 
 
2626
  SYNOPSYS
 
2627
    mysql_detach_stmt_list()
 
2628
      stmt_list  pointer to mysql->stmts
 
2629
      func_name  name of calling function
 
2630
 
 
2631
  NOTE
 
2632
    There is similar code in mysql_reconnect(), so changes here
 
2633
    should also be reflected there.
 
2634
*/
 
2635
 
 
2636
void mysql_detach_stmt_list(LIST **stmt_list __attribute__((unused)),
 
2637
                            const char *func_name __attribute__((unused)))
 
2638
{
 
2639
#ifdef MYSQL_CLIENT
 
2640
  /* Reset connection handle in all prepared statements. */
 
2641
  LIST *element= *stmt_list;
 
2642
  char buff[MYSQL_ERRMSG_SIZE];
 
2643
  DBUG_ENTER("mysql_detach_stmt_list");
 
2644
 
 
2645
  my_snprintf(buff, sizeof(buff)-1, ER(CR_STMT_CLOSED), func_name);
 
2646
  for (; element; element= element->next)
 
2647
  {
 
2648
    MYSQL_STMT *stmt= (MYSQL_STMT *) element->data;
 
2649
    set_stmt_error(stmt, CR_STMT_CLOSED, unknown_sqlstate, buff);
 
2650
    stmt->mysql= 0;
 
2651
    /* No need to call list_delete for statement here */
 
2652
  }
 
2653
  *stmt_list= 0;
 
2654
  DBUG_VOID_RETURN;
 
2655
#endif /* MYSQL_CLIENT */
 
2656
}
 
2657
 
 
2658
 
 
2659
void STDCALL mysql_close(MYSQL *mysql)
 
2660
{
 
2661
  DBUG_ENTER("mysql_close");
 
2662
  if (mysql)                                    /* Some simple safety */
 
2663
  {
 
2664
    /* If connection is still up, send a QUIT message */
 
2665
    if (mysql->net.vio != 0)
 
2666
    {
 
2667
      free_old_query(mysql);
 
2668
      mysql->status=MYSQL_STATUS_READY; /* Force command */
 
2669
      mysql->reconnect=0;
 
2670
      simple_command(mysql,COM_QUIT,(uchar*) 0,0,1);
 
2671
      end_server(mysql);                        /* Sets mysql->net.vio= 0 */
 
2672
    }
 
2673
    mysql_close_free_options(mysql);
 
2674
    mysql_close_free(mysql);
 
2675
    mysql_detach_stmt_list(&mysql->stmts, "mysql_close");
 
2676
#ifndef MYSQL_SERVER
 
2677
    if (mysql->thd)
 
2678
      (*mysql->methods->free_embedded_thd)(mysql);
 
2679
#endif
 
2680
    if (mysql->free_me)
 
2681
      my_free((uchar*) mysql,MYF(0));
 
2682
  }
 
2683
  DBUG_VOID_RETURN;
 
2684
}
 
2685
 
 
2686
 
 
2687
static my_bool cli_read_query_result(MYSQL *mysql)
 
2688
{
 
2689
  uchar *pos;
 
2690
  ulong field_count;
 
2691
  MYSQL_DATA *fields;
 
2692
  ulong length;
 
2693
  DBUG_ENTER("cli_read_query_result");
 
2694
 
 
2695
  if ((length = cli_safe_read(mysql)) == packet_error)
 
2696
    DBUG_RETURN(1);
 
2697
  free_old_query(mysql);                /* Free old result */
 
2698
#ifdef MYSQL_CLIENT                     /* Avoid warn of unused labels*/
 
2699
get_info:
 
2700
#endif
 
2701
  pos=(uchar*) mysql->net.read_pos;
 
2702
  if ((field_count= net_field_length(&pos)) == 0)
 
2703
  {
 
2704
    mysql->affected_rows= net_field_length_ll(&pos);
 
2705
    mysql->insert_id=     net_field_length_ll(&pos);
 
2706
    DBUG_PRINT("info",("affected_rows: %lu  insert_id: %lu",
 
2707
                       (ulong) mysql->affected_rows,
 
2708
                       (ulong) mysql->insert_id));
 
2709
    if (protocol_41(mysql))
 
2710
    {
 
2711
      mysql->server_status=uint2korr(pos); pos+=2;
 
2712
      mysql->warning_count=uint2korr(pos); pos+=2;
 
2713
    }
 
2714
    else if (mysql->server_capabilities & CLIENT_TRANSACTIONS)
 
2715
    {
 
2716
      /* MySQL 4.0 protocol */
 
2717
      mysql->server_status=uint2korr(pos); pos+=2;
 
2718
      mysql->warning_count= 0;
 
2719
    }
 
2720
    DBUG_PRINT("info",("status: %u  warning_count: %u",
 
2721
                       mysql->server_status, mysql->warning_count));
 
2722
    if (pos < mysql->net.read_pos+length && net_field_length(&pos))
 
2723
      mysql->info=(char*) pos;
 
2724
    DBUG_RETURN(0);
 
2725
  }
 
2726
#ifdef MYSQL_CLIENT
 
2727
  if (field_count == NULL_LENGTH)               /* LOAD DATA LOCAL INFILE */
 
2728
  {
 
2729
    int error;
 
2730
 
 
2731
    if (!(mysql->options.client_flag & CLIENT_LOCAL_FILES))
 
2732
    {
 
2733
      set_mysql_error(mysql, CR_MALFORMED_PACKET, unknown_sqlstate);
 
2734
      DBUG_RETURN(1);
 
2735
    }   
 
2736
 
 
2737
    error= handle_local_infile(mysql,(char*) pos);
 
2738
    if ((length= cli_safe_read(mysql)) == packet_error || error)
 
2739
      DBUG_RETURN(1);
 
2740
    goto get_info;                              /* Get info packet */
 
2741
  }
 
2742
#endif
 
2743
  if (!(mysql->server_status & SERVER_STATUS_AUTOCOMMIT))
 
2744
    mysql->server_status|= SERVER_STATUS_IN_TRANS;
 
2745
 
 
2746
  if (!(fields=cli_read_rows(mysql,(MYSQL_FIELD*)0, protocol_41(mysql) ? 7:5)))
 
2747
    DBUG_RETURN(1);
 
2748
  if (!(mysql->fields=unpack_fields(fields,&mysql->field_alloc,
 
2749
                                    (uint) field_count,0,
 
2750
                                    mysql->server_capabilities)))
 
2751
    DBUG_RETURN(1);
 
2752
  mysql->status= MYSQL_STATUS_GET_RESULT;
 
2753
  mysql->field_count= (uint) field_count;
 
2754
  DBUG_PRINT("exit",("ok"));
 
2755
  DBUG_RETURN(0);
 
2756
}
 
2757
 
 
2758
 
 
2759
/*
 
2760
  Send the query and return so we can do something else.
 
2761
  Needs to be followed by mysql_read_query_result() when we want to
 
2762
  finish processing it.
 
2763
*/
 
2764
 
 
2765
int STDCALL
 
2766
mysql_send_query(MYSQL* mysql, const char* query, ulong length)
 
2767
{
 
2768
  DBUG_ENTER("mysql_send_query");
 
2769
  DBUG_RETURN(simple_command(mysql, COM_QUERY, (uchar*) query, length, 1));
 
2770
}
 
2771
 
 
2772
 
 
2773
int STDCALL
 
2774
mysql_real_query(MYSQL *mysql, const char *query, ulong length)
 
2775
{
 
2776
  DBUG_ENTER("mysql_real_query");
 
2777
  DBUG_PRINT("enter",("handle: 0x%lx", (long) mysql));
 
2778
  DBUG_PRINT("query",("Query = '%-.4096s'",query));
 
2779
 
 
2780
  if (mysql_send_query(mysql,query,length))
 
2781
    DBUG_RETURN(1);
 
2782
  DBUG_RETURN((int) (*mysql->methods->read_query_result)(mysql));
 
2783
}
 
2784
 
 
2785
 
 
2786
/**************************************************************************
 
2787
  Alloc result struct for buffered results. All rows are read to buffer.
 
2788
  mysql_data_seek may be used.
 
2789
**************************************************************************/
 
2790
 
 
2791
MYSQL_RES * STDCALL mysql_store_result(MYSQL *mysql)
 
2792
{
 
2793
  MYSQL_RES *result;
 
2794
  DBUG_ENTER("mysql_store_result");
 
2795
 
 
2796
  if (!mysql->fields)
 
2797
    DBUG_RETURN(0);
 
2798
  if (mysql->status != MYSQL_STATUS_GET_RESULT)
 
2799
  {
 
2800
    set_mysql_error(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
 
2801
    DBUG_RETURN(0);
 
2802
  }
 
2803
  mysql->status=MYSQL_STATUS_READY;             /* server is ready */
 
2804
  if (!(result=(MYSQL_RES*) my_malloc((uint) (sizeof(MYSQL_RES)+
 
2805
                                              sizeof(ulong) *
 
2806
                                              mysql->field_count),
 
2807
                                      MYF(MY_WME | MY_ZEROFILL))))
 
2808
  {
 
2809
    set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate);
 
2810
    DBUG_RETURN(0);
 
2811
  }
 
2812
  result->methods= mysql->methods;
 
2813
  result->eof=1;                                /* Marker for buffered */
 
2814
  result->lengths=(ulong*) (result+1);
 
2815
  if (!(result->data=
 
2816
        (*mysql->methods->read_rows)(mysql,mysql->fields,mysql->field_count)))
 
2817
  {
 
2818
    my_free((uchar*) result,MYF(0));
 
2819
    DBUG_RETURN(0);
 
2820
  }
 
2821
  mysql->affected_rows= result->row_count= result->data->rows;
 
2822
  result->data_cursor=  result->data->data;
 
2823
  result->fields=       mysql->fields;
 
2824
  result->field_alloc=  mysql->field_alloc;
 
2825
  result->field_count=  mysql->field_count;
 
2826
  /* The rest of result members is bzeroed in malloc */
 
2827
  mysql->fields=0;                              /* fields is now in result */
 
2828
  clear_alloc_root(&mysql->field_alloc);
 
2829
  /* just in case this was mistakenly called after mysql_stmt_execute() */
 
2830
  mysql->unbuffered_fetch_owner= 0;
 
2831
  DBUG_RETURN(result);                          /* Data fetched */
 
2832
}
 
2833
 
 
2834
 
 
2835
/**************************************************************************
 
2836
  Alloc struct for use with unbuffered reads. Data is fetched by domand
 
2837
  when calling to mysql_fetch_row.
 
2838
  mysql_data_seek is a noop.
 
2839
 
 
2840
  No other queries may be specified with the same MYSQL handle.
 
2841
  There shouldn't be much processing per row because mysql server shouldn't
 
2842
  have to wait for the client (and will not wait more than 30 sec/packet).
 
2843
**************************************************************************/
 
2844
 
 
2845
static MYSQL_RES * cli_use_result(MYSQL *mysql)
 
2846
{
 
2847
  MYSQL_RES *result;
 
2848
  DBUG_ENTER("cli_use_result");
 
2849
 
 
2850
  if (!mysql->fields)
 
2851
    DBUG_RETURN(0);
 
2852
  if (mysql->status != MYSQL_STATUS_GET_RESULT)
 
2853
  {
 
2854
    set_mysql_error(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
 
2855
    DBUG_RETURN(0);
 
2856
  }
 
2857
  if (!(result=(MYSQL_RES*) my_malloc(sizeof(*result)+
 
2858
                                      sizeof(ulong)*mysql->field_count,
 
2859
                                      MYF(MY_WME | MY_ZEROFILL))))
 
2860
    DBUG_RETURN(0);
 
2861
  result->lengths=(ulong*) (result+1);
 
2862
  result->methods= mysql->methods;
 
2863
  if (!(result->row=(MYSQL_ROW)
 
2864
        my_malloc(sizeof(result->row[0])*(mysql->field_count+1), MYF(MY_WME))))
 
2865
  {                                     /* Ptrs: to one row */
 
2866
    my_free((uchar*) result,MYF(0));
 
2867
    DBUG_RETURN(0);
 
2868
  }
 
2869
  result->fields=       mysql->fields;
 
2870
  result->field_alloc=  mysql->field_alloc;
 
2871
  result->field_count=  mysql->field_count;
 
2872
  result->current_field=0;
 
2873
  result->handle=       mysql;
 
2874
  result->current_row=  0;
 
2875
  mysql->fields=0;                      /* fields is now in result */
 
2876
  clear_alloc_root(&mysql->field_alloc);
 
2877
  mysql->status=MYSQL_STATUS_USE_RESULT;
 
2878
  mysql->unbuffered_fetch_owner= &result->unbuffered_fetch_cancelled;
 
2879
  DBUG_RETURN(result);                  /* Data is read to be fetched */
428
2880
}
429
2881
 
430
2882
 
432
2884
  Return next row of the query results
433
2885
**************************************************************************/
434
2886
 
435
 
DRIZZLE_ROW
436
 
drizzle_fetch_row(DRIZZLE_RES *res)
 
2887
MYSQL_ROW STDCALL
 
2888
mysql_fetch_row(MYSQL_RES *res)
437
2889
{
 
2890
  DBUG_ENTER("mysql_fetch_row");
438
2891
  if (!res->data)
439
 
  {            /* Unbufferred fetch */
 
2892
  {                                             /* Unbufferred fetch */
440
2893
    if (!res->eof)
441
2894
    {
442
 
      DRIZZLE *drizzle= res->handle;
443
 
      if (drizzle->status != DRIZZLE_STATUS_USE_RESULT)
444
 
      {
445
 
        drizzle_set_error(drizzle,
446
 
                          res->unbuffered_fetch_cancelled ?
447
 
                          CR_FETCH_CANCELED : CR_COMMANDS_OUT_OF_SYNC,
448
 
                          sqlstate_get_unknown());
449
 
      }
450
 
      else if (!(read_one_row(drizzle, res->field_count, res->row, res->lengths)))
451
 
      {
452
 
  res->row_count++;
453
 
  return(res->current_row=res->row);
454
 
      }
 
2895
      MYSQL *mysql= res->handle;
 
2896
      if (mysql->status != MYSQL_STATUS_USE_RESULT)
 
2897
      {
 
2898
        set_mysql_error(mysql,
 
2899
                        res->unbuffered_fetch_cancelled ? 
 
2900
                        CR_FETCH_CANCELED : CR_COMMANDS_OUT_OF_SYNC,
 
2901
                        unknown_sqlstate);
 
2902
      }
 
2903
      else if (!(read_one_row(mysql, res->field_count, res->row, res->lengths)))
 
2904
      {
 
2905
        res->row_count++;
 
2906
        DBUG_RETURN(res->current_row=res->row);
 
2907
      }
 
2908
      DBUG_PRINT("info",("end of data"));
455
2909
      res->eof=1;
456
 
      drizzle->status=DRIZZLE_STATUS_READY;
 
2910
      mysql->status=MYSQL_STATUS_READY;
457
2911
      /*
458
2912
        Reset only if owner points to us: there is a chance that somebody
459
 
        started new query after drizzle_stmt_close():
 
2913
        started new query after mysql_stmt_close():
460
2914
      */
461
 
      if (drizzle->unbuffered_fetch_owner == &res->unbuffered_fetch_cancelled)
462
 
        drizzle->unbuffered_fetch_owner= 0;
463
 
      /* Don't clear handle in drizzle_free_result */
 
2915
      if (mysql->unbuffered_fetch_owner == &res->unbuffered_fetch_cancelled)
 
2916
        mysql->unbuffered_fetch_owner= 0;
 
2917
      /* Don't clear handle in mysql_free_result */
464
2918
      res->handle=0;
465
2919
    }
466
 
    return((DRIZZLE_ROW) NULL);
 
2920
    DBUG_RETURN((MYSQL_ROW) NULL);
467
2921
  }
468
2922
  {
469
 
    DRIZZLE_ROW tmp;
 
2923
    MYSQL_ROW tmp;
470
2924
    if (!res->data_cursor)
471
2925
    {
472
 
      return(res->current_row=(DRIZZLE_ROW) NULL);
 
2926
      DBUG_PRINT("info",("end of data"));
 
2927
      DBUG_RETURN(res->current_row=(MYSQL_ROW) NULL);
473
2928
    }
474
2929
    tmp = res->data_cursor->data;
475
2930
    res->data_cursor = res->data_cursor->next;
476
 
    return(res->current_row=tmp);
 
2931
    DBUG_RETURN(res->current_row=tmp);
477
2932
  }
478
2933
}
479
2934
 
480
2935
 
481
2936
/**************************************************************************
482
2937
  Get column lengths of the current row
483
 
  If one uses drizzle_use_result, res->lengths contains the length information,
 
2938
  If one uses mysql_use_result, res->lengths contains the length information,
484
2939
  else the lengths are calculated from the offset between pointers.
485
2940
**************************************************************************/
486
2941
 
487
 
uint32_t *
488
 
drizzle_fetch_lengths(DRIZZLE_RES *res)
 
2942
ulong * STDCALL
 
2943
mysql_fetch_lengths(MYSQL_RES *res)
489
2944
{
490
 
  DRIZZLE_ROW column;
 
2945
  MYSQL_ROW column;
491
2946
 
492
2947
  if (!(column=res->current_row))
493
 
    return 0;          /* Something is wrong */
 
2948
    return 0;                                   /* Something is wrong */
494
2949
  if (res->data)
495
2950
    (*res->methods->fetch_lengths)(res->lengths, column, res->field_count);
496
2951
  return res->lengths;
497
2952
}
498
2953
 
499
2954
 
500
 
int
501
 
drizzle_options(DRIZZLE *drizzle,enum drizzle_option option, const void *arg)
 
2955
int STDCALL
 
2956
mysql_options(MYSQL *mysql,enum mysql_option option, const void *arg)
502
2957
{
 
2958
  DBUG_ENTER("mysql_option");
 
2959
  DBUG_PRINT("enter",("option: %d",(int) option));
503
2960
  switch (option) {
504
 
  case DRIZZLE_OPT_CONNECT_TIMEOUT:
505
 
    drizzle->options.connect_timeout= *(uint32_t*) arg;
506
 
    break;
507
 
  case DRIZZLE_OPT_READ_TIMEOUT:
508
 
    drizzle->options.read_timeout= *(uint32_t*) arg;
509
 
    break;
510
 
  case DRIZZLE_OPT_WRITE_TIMEOUT:
511
 
    drizzle->options.write_timeout= *(uint32_t*) arg;
512
 
    break;
513
 
  case DRIZZLE_OPT_COMPRESS:
514
 
    drizzle->options.compress= 1;      /* Remember for connect */
515
 
    drizzle->options.client_flag|= CLIENT_COMPRESS;
516
 
    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
 
  case DRIZZLE_READ_DEFAULT_FILE:
524
 
    if (drizzle->options.my_cnf_file != NULL)
525
 
      free(drizzle->options.my_cnf_file);
526
 
    drizzle->options.my_cnf_file=strdup(arg);
527
 
    break;
528
 
  case DRIZZLE_READ_DEFAULT_GROUP:
529
 
    if (drizzle->options.my_cnf_group != NULL)
530
 
      free(drizzle->options.my_cnf_group);
531
 
    drizzle->options.my_cnf_group=strdup(arg);
532
 
    break;
533
 
  case DRIZZLE_OPT_PROTOCOL:
534
 
    break;
535
 
  case DRIZZLE_OPT_USE_REMOTE_CONNECTION:
536
 
  case DRIZZLE_OPT_GUESS_CONNECTION:
537
 
    drizzle->options.methods_to_use= option;
538
 
    break;
539
 
  case DRIZZLE_SET_CLIENT_IP:
540
 
    drizzle->options.client_ip= strdup(arg);
541
 
    break;
542
 
  case DRIZZLE_SECURE_AUTH:
543
 
    drizzle->options.secure_auth= *(const bool *) arg;
544
 
    break;
545
 
  case DRIZZLE_REPORT_DATA_TRUNCATION:
546
 
    drizzle->options.report_data_truncation= (*(const bool *) arg) ? 1 : 0;
547
 
    break;
548
 
  case DRIZZLE_OPT_RECONNECT:
549
 
    drizzle->reconnect= *(const bool *) arg;
550
 
    break;
551
 
  case DRIZZLE_OPT_SSL_VERIFY_SERVER_CERT:
552
 
    if (*(const bool*) arg)
553
 
      drizzle->options.client_flag|= CLIENT_SSL_VERIFY_SERVER_CERT;
554
 
    else
555
 
      drizzle->options.client_flag&= ~CLIENT_SSL_VERIFY_SERVER_CERT;
 
2961
  case MYSQL_OPT_CONNECT_TIMEOUT:
 
2962
    mysql->options.connect_timeout= *(uint*) arg;
 
2963
    break;
 
2964
  case MYSQL_OPT_READ_TIMEOUT:
 
2965
    mysql->options.read_timeout= *(uint*) arg;
 
2966
    break;
 
2967
  case MYSQL_OPT_WRITE_TIMEOUT:
 
2968
    mysql->options.write_timeout= *(uint*) arg;
 
2969
    break;
 
2970
  case MYSQL_OPT_COMPRESS:
 
2971
    mysql->options.compress= 1;                 /* Remember for connect */
 
2972
    mysql->options.client_flag|= CLIENT_COMPRESS;
 
2973
    break;
 
2974
  case MYSQL_OPT_NAMED_PIPE:                    /* This option is depricated */
 
2975
    mysql->options.protocol=MYSQL_PROTOCOL_PIPE; /* Force named pipe */
 
2976
    break;
 
2977
  case MYSQL_OPT_LOCAL_INFILE:                  /* Allow LOAD DATA LOCAL ?*/
 
2978
    if (!arg || test(*(uint*) arg))
 
2979
      mysql->options.client_flag|= CLIENT_LOCAL_FILES;
 
2980
    else
 
2981
      mysql->options.client_flag&= ~CLIENT_LOCAL_FILES;
 
2982
    break;
 
2983
  case MYSQL_INIT_COMMAND:
 
2984
    add_init_command(&mysql->options,arg);
 
2985
    break;
 
2986
  case MYSQL_READ_DEFAULT_FILE:
 
2987
    my_free(mysql->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR));
 
2988
    mysql->options.my_cnf_file=my_strdup(arg,MYF(MY_WME));
 
2989
    break;
 
2990
  case MYSQL_READ_DEFAULT_GROUP:
 
2991
    my_free(mysql->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR));
 
2992
    mysql->options.my_cnf_group=my_strdup(arg,MYF(MY_WME));
 
2993
    break;
 
2994
  case MYSQL_SET_CHARSET_DIR:
 
2995
    my_free(mysql->options.charset_dir,MYF(MY_ALLOW_ZERO_PTR));
 
2996
    mysql->options.charset_dir=my_strdup(arg,MYF(MY_WME));
 
2997
    break;
 
2998
  case MYSQL_SET_CHARSET_NAME:
 
2999
    my_free(mysql->options.charset_name,MYF(MY_ALLOW_ZERO_PTR));
 
3000
    mysql->options.charset_name=my_strdup(arg,MYF(MY_WME));
 
3001
    break;
 
3002
  case MYSQL_OPT_PROTOCOL:
 
3003
    mysql->options.protocol= *(uint*) arg;
 
3004
    break;
 
3005
  case MYSQL_SHARED_MEMORY_BASE_NAME:
 
3006
#ifdef HAVE_SMEM
 
3007
    if (mysql->options.shared_memory_base_name != def_shared_memory_base_name)
 
3008
      my_free(mysql->options.shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
 
3009
    mysql->options.shared_memory_base_name=my_strdup(arg,MYF(MY_WME));
 
3010
#endif
 
3011
    break;
 
3012
  case MYSQL_OPT_USE_REMOTE_CONNECTION:
 
3013
  case MYSQL_OPT_USE_EMBEDDED_CONNECTION:
 
3014
  case MYSQL_OPT_GUESS_CONNECTION:
 
3015
    mysql->options.methods_to_use= option;
 
3016
    break;
 
3017
  case MYSQL_SET_CLIENT_IP:
 
3018
    mysql->options.client_ip= my_strdup(arg, MYF(MY_WME));
 
3019
    break;
 
3020
  case MYSQL_SECURE_AUTH:
 
3021
    mysql->options.secure_auth= *(my_bool *) arg;
 
3022
    break;
 
3023
  case MYSQL_REPORT_DATA_TRUNCATION:
 
3024
    mysql->options.report_data_truncation= test(*(my_bool *) arg);
 
3025
    break;
 
3026
  case MYSQL_OPT_RECONNECT:
 
3027
    mysql->reconnect= *(my_bool *) arg;
 
3028
    break;
 
3029
  case MYSQL_OPT_SSL_VERIFY_SERVER_CERT:
 
3030
    if (*(my_bool*) arg)
 
3031
      mysql->options.client_flag|= CLIENT_SSL_VERIFY_SERVER_CERT;
 
3032
    else
 
3033
      mysql->options.client_flag&= ~CLIENT_SSL_VERIFY_SERVER_CERT;
556
3034
    break;
557
3035
  default:
558
 
    return(1);
 
3036
    DBUG_RETURN(1);
559
3037
  }
560
 
  return(0);
 
3038
  DBUG_RETURN(0);
561
3039
}
562
3040
 
563
3041
 
564
3042
/****************************************************************************
565
 
  Functions to get information from the DRIZZLE structure
 
3043
  Functions to get information from the MySQL structure
566
3044
  These are functions to make shared libraries more usable.
567
3045
****************************************************************************/
568
3046
 
569
 
/* DRIZZLE_RES */
570
 
uint64_t drizzle_num_rows(const DRIZZLE_RES *res)
 
3047
/* MYSQL_RES */
 
3048
my_ulonglong STDCALL mysql_num_rows(MYSQL_RES *res)
571
3049
{
572
3050
  return res->row_count;
573
3051
}
574
3052
 
575
 
unsigned int drizzle_num_fields(const DRIZZLE_RES *res)
 
3053
unsigned int STDCALL mysql_num_fields(MYSQL_RES *res)
576
3054
{
577
3055
  return res->field_count;
578
3056
}
579
3057
 
 
3058
uint STDCALL mysql_errno(MYSQL *mysql)
 
3059
{
 
3060
  return mysql ? mysql->net.last_errno : mysql_server_last_errno;
 
3061
}
 
3062
 
 
3063
 
 
3064
const char * STDCALL mysql_error(MYSQL *mysql)
 
3065
{
 
3066
  return mysql ? mysql->net.last_error : mysql_server_last_error;
 
3067
}
 
3068
 
580
3069
 
581
3070
/*
582
3071
  Get version number for server in a form easy to test on
583
3072
 
584
3073
  SYNOPSIS
585
 
    drizzle_get_server_version()
586
 
    drizzle Connection
 
3074
    mysql_get_server_version()
 
3075
    mysql               Connection
587
3076
 
588
3077
  EXAMPLE
589
3078
    4.1.0-alfa ->  40100
590
 
 
 
3079
  
591
3080
  NOTES
592
3081
    We will ensure that a newer server always has a bigger number.
593
3082
 
595
3084
   Signed number > 323000
596
3085
*/
597
3086
 
598
 
uint32_t
599
 
drizzle_get_server_version(const DRIZZLE *drizzle)
600
 
{
601
 
  uint32_t major, minor, version;
602
 
  char *pos= drizzle->server_version, *end_pos;
603
 
  major=   (uint32_t) strtoul(pos, &end_pos, 10);  pos=end_pos+1;
604
 
  minor=   (uint32_t) strtoul(pos, &end_pos, 10);  pos=end_pos+1;
605
 
  version= (uint32_t) strtoul(pos, &end_pos, 10);
606
 
  return (uint32_t) major*10000L+(uint32_t) (minor*100+version);
607
 
}
 
3087
ulong STDCALL
 
3088
mysql_get_server_version(MYSQL *mysql)
 
3089
{
 
3090
  uint major, minor, version;
 
3091
  char *pos= mysql->server_version, *end_pos;
 
3092
  major=   (uint) strtoul(pos, &end_pos, 10);   pos=end_pos+1;
 
3093
  minor=   (uint) strtoul(pos, &end_pos, 10);   pos=end_pos+1;
 
3094
  version= (uint) strtoul(pos, &end_pos, 10);
 
3095
  return (ulong) major*10000L+(ulong) (minor*100+version);
 
3096
}
 
3097
 
 
3098
 
 
3099
/* 
 
3100
   mysql_set_character_set function sends SET NAMES cs_name to
 
3101
   the server (which changes character_set_client, character_set_result
 
3102
   and character_set_connection) and updates mysql->charset so other
 
3103
   functions like mysql_real_escape will work correctly.
 
3104
*/
 
3105
int STDCALL mysql_set_character_set(MYSQL *mysql, const char *cs_name)
 
3106
{
 
3107
  struct charset_info_st *cs;
 
3108
  const char *save_csdir= charsets_dir;
 
3109
 
 
3110
  if (mysql->options.charset_dir)
 
3111
    charsets_dir= mysql->options.charset_dir;
 
3112
 
 
3113
  if (strlen(cs_name) < MY_CS_NAME_SIZE &&
 
3114
     (cs= get_charset_by_csname(cs_name, MY_CS_PRIMARY, MYF(0))))
 
3115
  {
 
3116
    char buff[MY_CS_NAME_SIZE + 10];
 
3117
    charsets_dir= save_csdir;
 
3118
    /* Skip execution of "SET NAMES" for pre-4.1 servers */
 
3119
    if (mysql_get_server_version(mysql) < 40100)
 
3120
      return 0;
 
3121
    sprintf(buff, "SET NAMES %s", cs_name);
 
3122
    if (!mysql_real_query(mysql, buff, strlen(buff)))
 
3123
    {
 
3124
      mysql->charset= cs;
 
3125
    }
 
3126
  }
 
3127
  else
 
3128
  {
 
3129
    char cs_dir_name[FN_REFLEN];
 
3130
    get_charsets_dir(cs_dir_name);
 
3131
    set_mysql_extended_error(mysql, CR_CANT_READ_CHARSET, unknown_sqlstate,
 
3132
                             ER(CR_CANT_READ_CHARSET), cs_name, cs_dir_name);
 
3133
  }
 
3134
  charsets_dir= save_csdir;
 
3135
  return mysql->net.last_errno;
 
3136
}
 
3137
 
608
3138