~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to libdrizzle/client.c

Removed/replaced DBUG symbols and standardized TRUE/FALSE

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