~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/* Copyright (C) 2000-2004 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.
6
7
   There are special exceptions to the terms and conditions of the GPL as it
8
   is applied to this software. View the full text of the exception in file
9
   EXCEPTIONS-CLIENT in the directory of this software distribution.
10
11
   This program is distributed in the hope that it will be useful,
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
   GNU General Public License for more details.
15
16
   You should have received a copy of the GNU General Public License
17
   along with this program; if not, write to the Free Software
18
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
19
20
#include <my_global.h>
21
#include <my_sys.h>
22
#include <my_time.h>
23
#include <mysys_err.h>
24
#include <m_string.h>
25
#include <m_ctype.h>
77.1.39 by Monty Taylor
More mysql->drizzle renaming.
26
#include "drizzle.h"
27
#include "drizzle_version.h"
1 by brian
clean slate
28
#include "mysqld_error.h"
29
#include "errmsg.h"
30
#include <violite.h>
31
#include <sys/stat.h>
32
#include <signal.h>
33
#include <time.h>
34
#ifdef	 HAVE_PWD_H
35
#include <pwd.h>
36
#endif
94 by Brian Aker
DOS removal. DOS... hard to believe aye?
37
1 by brian
clean slate
38
#include <sys/socket.h>
39
#include <netinet/in.h>
40
#include <arpa/inet.h>
41
#include <netdb.h>
42
#ifdef HAVE_SELECT_H
43
#include <select.h>
44
#endif
45
#ifdef HAVE_SYS_SELECT_H
46
#include <sys/select.h>
47
#endif
94 by Brian Aker
DOS removal. DOS... hard to believe aye?
48
1 by brian
clean slate
49
#ifdef HAVE_POLL
50
#include <sys/poll.h>
51
#endif
52
#ifdef HAVE_SYS_UN_H
53
#include <sys/un.h>
54
#endif
55
#include <my_pthread.h>				/* because of signal()	*/
56
#ifndef INADDR_NONE
57
#define INADDR_NONE	-1
58
#endif
59
60
#include <sql_common.h>
61
#include "client_settings.h"
62
63
#undef net_buffer_length
64
#undef max_allowed_packet
65
164 by Brian Aker
Commit cleanup of export types.
66
uint32_t 		net_buffer_length= 8192;
67
uint32_t		max_allowed_packet= 1024L*1024L*1024L;
1 by brian
clean slate
68
69
#include <errno.h>
70
#define SOCKET_ERROR -1
71
72
/*
73
  If allowed through some configuration, then this needs to
74
  be changed
75
*/
76
#define MAX_LONG_DATA_LENGTH 8192
77
#define unsigned_field(A) ((A)->flags & UNSIGNED_FLAG)
78
79
static void append_wild(char *to,char *end,const char *wild);
80
81
static my_bool mysql_client_init= 0;
82
static my_bool org_my_init_done= 0;
83
84
85
/*
86
  Initialize the MySQL client library
87
88
  SYNOPSIS
89
    mysql_server_init()
90
91
  NOTES
92
    Should be called before doing any other calls to the MySQL
93
    client library to initialize thread specific variables etc.
94
    It's called by mysql_init() to ensure that things will work for
95
    old not threaded applications that doesn't call mysql_server_init()
96
    directly.
97
98
  RETURN
99
    0  ok
100
    1  could not initialize environment (out of memory or thread keys)
101
*/
102
103
int STDCALL mysql_server_init(int argc __attribute__((unused)),
104
			      char **argv __attribute__((unused)),
105
			      char **groups __attribute__((unused)))
106
{
107
  int result= 0;
108
  if (!mysql_client_init)
109
  {
110
    mysql_client_init=1;
111
    org_my_init_done=my_init_done;
112
    if (my_init())				/* Will init threads */
113
      return 1;
114
    init_client_errs();
115
    if (!mysql_port)
116
    {
117
      mysql_port = MYSQL_PORT;
118
      {
119
	struct servent *serv_ptr;
120
	char	*env;
121
122
        /*
123
          if builder specifically requested a default port, use that
124
          (even if it coincides with our factory default).
125
          only if they didn't do we check /etc/services (and, failing
165.1.1 by Elliot Murphy
new port number from IANA
126
          on that, fall back to the factory default of 4427).
1 by brian
clean slate
127
          either default can be overridden by the environment variable
128
          MYSQL_TCP_PORT, which in turn can be overridden with command
129
          line options.
130
        */
131
132
#if MYSQL_PORT_DEFAULT == 0
133
        if ((serv_ptr = getservbyname("mysql", "tcp")))
134
          mysql_port = (uint) ntohs((ushort) serv_ptr->s_port);
135
#endif
136
        if ((env = getenv("MYSQL_TCP_PORT")))
137
          mysql_port =(uint) atoi(env);
138
      }
139
    }
140
    if (!mysql_unix_port)
141
    {
142
      char *env;
143
      mysql_unix_port = (char*) MYSQL_UNIX_ADDR;
144
      if ((env = getenv("MYSQL_UNIX_PORT")))
145
	mysql_unix_port = env;
146
    }
147
    mysql_debug(NullS);
47 by Brian Aker
First pass on removing binary protocol from client library.
148
#if defined(SIGPIPE)
1 by brian
clean slate
149
    (void) signal(SIGPIPE, SIG_IGN);
150
#endif
151
  }
152
  else
153
    result= (int)my_thread_init();         /* Init if new thread */
154
  return result;
155
}
156
157
158
/*
159
  Free all memory and resources used by the client library
160
161
  NOTES
162
    When calling this there should not be any other threads using
163
    the library.
164
165
    To make things simpler when used with windows dll's (which calls this
166
    function automaticly), it's safe to call this function multiple times.
167
*/
168
169
170
void STDCALL mysql_server_end()
171
{
172
  if (!mysql_client_init)
173
    return;
174
175
  finish_client_errs();
176
  vio_end();
177
178
  /* If library called my_init(), free memory allocated by it */
179
  if (!org_my_init_done)
180
  {
181
    my_end(MY_DONT_FREE_DBUG);
182
    /* Remove TRACING, if enabled by mysql_debug() */
183
    DBUG_POP();
184
  }
185
  else
186
  {
187
    free_charsets();
188
    mysql_thread_end();
189
  }
190
191
  mysql_client_init= org_my_init_done= 0;
192
#ifdef EMBEDDED_SERVER
193
  if (stderror_file)
194
  {
195
    fclose(stderror_file);
196
    stderror_file= 0;
197
  }
198
#endif
199
}
200
201
static MYSQL_PARAMETERS mysql_internal_parameters=
202
{&max_allowed_packet, &net_buffer_length, 0};
203
204
MYSQL_PARAMETERS *STDCALL mysql_get_parameters(void)
205
{
206
  return &mysql_internal_parameters;
207
}
208
209
my_bool STDCALL mysql_thread_init()
210
{
211
  return my_thread_init();
212
}
213
214
void STDCALL mysql_thread_end()
215
{
216
  my_thread_end();
217
}
218
219
220
/*
221
  Expand wildcard to a sql string
222
*/
223
224
static void
225
append_wild(char *to, char *end, const char *wild)
226
{
227
  end-=5;					/* Some extra */
228
  if (wild && wild[0])
229
  {
230
    to=strmov(to," like '");
231
    while (*wild && to < end)
232
    {
233
      if (*wild == '\\' || *wild == '\'')
234
	*to++='\\';
235
      *to++= *wild++;
236
    }
237
    if (*wild)					/* Too small buffer */
238
      *to++='%';				/* Nicer this way */
239
    to[0]='\'';
240
    to[1]=0;
241
  }
242
}
243
244
245
/**************************************************************************
246
  Init debugging if MYSQL_DEBUG environment variable is found
247
**************************************************************************/
248
249
void STDCALL
250
mysql_debug(const char *debug __attribute__((unused)))
251
{
252
#ifndef DBUG_OFF
253
  char	*env;
254
  if (debug)
255
  {
256
    DBUG_PUSH(debug);
257
  }
258
  else if ((env = getenv("MYSQL_DEBUG")))
259
  {
260
    DBUG_PUSH(env);
261
#if !defined(_WINVER) && !defined(WINVER)
262
    puts("\n-------------------------------------------------------");
263
    puts("MYSQL_DEBUG found. libmysql started with the following:");
264
    puts(env);
265
    puts("-------------------------------------------------------\n");
266
#else
267
    {
268
      char buff[80];
269
      buff[sizeof(buff)-1]= 0;
270
      strxnmov(buff,sizeof(buff)-1,"libmysql: ", env, NullS);
271
      MessageBox((HWND) 0,"Debugging variable MYSQL_DEBUG used",buff,MB_OK);
272
    }
273
#endif
274
  }
275
#endif
276
}
277
278
279
/**************************************************************************
280
  Ignore SIGPIPE handler
281
   ARGSUSED
282
**************************************************************************/
283
284
sig_handler
285
my_pipe_sig_handler(int sig __attribute__((unused)))
286
{
287
  DBUG_PRINT("info",("Hit by signal %d",sig));
288
#ifdef DONT_REMEMBER_SIGNAL
289
  (void) signal(SIGPIPE, my_pipe_sig_handler);
290
#endif
291
}
292
293
294
/**************************************************************************
295
  Connect to sql server
296
  If host == 0 then use localhost
297
**************************************************************************/
298
299
#ifdef USE_OLD_FUNCTIONS
300
MYSQL * STDCALL
301
mysql_connect(MYSQL *mysql,const char *host,
302
	      const char *user, const char *passwd)
303
{
304
  MYSQL *res;
305
  mysql=mysql_init(mysql);			/* Make it thread safe */
306
  {
307
    DBUG_ENTER("mysql_connect");
308
    if (!(res=mysql_real_connect(mysql,host,user,passwd,NullS,0,NullS,0)))
309
    {
310
      if (mysql->free_me)
311
	my_free((uchar*) mysql,MYF(0));
312
    }
313
    mysql->reconnect= 1;
314
    DBUG_RETURN(res);
315
  }
316
}
317
#endif
318
319
320
/**************************************************************************
321
  Change user and database
322
**************************************************************************/
323
324
int cli_read_change_user_result(MYSQL *mysql, char *buff, const char *passwd)
325
{
77.1.107 by Monty Taylor
Fixed build warnings.
326
  (void)buff;
327
  (void)passwd;
1 by brian
clean slate
328
  ulong pkt_length;
329
330
  pkt_length= cli_safe_read(mysql);
331
  
332
  if (pkt_length == packet_error)
333
    return 1;
334
335
  return 0;
336
}
337
338
my_bool	STDCALL mysql_change_user(MYSQL *mysql, const char *user,
339
				  const char *passwd, const char *db)
340
{
341
  char buff[USERNAME_LENGTH+SCRAMBLED_PASSWORD_CHAR_LENGTH+NAME_LEN+2];
342
  char *end= buff;
343
  int rc;
344
  CHARSET_INFO *saved_cs= mysql->charset;
345
346
  DBUG_ENTER("mysql_change_user");
347
348
  /* Get the connection-default character set. */
349
350
  if (mysql_init_character_set(mysql))
351
  {
352
    mysql->charset= saved_cs;
163 by Brian Aker
Merge Monty's code.
353
    DBUG_RETURN(true);
1 by brian
clean slate
354
  }
355
356
  /* Use an empty string instead of NULL. */
357
358
  if (!user)
359
    user="";
360
  if (!passwd)
361
    passwd="";
362
363
  /* Store user into the buffer */
364
  end= strmake(end, user, USERNAME_LENGTH) + 1;
365
366
  /* write scrambled password according to server capabilities */
367
  if (passwd[0])
368
  {
369
    {
370
      *end++= SCRAMBLE_LENGTH;
371
      scramble(end, mysql->scramble, passwd);
372
      end+= SCRAMBLE_LENGTH;
373
    }
374
  }
375
  else
376
    *end++= '\0';                               /* empty password */
377
  /* Add database if needed */
378
  end= strmake(end, db ? db : "", NAME_LEN) + 1;
379
380
  /* Add character set number. */
381
382
  if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
383
  {
384
    int2store(end, (ushort) mysql->charset->number);
385
    end+= 2;
386
  }
387
388
  /* Write authentication package */
164 by Brian Aker
Commit cleanup of export types.
389
  (void)simple_command(mysql,COM_CHANGE_USER, (uchar*) buff, (ulong) (end-buff), 1);
1 by brian
clean slate
390
391
  rc= (*mysql->methods->read_change_user_result)(mysql, buff, passwd);
392
393
  if (rc == 0)
394
  {
395
    /* Free old connect information */
396
    my_free(mysql->user,MYF(MY_ALLOW_ZERO_PTR));
397
    my_free(mysql->passwd,MYF(MY_ALLOW_ZERO_PTR));
398
    my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR));
399
400
    /* alloc new connect information */
401
    mysql->user=  my_strdup(user,MYF(MY_WME));
402
    mysql->passwd=my_strdup(passwd,MYF(MY_WME));
403
    mysql->db=    db ? my_strdup(db,MYF(MY_WME)) : 0;
404
  }
405
  else
406
  {
407
    mysql->charset= saved_cs;
408
  }
409
410
  DBUG_RETURN(rc);
411
}
412
413
#if defined(HAVE_GETPWUID) && defined(NO_GETPWUID_DECL)
414
struct passwd *getpwuid(uid_t);
415
char* getlogin(void);
416
#endif
417
418
void read_user_name(char *name)
419
{
420
  DBUG_ENTER("read_user_name");
421
  if (geteuid() == 0)
422
    (void) strmov(name,"root");		/* allow use of surun */
423
  else
424
  {
425
#ifdef HAVE_GETPWUID
426
    struct passwd *skr;
427
    const char *str;
428
    if ((str=getlogin()) == NULL)
429
    {
430
      if ((skr=getpwuid(geteuid())) != NULL)
431
	str=skr->pw_name;
432
      else if (!(str=getenv("USER")) && !(str=getenv("LOGNAME")) &&
433
	       !(str=getenv("LOGIN")))
434
	str="UNKNOWN_USER";
435
    }
436
    (void) strmake(name,str,USERNAME_LENGTH);
437
#elif HAVE_CUSERID
438
    (void) cuserid(name);
439
#else
440
    strmov(name,"UNKNOWN_USER");
441
#endif
442
  }
443
  DBUG_VOID_RETURN;
444
}
445
446
my_bool handle_local_infile(MYSQL *mysql, const char *net_filename)
447
{
448
  my_bool result= 1;
449
  uint packet_length=MY_ALIGN(mysql->net.max_packet-16,IO_SIZE);
450
  NET *net= &mysql->net;
451
  int readcount;
452
  void *li_ptr;          /* pass state to local_infile functions */
453
  char *buf;		/* buffer to be filled by local_infile_read */
454
  struct st_mysql_options *options= &mysql->options;
455
  DBUG_ENTER("handle_local_infile");
456
457
  /* check that we've got valid callback functions */
458
  if (!(options->local_infile_init &&
459
	options->local_infile_read &&
460
	options->local_infile_end &&
461
	options->local_infile_error))
462
  {
463
    /* if any of the functions is invalid, set the default */
464
    mysql_set_local_infile_default(mysql);
465
  }
466
467
  /* copy filename into local memory and allocate read buffer */
468
  if (!(buf=my_malloc(packet_length, MYF(0))))
469
  {
470
    set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate);
471
    DBUG_RETURN(1);
472
  }
473
474
  /* initialize local infile (open file, usually) */
475
  if ((*options->local_infile_init)(&li_ptr, net_filename,
476
    options->local_infile_userdata))
477
  {
478
    VOID(my_net_write(net,(const uchar*) "",0)); /* Server needs one packet */
479
    net_flush(net);
480
    strmov(net->sqlstate, unknown_sqlstate);
481
    net->last_errno=
482
      (*options->local_infile_error)(li_ptr,
483
                                     net->last_error,
484
                                     sizeof(net->last_error)-1);
485
    goto err;
486
  }
487
488
  /* read blocks of data from local infile callback */
489
  while ((readcount =
490
	  (*options->local_infile_read)(li_ptr, buf,
491
					packet_length)) > 0)
492
  {
493
    if (my_net_write(net, (uchar*) buf, readcount))
494
    {
495
      DBUG_PRINT("error",
496
		 ("Lost connection to MySQL server during LOAD DATA of local file"));
497
      set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate);
498
      goto err;
499
    }
500
  }
501
502
  /* Send empty packet to mark end of file */
503
  if (my_net_write(net, (const uchar*) "", 0) || net_flush(net))
504
  {
505
    set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate);
506
    goto err;
507
  }
508
509
  if (readcount < 0)
510
  {
511
    net->last_errno=
512
      (*options->local_infile_error)(li_ptr,
513
                                     net->last_error,
514
                                     sizeof(net->last_error)-1);
515
    goto err;
516
  }
517
518
  result=0;					/* Ok */
519
520
err:
521
  /* free up memory allocated with _init, usually */
522
  (*options->local_infile_end)(li_ptr);
523
  my_free(buf, MYF(0));
524
  DBUG_RETURN(result);
525
}
526
527
528
/****************************************************************************
529
  Default handlers for LOAD LOCAL INFILE
530
****************************************************************************/
531
532
typedef struct st_default_local_infile
533
{
534
  int fd;
535
  int error_num;
536
  const char *filename;
537
  char error_msg[LOCAL_INFILE_ERROR_LEN];
538
} default_local_infile_data;
539
540
541
/*
542
  Open file for LOAD LOCAL INFILE
543
544
  SYNOPSIS
545
    default_local_infile_init()
546
    ptr			Store pointer to internal data here
547
    filename		File name to open. This may be in unix format !
548
549
550
  NOTES
551
    Even if this function returns an error, the load data interface
552
    guarantees that default_local_infile_end() is called.
553
554
  RETURN
555
    0	ok
556
    1	error
557
*/
558
559
static int default_local_infile_init(void **ptr, const char *filename,
560
             void *userdata __attribute__ ((unused)))
561
{
562
  default_local_infile_data *data;
563
  char tmp_name[FN_REFLEN];
564
565
  if (!(*ptr= data= ((default_local_infile_data *)
566
		     my_malloc(sizeof(default_local_infile_data),  MYF(0)))))
567
    return 1; /* out of memory */
568
569
  data->error_msg[0]= 0;
570
  data->error_num=    0;
571
  data->filename= filename;
572
573
  fn_format(tmp_name, filename, "", "", MY_UNPACK_FILENAME);
574
  if ((data->fd = my_open(tmp_name, O_RDONLY, MYF(0))) < 0)
575
  {
576
    data->error_num= my_errno;
77.1.18 by Monty Taylor
Removed my_vsnprintf and my_snprintf.
577
    snprintf(data->error_msg, sizeof(data->error_msg)-1,
578
             EE(EE_FILENOTFOUND), tmp_name, data->error_num);
1 by brian
clean slate
579
    return 1;
580
  }
581
  return 0; /* ok */
582
}
583
584
585
/*
586
  Read data for LOAD LOCAL INFILE
587
588
  SYNOPSIS
589
    default_local_infile_read()
590
    ptr			Points to handle allocated by _init
591
    buf			Read data here
592
    buf_len		Ammount of data to read
593
594
  RETURN
595
    > 0		number of bytes read
596
    == 0	End of data
597
    < 0		Error
598
*/
599
600
static int default_local_infile_read(void *ptr, char *buf, uint buf_len)
601
{
602
  int count;
603
  default_local_infile_data*data = (default_local_infile_data *) ptr;
604
605
  if ((count= (int) my_read(data->fd, (uchar *) buf, buf_len, MYF(0))) < 0)
606
  {
607
    data->error_num= EE_READ; /* the errmsg for not entire file read */
77.1.18 by Monty Taylor
Removed my_vsnprintf and my_snprintf.
608
    snprintf(data->error_msg, sizeof(data->error_msg)-1,
609
             EE(EE_READ),
610
             data->filename, my_errno);
1 by brian
clean slate
611
  }
612
  return count;
613
}
614
615
616
/*
617
  Read data for LOAD LOCAL INFILE
618
619
  SYNOPSIS
620
    default_local_infile_end()
621
    ptr			Points to handle allocated by _init
622
			May be NULL if _init failed!
623
624
  RETURN
625
*/
626
627
static void default_local_infile_end(void *ptr)
628
{
629
  default_local_infile_data *data= (default_local_infile_data *) ptr;
630
  if (data)					/* If not error on open */
631
  {
632
    if (data->fd >= 0)
633
      my_close(data->fd, MYF(MY_WME));
634
    my_free(ptr, MYF(MY_WME));
635
  }
636
}
637
638
639
/*
640
  Return error from LOAD LOCAL INFILE
641
642
  SYNOPSIS
643
    default_local_infile_end()
644
    ptr			Points to handle allocated by _init
645
			May be NULL if _init failed!
646
    error_msg		Store error text here
647
    error_msg_len	Max lenght of error_msg
648
649
  RETURN
650
    error message number
651
*/
652
653
static int
654
default_local_infile_error(void *ptr, char *error_msg, uint error_msg_len)
655
{
656
  default_local_infile_data *data = (default_local_infile_data *) ptr;
657
  if (data)					/* If not error on open */
658
  {
659
    strmake(error_msg, data->error_msg, error_msg_len);
660
    return data->error_num;
661
  }
662
  /* This can only happen if we got error on malloc of handle */
663
  strmov(error_msg, ER(CR_OUT_OF_MEMORY));
664
  return CR_OUT_OF_MEMORY;
665
}
666
667
668
void
669
mysql_set_local_infile_handler(MYSQL *mysql,
670
                               int (*local_infile_init)(void **, const char *,
671
                               void *),
672
                               int (*local_infile_read)(void *, char *, uint),
673
                               void (*local_infile_end)(void *),
674
                               int (*local_infile_error)(void *, char *, uint),
675
                               void *userdata)
676
{
677
  mysql->options.local_infile_init=  local_infile_init;
678
  mysql->options.local_infile_read=  local_infile_read;
679
  mysql->options.local_infile_end=   local_infile_end;
680
  mysql->options.local_infile_error= local_infile_error;
681
  mysql->options.local_infile_userdata = userdata;
682
}
683
684
685
void mysql_set_local_infile_default(MYSQL *mysql)
686
{
687
  mysql->options.local_infile_init=  default_local_infile_init;
688
  mysql->options.local_infile_read=  default_local_infile_read;
689
  mysql->options.local_infile_end=   default_local_infile_end;
690
  mysql->options.local_infile_error= default_local_infile_error;
691
}
692
693
694
/**************************************************************************
695
  Do a query. If query returned rows, free old rows.
696
  Read data by mysql_store_result or by repeat call of mysql_fetch_row
697
**************************************************************************/
698
699
int STDCALL
700
mysql_query(MYSQL *mysql, const char *query)
701
{
702
  return mysql_real_query(mysql,query, (uint) strlen(query));
703
}
704
705
706
/**************************************************************************
707
  Return next field of the query results
708
**************************************************************************/
709
710
MYSQL_FIELD * STDCALL
711
mysql_fetch_field(MYSQL_RES *result)
712
{
713
  if (result->current_field >= result->field_count)
714
    return(NULL);
715
  return &result->fields[result->current_field++];
716
}
717
718
719
/**************************************************************************
720
  Move to a specific row and column
721
**************************************************************************/
722
723
void STDCALL
155 by Brian Aker
Removing a few "additional" ways of saying uint64_t
724
mysql_data_seek(MYSQL_RES *result, uint64_t row)
1 by brian
clean slate
725
{
726
  MYSQL_ROWS	*tmp=0;
727
  DBUG_PRINT("info",("mysql_data_seek(%ld)",(long) row));
728
  if (result->data)
729
    for (tmp=result->data->data; row-- && tmp ; tmp = tmp->next) ;
730
  result->current_row=0;
731
  result->data_cursor = tmp;
732
}
733
734
735
/*************************************************************************
736
  put the row or field cursor one a position one got from mysql_row_tell()
737
  This doesn't restore any data. The next mysql_fetch_row or
738
  mysql_fetch_field will return the next row or field after the last used
739
*************************************************************************/
740
741
MYSQL_ROW_OFFSET STDCALL
742
mysql_row_seek(MYSQL_RES *result, MYSQL_ROW_OFFSET row)
743
{
744
  MYSQL_ROW_OFFSET return_value=result->data_cursor;
745
  result->current_row= 0;
746
  result->data_cursor= row;
747
  return return_value;
748
}
749
750
751
MYSQL_FIELD_OFFSET STDCALL
752
mysql_field_seek(MYSQL_RES *result, MYSQL_FIELD_OFFSET field_offset)
753
{
754
  MYSQL_FIELD_OFFSET return_value=result->current_field;
755
  result->current_field=field_offset;
756
  return return_value;
757
}
758
759
760
/*****************************************************************************
761
  List all databases
762
*****************************************************************************/
763
764
MYSQL_RES * STDCALL
765
mysql_list_dbs(MYSQL *mysql, const char *wild)
766
{
767
  char buff[255];
768
  DBUG_ENTER("mysql_list_dbs");
769
770
  append_wild(strmov(buff,"show databases"),buff+sizeof(buff),wild);
771
  if (mysql_query(mysql,buff))
772
    DBUG_RETURN(0);
773
  DBUG_RETURN (mysql_store_result(mysql));
774
}
775
776
777
/*****************************************************************************
778
  List all tables in a database
779
  If wild is given then only the tables matching wild is returned
780
*****************************************************************************/
781
782
MYSQL_RES * STDCALL
783
mysql_list_tables(MYSQL *mysql, const char *wild)
784
{
785
  char buff[255];
786
  DBUG_ENTER("mysql_list_tables");
787
788
  append_wild(strmov(buff,"show tables"),buff+sizeof(buff),wild);
789
  if (mysql_query(mysql,buff))
790
    DBUG_RETURN(0);
791
  DBUG_RETURN (mysql_store_result(mysql));
792
}
793
794
795
MYSQL_FIELD *cli_list_fields(MYSQL *mysql)
796
{
797
  MYSQL_DATA *query;
798
  if (!(query= cli_read_rows(mysql,(MYSQL_FIELD*) 0, 
799
			     protocol_41(mysql) ? 8 : 6)))
800
    return NULL;
801
802
  mysql->field_count= (uint) query->rows;
803
  return unpack_fields(query,&mysql->field_alloc,
804
		       mysql->field_count, 1, mysql->server_capabilities);
805
}
806
807
808
/**************************************************************************
809
  List all fields in a table
810
  If wild is given then only the fields matching wild is returned
811
  Instead of this use query:
812
  show fields in 'table' like "wild"
813
**************************************************************************/
814
815
MYSQL_RES * STDCALL
816
mysql_list_fields(MYSQL *mysql, const char *table, const char *wild)
817
{
818
  MYSQL_RES   *result;
819
  MYSQL_FIELD *fields;
820
  char	     buff[257],*end;
821
  DBUG_ENTER("mysql_list_fields");
822
  DBUG_PRINT("enter",("table: '%s'  wild: '%s'",table,wild ? wild : ""));
823
824
  end=strmake(strmake(buff, table,128)+1,wild ? wild : "",128);
825
  free_old_query(mysql);
826
  if (simple_command(mysql, COM_FIELD_LIST, (uchar*) buff,
827
                     (ulong) (end-buff), 1) ||
828
      !(fields= (*mysql->methods->list_fields)(mysql)))
829
    DBUG_RETURN(NULL);
830
831
  if (!(result = (MYSQL_RES *) my_malloc(sizeof(MYSQL_RES),
832
					 MYF(MY_WME | MY_ZEROFILL))))
833
    DBUG_RETURN(NULL);
834
835
  result->methods= mysql->methods;
836
  result->field_alloc=mysql->field_alloc;
837
  mysql->fields=0;
838
  result->field_count = mysql->field_count;
839
  result->fields= fields;
840
  result->eof=1;
841
  DBUG_RETURN(result);
842
}
843
844
/* List all running processes (threads) in server */
845
846
MYSQL_RES * STDCALL
847
mysql_list_processes(MYSQL *mysql)
848
{
849
  MYSQL_DATA *fields;
850
  uint field_count;
851
  uchar *pos;
852
  DBUG_ENTER("mysql_list_processes");
853
854
  if (simple_command(mysql,COM_PROCESS_INFO,0,0,0))
855
    DBUG_RETURN(0);
856
  free_old_query(mysql);
857
  pos=(uchar*) mysql->net.read_pos;
858
  field_count=(uint) net_field_length(&pos);
859
  if (!(fields = (*mysql->methods->read_rows)(mysql,(MYSQL_FIELD*) 0,
860
					      protocol_41(mysql) ? 7 : 5)))
861
    DBUG_RETURN(NULL);
862
  if (!(mysql->fields=unpack_fields(fields,&mysql->field_alloc,field_count,0,
863
				    mysql->server_capabilities)))
864
    DBUG_RETURN(0);
865
  mysql->status=MYSQL_STATUS_GET_RESULT;
866
  mysql->field_count=field_count;
867
  DBUG_RETURN(mysql_store_result(mysql));
868
}
869
870
871
#ifdef USE_OLD_FUNCTIONS
872
int  STDCALL
873
mysql_create_db(MYSQL *mysql, const char *db)
874
{
875
  DBUG_ENTER("mysql_createdb");
876
  DBUG_PRINT("enter",("db: %s",db));
877
  DBUG_RETURN(simple_command(mysql,COM_CREATE_DB,db, (ulong) strlen(db),0));
878
}
879
880
881
int  STDCALL
882
mysql_drop_db(MYSQL *mysql, const char *db)
883
{
884
  DBUG_ENTER("mysql_drop_db");
885
  DBUG_PRINT("enter",("db: %s",db));
886
  DBUG_RETURN(simple_command(mysql,COM_DROP_DB,db,(ulong) strlen(db),0));
887
}
888
#endif
889
890
891
int STDCALL
892
mysql_shutdown(MYSQL *mysql, enum mysql_enum_shutdown_level shutdown_level)
893
{
894
  uchar level[1];
895
  DBUG_ENTER("mysql_shutdown");
896
  level[0]= (uchar) shutdown_level;
897
  DBUG_RETURN(simple_command(mysql, COM_SHUTDOWN, level, 1, 0));
898
}
899
900
901
int STDCALL
902
mysql_refresh(MYSQL *mysql,uint options)
903
{
904
  uchar bits[1];
905
  DBUG_ENTER("mysql_refresh");
906
  bits[0]= (uchar) options;
907
  DBUG_RETURN(simple_command(mysql, COM_REFRESH, bits, 1, 0));
908
}
909
910
164 by Brian Aker
Commit cleanup of export types.
911
int32_t STDCALL
912
mysql_kill(MYSQL *mysql, uint32_t pid)
1 by brian
clean slate
913
{
914
  uchar buff[4];
915
  DBUG_ENTER("mysql_kill");
916
  int4store(buff,pid);
917
  DBUG_RETURN(simple_command(mysql,COM_PROCESS_KILL,buff,sizeof(buff),0));
918
}
919
920
921
int STDCALL
922
mysql_set_server_option(MYSQL *mysql, enum enum_mysql_set_option option)
923
{
924
  uchar buff[2];
925
  DBUG_ENTER("mysql_set_server_option");
926
  int2store(buff, (uint) option);
927
  DBUG_RETURN(simple_command(mysql, COM_SET_OPTION, buff, sizeof(buff), 0));
928
}
929
930
931
int STDCALL
932
mysql_dump_debug_info(MYSQL *mysql)
933
{
934
  DBUG_ENTER("mysql_dump_debug_info");
935
  DBUG_RETURN(simple_command(mysql,COM_DEBUG,0,0,0));
936
}
937
938
939
const char *cli_read_statistics(MYSQL *mysql)
940
{
941
  mysql->net.read_pos[mysql->packet_length]=0;	/* End of stat string */
942
  if (!mysql->net.read_pos[0])
943
  {
944
    set_mysql_error(mysql, CR_WRONG_HOST_INFO, unknown_sqlstate);
945
    return mysql->net.last_error;
946
  }
947
  return (char*) mysql->net.read_pos;
948
}
949
950
951
const char * STDCALL
952
mysql_stat(MYSQL *mysql)
953
{
954
  DBUG_ENTER("mysql_stat");
955
  if (simple_command(mysql,COM_STATISTICS,0,0,0))
956
    DBUG_RETURN(mysql->net.last_error);
957
  DBUG_RETURN((*mysql->methods->read_statistics)(mysql));
958
}
959
960
961
int STDCALL
962
mysql_ping(MYSQL *mysql)
963
{
964
  int res;
965
  DBUG_ENTER("mysql_ping");
966
  res= simple_command(mysql,COM_PING,0,0,0);
967
  if (res == CR_SERVER_LOST && mysql->reconnect)
968
    res= simple_command(mysql,COM_PING,0,0,0);
969
  DBUG_RETURN(res);
970
}
971
972
973
const char * STDCALL
974
mysql_get_server_info(MYSQL *mysql)
975
{
976
  return((char*) mysql->server_version);
977
}
978
979
980
const char * STDCALL
981
mysql_get_host_info(MYSQL *mysql)
982
{
983
  return(mysql->host_info);
984
}
985
986
987
uint STDCALL
988
mysql_get_proto_info(MYSQL *mysql)
989
{
990
  return (mysql->protocol_version);
991
}
992
993
const char * STDCALL
994
mysql_get_client_info(void)
995
{
996
  return (char*) MYSQL_SERVER_VERSION;
997
}
998
164 by Brian Aker
Commit cleanup of export types.
999
uint32_t STDCALL mysql_get_client_version(void)
1 by brian
clean slate
1000
{
1001
  return MYSQL_VERSION_ID;
1002
}
1003
1004
my_bool STDCALL mysql_eof(MYSQL_RES *res)
1005
{
1006
  return res->eof;
1007
}
1008
1009
MYSQL_FIELD * STDCALL mysql_fetch_field_direct(MYSQL_RES *res,uint fieldnr)
1010
{
1011
  return &(res)->fields[fieldnr];
1012
}
1013
1014
MYSQL_FIELD * STDCALL mysql_fetch_fields(MYSQL_RES *res)
1015
{
1016
  return (res)->fields;
1017
}
1018
1019
MYSQL_ROW_OFFSET STDCALL mysql_row_tell(MYSQL_RES *res)
1020
{
1021
  return res->data_cursor;
1022
}
1023
1024
MYSQL_FIELD_OFFSET STDCALL mysql_field_tell(MYSQL_RES *res)
1025
{
1026
  return (res)->current_field;
1027
}
1028
1029
/* MYSQL */
1030
1031
unsigned int STDCALL mysql_field_count(MYSQL *mysql)
1032
{
1033
  return mysql->field_count;
1034
}
1035
155 by Brian Aker
Removing a few "additional" ways of saying uint64_t
1036
uint64_t STDCALL mysql_affected_rows(MYSQL *mysql)
1 by brian
clean slate
1037
{
1038
  return mysql->affected_rows;
1039
}
1040
155 by Brian Aker
Removing a few "additional" ways of saying uint64_t
1041
uint64_t STDCALL mysql_insert_id(MYSQL *mysql)
1 by brian
clean slate
1042
{
1043
  return mysql->insert_id;
1044
}
1045
1046
const char *STDCALL mysql_sqlstate(MYSQL *mysql)
1047
{
1048
  return mysql ? mysql->net.sqlstate : cant_connect_sqlstate;
1049
}
1050
164 by Brian Aker
Commit cleanup of export types.
1051
uint32_t STDCALL mysql_warning_count(MYSQL *mysql)
1 by brian
clean slate
1052
{
1053
  return mysql->warning_count;
1054
}
1055
1056
const char *STDCALL mysql_info(MYSQL *mysql)
1057
{
1058
  return mysql->info;
1059
}
1060
164 by Brian Aker
Commit cleanup of export types.
1061
uint32_t STDCALL mysql_thread_id(MYSQL *mysql)
1 by brian
clean slate
1062
{
1063
  return (mysql)->thread_id;
1064
}
1065
1066
const char * STDCALL mysql_character_set_name(MYSQL *mysql)
1067
{
1068
  return mysql->charset->csname;
1069
}
1070
1071
void STDCALL mysql_get_character_set_info(MYSQL *mysql, MY_CHARSET_INFO *csinfo)
1072
{
1073
  csinfo->number   = mysql->charset->number;
1074
  csinfo->state    = mysql->charset->state;
1075
  csinfo->csname   = mysql->charset->csname;
1076
  csinfo->name     = mysql->charset->name;
1077
  csinfo->comment  = mysql->charset->comment;
1078
  csinfo->mbminlen = mysql->charset->mbminlen;
1079
  csinfo->mbmaxlen = mysql->charset->mbmaxlen;
1080
1081
  if (mysql->options.charset_dir)
1082
    csinfo->dir = mysql->options.charset_dir;
1083
  else
1084
    csinfo->dir = charsets_dir;
1085
}
1086
1087
uint STDCALL mysql_thread_safe(void)
1088
{
1089
  return 1;
1090
}
1091
1092
1093
my_bool STDCALL mysql_embedded(void)
1094
{
1095
#ifdef EMBEDDED_LIBRARY
1096
  return 1;
1097
#else
1098
  return 0;
1099
#endif
1100
}
1101
1102
/****************************************************************************
1103
  Some support functions
1104
****************************************************************************/
1105
1106
/*
1107
  Functions called my my_net_init() to set some application specific variables
1108
*/
1109
1110
void my_net_local_init(NET *net)
1111
{
1112
  net->max_packet=   (uint) net_buffer_length;
1113
  my_net_set_read_timeout(net, CLIENT_NET_READ_TIMEOUT);
1114
  my_net_set_write_timeout(net, CLIENT_NET_WRITE_TIMEOUT);
1115
  net->retry_count=  1;
1116
  net->max_packet_size= max(net_buffer_length, max_allowed_packet);
1117
}
1118
1119
/*
1120
  This function is used to create HEX string that you
1121
  can use in a SQL statement in of the either ways:
1122
    INSERT INTO blob_column VALUES (0xAABBCC);  (any MySQL version)
1123
    INSERT INTO blob_column VALUES (X'AABBCC'); (4.1 and higher)
1124
  
1125
  The string in "from" is encoded to a HEX string.
1126
  The result is placed in "to" and a terminating null byte is appended.
1127
  
1128
  The string pointed to by "from" must be "length" bytes long.
1129
  You must allocate the "to" buffer to be at least length*2+1 bytes long.
1130
  Each character needs two bytes, and you need room for the terminating
1131
  null byte. When mysql_hex_string() returns, the contents of "to" will
1132
  be a null-terminated string. The return value is the length of the
1133
  encoded string, not including the terminating null character.
1134
1135
  The return value does not contain any leading 0x or a leading X' and
1136
  trailing '. The caller must supply whichever of those is desired.
1137
*/
1138
164 by Brian Aker
Commit cleanup of export types.
1139
uint32_t STDCALL
1140
mysql_hex_string(char *to, const char *from, uint32_t length)
1 by brian
clean slate
1141
{
1142
  char *to0= to;
1143
  const char *end;
1144
            
1145
  for (end= from + length; from < end; from++)
1146
  {
1147
    *to++= _dig_vec_upper[((unsigned char) *from) >> 4];
1148
    *to++= _dig_vec_upper[((unsigned char) *from) & 0x0F];
1149
  }
1150
  *to= '\0';
164 by Brian Aker
Commit cleanup of export types.
1151
  return (uint32_t) (to-to0);
1 by brian
clean slate
1152
}
1153
1154
/*
1155
  Add escape characters to a string (blob?) to make it suitable for a insert
1156
  to should at least have place for length*2+1 chars
1157
  Returns the length of the to string
1158
*/
1159
164 by Brian Aker
Commit cleanup of export types.
1160
uint32_t STDCALL
1161
mysql_escape_string(char *to,const char *from, uint32_t length)
1 by brian
clean slate
1162
{
1163
  return escape_string_for_mysql(default_charset_info, to, 0, from, length);
1164
}
1165
164 by Brian Aker
Commit cleanup of export types.
1166
uint32_t STDCALL
1 by brian
clean slate
1167
mysql_real_escape_string(MYSQL *mysql, char *to,const char *from,
164 by Brian Aker
Commit cleanup of export types.
1168
			 uint32_t length)
1 by brian
clean slate
1169
{
1170
  if (mysql->server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES)
1171
    return escape_quotes_for_mysql(mysql->charset, to, 0, from, length);
1172
  return escape_string_for_mysql(mysql->charset, to, 0, from, length);
1173
}
1174
1175
void STDCALL
1176
myodbc_remove_escape(MYSQL *mysql,char *name)
1177
{
1178
  char *to;
1179
#ifdef USE_MB
1180
  my_bool use_mb_flag=use_mb(mysql->charset);
77.1.77 by Monty Taylor
A crapton more warning cleanups (I turned on more warnings)
1181
  char *end=NULL;
1 by brian
clean slate
1182
  if (use_mb_flag)
1183
    for (end=name; *end ; end++) ;
1184
#endif
1185
1186
  for (to=name ; *name ; name++)
1187
  {
1188
#ifdef USE_MB
1189
    int l;
1190
    if (use_mb_flag && (l = my_ismbchar( mysql->charset, name , end ) ) )
1191
    {
1192
      while (l--)
1193
	*to++ = *name++;
1194
      name--;
1195
      continue;
1196
    }
1197
#endif
1198
    if (*name == '\\' && name[1])
1199
      name++;
1200
    *to++= *name;
1201
  }
1202
  *to=0;
1203
}
1204
1205
int cli_unbuffered_fetch(MYSQL *mysql, char **row)
1206
{
1207
  if (packet_error == cli_safe_read(mysql))
1208
    return 1;
1209
1210
  *row= ((mysql->net.read_pos[0] == 254) ? NULL :
1211
	 (char*) (mysql->net.read_pos+1));
1212
  return 0;
1213
}
1214
1215
/********************************************************************
1216
 Transactional APIs
1217
*********************************************************************/
1218
1219
/*
1220
  Commit the current transaction
1221
*/
1222
1223
my_bool STDCALL mysql_commit(MYSQL * mysql)
1224
{
1225
  DBUG_ENTER("mysql_commit");
1226
  DBUG_RETURN((my_bool) mysql_real_query(mysql, "commit", 6));
1227
}
1228
1229
/*
1230
  Rollback the current transaction
1231
*/
1232
1233
my_bool STDCALL mysql_rollback(MYSQL * mysql)
1234
{
1235
  DBUG_ENTER("mysql_rollback");
1236
  DBUG_RETURN((my_bool) mysql_real_query(mysql, "rollback", 8));
1237
}
1238
1239
1240
/*
1241
  Set autocommit to either true or false
1242
*/
1243
1244
my_bool STDCALL mysql_autocommit(MYSQL * mysql, my_bool auto_mode)
1245
{
1246
  DBUG_ENTER("mysql_autocommit");
1247
  DBUG_PRINT("enter", ("mode : %d", auto_mode));
1248
1249
  DBUG_RETURN((my_bool) mysql_real_query(mysql, auto_mode ?
1250
                                         "set autocommit=1":"set autocommit=0",
1251
                                         16));
1252
}
1253
1254
1255
/********************************************************************
1256
 Multi query execution + SPs APIs
1257
*********************************************************************/
1258
1259
/*
1260
  Returns true/false to indicate whether any more query results exist
1261
  to be read using mysql_next_result()
1262
*/
1263
1264
my_bool STDCALL mysql_more_results(MYSQL *mysql)
1265
{
1266
  my_bool res;
1267
  DBUG_ENTER("mysql_more_results");
1268
1269
  res= ((mysql->server_status & SERVER_MORE_RESULTS_EXISTS) ? 1: 0);
1270
  DBUG_PRINT("exit",("More results exists ? %d", res));
1271
  DBUG_RETURN(res);
1272
}
1273
1274
1275
/*
1276
  Reads and returns the next query results
1277
*/
1278
int STDCALL mysql_next_result(MYSQL *mysql)
1279
{
1280
  DBUG_ENTER("mysql_next_result");
1281
1282
  if (mysql->status != MYSQL_STATUS_READY)
1283
  {
1284
    set_mysql_error(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
1285
    DBUG_RETURN(1);
1286
  }
1287
1288
  net_clear_error(&mysql->net);
155 by Brian Aker
Removing a few "additional" ways of saying uint64_t
1289
  mysql->affected_rows= ~(uint64_t) 0;
1 by brian
clean slate
1290
1291
  if (mysql->server_status & SERVER_MORE_RESULTS_EXISTS)
1292
    DBUG_RETURN((*mysql->methods->next_result)(mysql));
1293
1294
  DBUG_RETURN(-1);				/* No more results */
1295
}
1296
1297
1298
MYSQL_RES * STDCALL mysql_use_result(MYSQL *mysql)
1299
{
1300
  return (*mysql->methods->use_result)(mysql);
1301
}
1302
1303
my_bool STDCALL mysql_read_query_result(MYSQL *mysql)
1304
{
1305
  return (*mysql->methods->read_query_result)(mysql);
1306
}
1307