~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to libdrizzle/client.c

  • Committer: Jay Pipes
  • Date: 2008-07-21 17:52:33 UTC
  • mto: (201.2.1 drizzle)
  • mto: This revision was merged to the branch mainline in revision 204.
  • Revision ID: jay@mysql.com-20080721175233-mtyz298j8xl3v63y
cleanup of FAQ file

Show diffs side-by-side

added added

removed removed

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