~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to libmysql/client.c

  • Committer: Monty Taylor
  • Date: 2008-07-05 18:10:38 UTC
  • mto: This revision was merged to the branch mainline in revision 63.
  • Revision ID: monty@inaugust.com-20080705181038-0ih0nnamu5qrut0y
Fixed prototypes. Cleaned define a little bit.

Show diffs side-by-side

added added

removed removed

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