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 |
||
66 |
ulong net_buffer_length=8192; |
|
67 |
ulong max_allowed_packet= 1024L*1024L*1024L; |
|
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
|
|
126 |
on that, fall back to the factory default of 3306).
|
|
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 |
{
|
|
326 |
NET *net= &mysql->net; |
|
327 |
ulong pkt_length; |
|
328 |
||
329 |
pkt_length= cli_safe_read(mysql); |
|
330 |
||
331 |
if (pkt_length == packet_error) |
|
332 |
return 1; |
|
333 |
||
334 |
if (pkt_length == 1 && net->read_pos[0] == 254 && |
|
335 |
mysql->server_capabilities & CLIENT_SECURE_CONNECTION) |
|
336 |
{
|
|
337 |
/*
|
|
338 |
By sending this very specific reply server asks us to send scrambled
|
|
339 |
password in old format. The reply contains scramble_323.
|
|
340 |
*/
|
|
341 |
scramble_323(buff, mysql->scramble, passwd); |
|
342 |
if (my_net_write(net, (uchar*) buff, SCRAMBLE_LENGTH_323 + 1) || |
|
343 |
net_flush(net)) |
|
344 |
{
|
|
345 |
set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate); |
|
346 |
return 1; |
|
347 |
}
|
|
348 |
/* Read what server thinks about out new auth message report */
|
|
349 |
if (cli_safe_read(mysql) == packet_error) |
|
350 |
return 1; |
|
351 |
}
|
|
352 |
return 0; |
|
353 |
}
|
|
354 |
||
355 |
my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user, |
|
356 |
const char *passwd, const char *db) |
|
357 |
{
|
|
358 |
char buff[USERNAME_LENGTH+SCRAMBLED_PASSWORD_CHAR_LENGTH+NAME_LEN+2]; |
|
359 |
char *end= buff; |
|
360 |
int rc; |
|
361 |
CHARSET_INFO *saved_cs= mysql->charset; |
|
362 |
||
363 |
DBUG_ENTER("mysql_change_user"); |
|
364 |
||
365 |
/* Get the connection-default character set. */
|
|
366 |
||
367 |
if (mysql_init_character_set(mysql)) |
|
368 |
{
|
|
369 |
mysql->charset= saved_cs; |
|
370 |
DBUG_RETURN(TRUE); |
|
371 |
}
|
|
372 |
||
373 |
/* Use an empty string instead of NULL. */
|
|
374 |
||
375 |
if (!user) |
|
376 |
user=""; |
|
377 |
if (!passwd) |
|
378 |
passwd=""; |
|
379 |
||
380 |
/* Store user into the buffer */
|
|
381 |
end= strmake(end, user, USERNAME_LENGTH) + 1; |
|
382 |
||
383 |
/* write scrambled password according to server capabilities */
|
|
384 |
if (passwd[0]) |
|
385 |
{
|
|
386 |
if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION) |
|
387 |
{
|
|
388 |
*end++= SCRAMBLE_LENGTH; |
|
389 |
scramble(end, mysql->scramble, passwd); |
|
390 |
end+= SCRAMBLE_LENGTH; |
|
391 |
}
|
|
392 |
else
|
|
393 |
{
|
|
394 |
scramble_323(end, mysql->scramble, passwd); |
|
395 |
end+= SCRAMBLE_LENGTH_323 + 1; |
|
396 |
}
|
|
397 |
}
|
|
398 |
else
|
|
399 |
*end++= '\0'; /* empty password */ |
|
400 |
/* Add database if needed */
|
|
401 |
end= strmake(end, db ? db : "", NAME_LEN) + 1; |
|
402 |
||
403 |
/* Add character set number. */
|
|
404 |
||
405 |
if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION) |
|
406 |
{
|
|
407 |
int2store(end, (ushort) mysql->charset->number); |
|
408 |
end+= 2; |
|
409 |
}
|
|
410 |
||
411 |
/* Write authentication package */
|
|
412 |
simple_command(mysql,COM_CHANGE_USER, (uchar*) buff, (ulong) (end-buff), 1); |
|
413 |
||
414 |
rc= (*mysql->methods->read_change_user_result)(mysql, buff, passwd); |
|
415 |
||
416 |
if (rc == 0) |
|
417 |
{
|
|
418 |
/* Free old connect information */
|
|
419 |
my_free(mysql->user,MYF(MY_ALLOW_ZERO_PTR)); |
|
420 |
my_free(mysql->passwd,MYF(MY_ALLOW_ZERO_PTR)); |
|
421 |
my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR)); |
|
422 |
||
423 |
/* alloc new connect information */
|
|
424 |
mysql->user= my_strdup(user,MYF(MY_WME)); |
|
425 |
mysql->passwd=my_strdup(passwd,MYF(MY_WME)); |
|
426 |
mysql->db= db ? my_strdup(db,MYF(MY_WME)) : 0; |
|
427 |
}
|
|
428 |
else
|
|
429 |
{
|
|
430 |
mysql->charset= saved_cs; |
|
431 |
}
|
|
432 |
||
433 |
DBUG_RETURN(rc); |
|
434 |
}
|
|
435 |
||
436 |
#if defined(HAVE_GETPWUID) && defined(NO_GETPWUID_DECL)
|
|
437 |
struct passwd *getpwuid(uid_t); |
|
438 |
char* getlogin(void); |
|
439 |
#endif
|
|
440 |
||
441 |
void read_user_name(char *name) |
|
442 |
{
|
|
443 |
DBUG_ENTER("read_user_name"); |
|
444 |
if (geteuid() == 0) |
|
445 |
(void) strmov(name,"root"); /* allow use of surun */ |
|
446 |
else
|
|
447 |
{
|
|
448 |
#ifdef HAVE_GETPWUID
|
|
449 |
struct passwd *skr; |
|
450 |
const char *str; |
|
451 |
if ((str=getlogin()) == NULL) |
|
452 |
{
|
|
453 |
if ((skr=getpwuid(geteuid())) != NULL) |
|
454 |
str=skr->pw_name; |
|
455 |
else if (!(str=getenv("USER")) && !(str=getenv("LOGNAME")) && |
|
456 |
!(str=getenv("LOGIN"))) |
|
457 |
str="UNKNOWN_USER"; |
|
458 |
}
|
|
459 |
(void) strmake(name,str,USERNAME_LENGTH); |
|
460 |
#elif HAVE_CUSERID
|
|
461 |
(void) cuserid(name); |
|
462 |
#else
|
|
463 |
strmov(name,"UNKNOWN_USER"); |
|
464 |
#endif
|
|
465 |
}
|
|
466 |
DBUG_VOID_RETURN; |
|
467 |
}
|
|
468 |
||
469 |
my_bool handle_local_infile(MYSQL *mysql, const char *net_filename) |
|
470 |
{
|
|
471 |
my_bool result= 1; |
|
472 |
uint packet_length=MY_ALIGN(mysql->net.max_packet-16,IO_SIZE); |
|
473 |
NET *net= &mysql->net; |
|
474 |
int readcount; |
|
475 |
void *li_ptr; /* pass state to local_infile functions */ |
|
476 |
char *buf; /* buffer to be filled by local_infile_read */ |
|
477 |
struct st_mysql_options *options= &mysql->options; |
|
478 |
DBUG_ENTER("handle_local_infile"); |
|
479 |
||
480 |
/* check that we've got valid callback functions */
|
|
481 |
if (!(options->local_infile_init && |
|
482 |
options->local_infile_read && |
|
483 |
options->local_infile_end && |
|
484 |
options->local_infile_error)) |
|
485 |
{
|
|
486 |
/* if any of the functions is invalid, set the default */
|
|
487 |
mysql_set_local_infile_default(mysql); |
|
488 |
}
|
|
489 |
||
490 |
/* copy filename into local memory and allocate read buffer */
|
|
491 |
if (!(buf=my_malloc(packet_length, MYF(0)))) |
|
492 |
{
|
|
493 |
set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate); |
|
494 |
DBUG_RETURN(1); |
|
495 |
}
|
|
496 |
||
497 |
/* initialize local infile (open file, usually) */
|
|
498 |
if ((*options->local_infile_init)(&li_ptr, net_filename, |
|
499 |
options->local_infile_userdata)) |
|
500 |
{
|
|
501 |
VOID(my_net_write(net,(const uchar*) "",0)); /* Server needs one packet */ |
|
502 |
net_flush(net); |
|
503 |
strmov(net->sqlstate, unknown_sqlstate); |
|
504 |
net->last_errno= |
|
505 |
(*options->local_infile_error)(li_ptr, |
|
506 |
net->last_error, |
|
507 |
sizeof(net->last_error)-1); |
|
508 |
goto err; |
|
509 |
}
|
|
510 |
||
511 |
/* read blocks of data from local infile callback */
|
|
512 |
while ((readcount = |
|
513 |
(*options->local_infile_read)(li_ptr, buf, |
|
514 |
packet_length)) > 0) |
|
515 |
{
|
|
516 |
if (my_net_write(net, (uchar*) buf, readcount)) |
|
517 |
{
|
|
518 |
DBUG_PRINT("error", |
|
519 |
("Lost connection to MySQL server during LOAD DATA of local file")); |
|
520 |
set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate); |
|
521 |
goto err; |
|
522 |
}
|
|
523 |
}
|
|
524 |
||
525 |
/* Send empty packet to mark end of file */
|
|
526 |
if (my_net_write(net, (const uchar*) "", 0) || net_flush(net)) |
|
527 |
{
|
|
528 |
set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate); |
|
529 |
goto err; |
|
530 |
}
|
|
531 |
||
532 |
if (readcount < 0) |
|
533 |
{
|
|
534 |
net->last_errno= |
|
535 |
(*options->local_infile_error)(li_ptr, |
|
536 |
net->last_error, |
|
537 |
sizeof(net->last_error)-1); |
|
538 |
goto err; |
|
539 |
}
|
|
540 |
||
541 |
result=0; /* Ok */ |
|
542 |
||
543 |
err: |
|
544 |
/* free up memory allocated with _init, usually */
|
|
545 |
(*options->local_infile_end)(li_ptr); |
|
546 |
my_free(buf, MYF(0)); |
|
547 |
DBUG_RETURN(result); |
|
548 |
}
|
|
549 |
||
550 |
||
551 |
/****************************************************************************
|
|
552 |
Default handlers for LOAD LOCAL INFILE
|
|
553 |
****************************************************************************/
|
|
554 |
||
555 |
typedef struct st_default_local_infile |
|
556 |
{
|
|
557 |
int fd; |
|
558 |
int error_num; |
|
559 |
const char *filename; |
|
560 |
char error_msg[LOCAL_INFILE_ERROR_LEN]; |
|
561 |
} default_local_infile_data; |
|
562 |
||
563 |
||
564 |
/*
|
|
565 |
Open file for LOAD LOCAL INFILE
|
|
566 |
||
567 |
SYNOPSIS
|
|
568 |
default_local_infile_init()
|
|
569 |
ptr Store pointer to internal data here
|
|
570 |
filename File name to open. This may be in unix format !
|
|
571 |
||
572 |
||
573 |
NOTES
|
|
574 |
Even if this function returns an error, the load data interface
|
|
575 |
guarantees that default_local_infile_end() is called.
|
|
576 |
||
577 |
RETURN
|
|
578 |
0 ok
|
|
579 |
1 error
|
|
580 |
*/
|
|
581 |
||
582 |
static int default_local_infile_init(void **ptr, const char *filename, |
|
583 |
void *userdata __attribute__ ((unused))) |
|
584 |
{
|
|
585 |
default_local_infile_data *data; |
|
586 |
char tmp_name[FN_REFLEN]; |
|
587 |
||
588 |
if (!(*ptr= data= ((default_local_infile_data *) |
|
589 |
my_malloc(sizeof(default_local_infile_data), MYF(0))))) |
|
590 |
return 1; /* out of memory */ |
|
591 |
||
592 |
data->error_msg[0]= 0; |
|
593 |
data->error_num= 0; |
|
594 |
data->filename= filename; |
|
595 |
||
596 |
fn_format(tmp_name, filename, "", "", MY_UNPACK_FILENAME); |
|
597 |
if ((data->fd = my_open(tmp_name, O_RDONLY, MYF(0))) < 0) |
|
598 |
{
|
|
599 |
data->error_num= my_errno; |
|
77.1.18
by Monty Taylor
Removed my_vsnprintf and my_snprintf. |
600 |
snprintf(data->error_msg, sizeof(data->error_msg)-1, |
601 |
EE(EE_FILENOTFOUND), tmp_name, data->error_num); |
|
1
by brian
clean slate |
602 |
return 1; |
603 |
}
|
|
604 |
return 0; /* ok */ |
|
605 |
}
|
|
606 |
||
607 |
||
608 |
/*
|
|
609 |
Read data for LOAD LOCAL INFILE
|
|
610 |
||
611 |
SYNOPSIS
|
|
612 |
default_local_infile_read()
|
|
613 |
ptr Points to handle allocated by _init
|
|
614 |
buf Read data here
|
|
615 |
buf_len Ammount of data to read
|
|
616 |
||
617 |
RETURN
|
|
618 |
> 0 number of bytes read
|
|
619 |
== 0 End of data
|
|
620 |
< 0 Error
|
|
621 |
*/
|
|
622 |
||
623 |
static int default_local_infile_read(void *ptr, char *buf, uint buf_len) |
|
624 |
{
|
|
625 |
int count; |
|
626 |
default_local_infile_data*data = (default_local_infile_data *) ptr; |
|
627 |
||
628 |
if ((count= (int) my_read(data->fd, (uchar *) buf, buf_len, MYF(0))) < 0) |
|
629 |
{
|
|
630 |
data->error_num= EE_READ; /* the errmsg for not entire file read */ |
|
77.1.18
by Monty Taylor
Removed my_vsnprintf and my_snprintf. |
631 |
snprintf(data->error_msg, sizeof(data->error_msg)-1, |
632 |
EE(EE_READ), |
|
633 |
data->filename, my_errno); |
|
1
by brian
clean slate |
634 |
}
|
635 |
return count; |
|
636 |
}
|
|
637 |
||
638 |
||
639 |
/*
|
|
640 |
Read data for 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 |
||
647 |
RETURN
|
|
648 |
*/
|
|
649 |
||
650 |
static void default_local_infile_end(void *ptr) |
|
651 |
{
|
|
652 |
default_local_infile_data *data= (default_local_infile_data *) ptr; |
|
653 |
if (data) /* If not error on open */ |
|
654 |
{
|
|
655 |
if (data->fd >= 0) |
|
656 |
my_close(data->fd, MYF(MY_WME)); |
|
657 |
my_free(ptr, MYF(MY_WME)); |
|
658 |
}
|
|
659 |
}
|
|
660 |
||
661 |
||
662 |
/*
|
|
663 |
Return error from LOAD LOCAL INFILE
|
|
664 |
||
665 |
SYNOPSIS
|
|
666 |
default_local_infile_end()
|
|
667 |
ptr Points to handle allocated by _init
|
|
668 |
May be NULL if _init failed!
|
|
669 |
error_msg Store error text here
|
|
670 |
error_msg_len Max lenght of error_msg
|
|
671 |
||
672 |
RETURN
|
|
673 |
error message number
|
|
674 |
*/
|
|
675 |
||
676 |
static int |
|
677 |
default_local_infile_error(void *ptr, char *error_msg, uint error_msg_len) |
|
678 |
{
|
|
679 |
default_local_infile_data *data = (default_local_infile_data *) ptr; |
|
680 |
if (data) /* If not error on open */ |
|
681 |
{
|
|
682 |
strmake(error_msg, data->error_msg, error_msg_len); |
|
683 |
return data->error_num; |
|
684 |
}
|
|
685 |
/* This can only happen if we got error on malloc of handle */
|
|
686 |
strmov(error_msg, ER(CR_OUT_OF_MEMORY)); |
|
687 |
return CR_OUT_OF_MEMORY; |
|
688 |
}
|
|
689 |
||
690 |
||
691 |
void
|
|
692 |
mysql_set_local_infile_handler(MYSQL *mysql, |
|
693 |
int (*local_infile_init)(void **, const char *, |
|
694 |
void *), |
|
695 |
int (*local_infile_read)(void *, char *, uint), |
|
696 |
void (*local_infile_end)(void *), |
|
697 |
int (*local_infile_error)(void *, char *, uint), |
|
698 |
void *userdata) |
|
699 |
{
|
|
700 |
mysql->options.local_infile_init= local_infile_init; |
|
701 |
mysql->options.local_infile_read= local_infile_read; |
|
702 |
mysql->options.local_infile_end= local_infile_end; |
|
703 |
mysql->options.local_infile_error= local_infile_error; |
|
704 |
mysql->options.local_infile_userdata = userdata; |
|
705 |
}
|
|
706 |
||
707 |
||
708 |
void mysql_set_local_infile_default(MYSQL *mysql) |
|
709 |
{
|
|
710 |
mysql->options.local_infile_init= default_local_infile_init; |
|
711 |
mysql->options.local_infile_read= default_local_infile_read; |
|
712 |
mysql->options.local_infile_end= default_local_infile_end; |
|
713 |
mysql->options.local_infile_error= default_local_infile_error; |
|
714 |
}
|
|
715 |
||
716 |
||
717 |
/**************************************************************************
|
|
718 |
Do a query. If query returned rows, free old rows.
|
|
719 |
Read data by mysql_store_result or by repeat call of mysql_fetch_row
|
|
720 |
**************************************************************************/
|
|
721 |
||
722 |
int STDCALL |
|
723 |
mysql_query(MYSQL *mysql, const char *query) |
|
724 |
{
|
|
725 |
return mysql_real_query(mysql,query, (uint) strlen(query)); |
|
726 |
}
|
|
727 |
||
728 |
||
729 |
/**************************************************************************
|
|
730 |
Return next field of the query results
|
|
731 |
**************************************************************************/
|
|
732 |
||
733 |
MYSQL_FIELD * STDCALL |
|
734 |
mysql_fetch_field(MYSQL_RES *result) |
|
735 |
{
|
|
736 |
if (result->current_field >= result->field_count) |
|
737 |
return(NULL); |
|
738 |
return &result->fields[result->current_field++]; |
|
739 |
}
|
|
740 |
||
741 |
||
742 |
/**************************************************************************
|
|
743 |
Move to a specific row and column
|
|
744 |
**************************************************************************/
|
|
745 |
||
746 |
void STDCALL |
|
747 |
mysql_data_seek(MYSQL_RES *result, my_ulonglong row) |
|
748 |
{
|
|
749 |
MYSQL_ROWS *tmp=0; |
|
750 |
DBUG_PRINT("info",("mysql_data_seek(%ld)",(long) row)); |
|
751 |
if (result->data) |
|
752 |
for (tmp=result->data->data; row-- && tmp ; tmp = tmp->next) ; |
|
753 |
result->current_row=0; |
|
754 |
result->data_cursor = tmp; |
|
755 |
}
|
|
756 |
||
757 |
||
758 |
/*************************************************************************
|
|
759 |
put the row or field cursor one a position one got from mysql_row_tell()
|
|
760 |
This doesn't restore any data. The next mysql_fetch_row or
|
|
761 |
mysql_fetch_field will return the next row or field after the last used
|
|
762 |
*************************************************************************/
|
|
763 |
||
764 |
MYSQL_ROW_OFFSET STDCALL |
|
765 |
mysql_row_seek(MYSQL_RES *result, MYSQL_ROW_OFFSET row) |
|
766 |
{
|
|
767 |
MYSQL_ROW_OFFSET return_value=result->data_cursor; |
|
768 |
result->current_row= 0; |
|
769 |
result->data_cursor= row; |
|
770 |
return return_value; |
|
771 |
}
|
|
772 |
||
773 |
||
774 |
MYSQL_FIELD_OFFSET STDCALL |
|
775 |
mysql_field_seek(MYSQL_RES *result, MYSQL_FIELD_OFFSET field_offset) |
|
776 |
{
|
|
777 |
MYSQL_FIELD_OFFSET return_value=result->current_field; |
|
778 |
result->current_field=field_offset; |
|
779 |
return return_value; |
|
780 |
}
|
|
781 |
||
782 |
||
783 |
/*****************************************************************************
|
|
784 |
List all databases
|
|
785 |
*****************************************************************************/
|
|
786 |
||
787 |
MYSQL_RES * STDCALL |
|
788 |
mysql_list_dbs(MYSQL *mysql, const char *wild) |
|
789 |
{
|
|
790 |
char buff[255]; |
|
791 |
DBUG_ENTER("mysql_list_dbs"); |
|
792 |
||
793 |
append_wild(strmov(buff,"show databases"),buff+sizeof(buff),wild); |
|
794 |
if (mysql_query(mysql,buff)) |
|
795 |
DBUG_RETURN(0); |
|
796 |
DBUG_RETURN (mysql_store_result(mysql)); |
|
797 |
}
|
|
798 |
||
799 |
||
800 |
/*****************************************************************************
|
|
801 |
List all tables in a database
|
|
802 |
If wild is given then only the tables matching wild is returned
|
|
803 |
*****************************************************************************/
|
|
804 |
||
805 |
MYSQL_RES * STDCALL |
|
806 |
mysql_list_tables(MYSQL *mysql, const char *wild) |
|
807 |
{
|
|
808 |
char buff[255]; |
|
809 |
DBUG_ENTER("mysql_list_tables"); |
|
810 |
||
811 |
append_wild(strmov(buff,"show tables"),buff+sizeof(buff),wild); |
|
812 |
if (mysql_query(mysql,buff)) |
|
813 |
DBUG_RETURN(0); |
|
814 |
DBUG_RETURN (mysql_store_result(mysql)); |
|
815 |
}
|
|
816 |
||
817 |
||
818 |
MYSQL_FIELD *cli_list_fields(MYSQL *mysql) |
|
819 |
{
|
|
820 |
MYSQL_DATA *query; |
|
821 |
if (!(query= cli_read_rows(mysql,(MYSQL_FIELD*) 0, |
|
822 |
protocol_41(mysql) ? 8 : 6))) |
|
823 |
return NULL; |
|
824 |
||
825 |
mysql->field_count= (uint) query->rows; |
|
826 |
return unpack_fields(query,&mysql->field_alloc, |
|
827 |
mysql->field_count, 1, mysql->server_capabilities); |
|
828 |
}
|
|
829 |
||
830 |
||
831 |
/**************************************************************************
|
|
832 |
List all fields in a table
|
|
833 |
If wild is given then only the fields matching wild is returned
|
|
834 |
Instead of this use query:
|
|
835 |
show fields in 'table' like "wild"
|
|
836 |
**************************************************************************/
|
|
837 |
||
838 |
MYSQL_RES * STDCALL |
|
839 |
mysql_list_fields(MYSQL *mysql, const char *table, const char *wild) |
|
840 |
{
|
|
841 |
MYSQL_RES *result; |
|
842 |
MYSQL_FIELD *fields; |
|
843 |
char buff[257],*end; |
|
844 |
DBUG_ENTER("mysql_list_fields"); |
|
845 |
DBUG_PRINT("enter",("table: '%s' wild: '%s'",table,wild ? wild : "")); |
|
846 |
||
847 |
end=strmake(strmake(buff, table,128)+1,wild ? wild : "",128); |
|
848 |
free_old_query(mysql); |
|
849 |
if (simple_command(mysql, COM_FIELD_LIST, (uchar*) buff, |
|
850 |
(ulong) (end-buff), 1) || |
|
851 |
!(fields= (*mysql->methods->list_fields)(mysql))) |
|
852 |
DBUG_RETURN(NULL); |
|
853 |
||
854 |
if (!(result = (MYSQL_RES *) my_malloc(sizeof(MYSQL_RES), |
|
855 |
MYF(MY_WME | MY_ZEROFILL)))) |
|
856 |
DBUG_RETURN(NULL); |
|
857 |
||
858 |
result->methods= mysql->methods; |
|
859 |
result->field_alloc=mysql->field_alloc; |
|
860 |
mysql->fields=0; |
|
861 |
result->field_count = mysql->field_count; |
|
862 |
result->fields= fields; |
|
863 |
result->eof=1; |
|
864 |
DBUG_RETURN(result); |
|
865 |
}
|
|
866 |
||
867 |
/* List all running processes (threads) in server */
|
|
868 |
||
869 |
MYSQL_RES * STDCALL |
|
870 |
mysql_list_processes(MYSQL *mysql) |
|
871 |
{
|
|
872 |
MYSQL_DATA *fields; |
|
873 |
uint field_count; |
|
874 |
uchar *pos; |
|
875 |
DBUG_ENTER("mysql_list_processes"); |
|
876 |
||
877 |
if (simple_command(mysql,COM_PROCESS_INFO,0,0,0)) |
|
878 |
DBUG_RETURN(0); |
|
879 |
free_old_query(mysql); |
|
880 |
pos=(uchar*) mysql->net.read_pos; |
|
881 |
field_count=(uint) net_field_length(&pos); |
|
882 |
if (!(fields = (*mysql->methods->read_rows)(mysql,(MYSQL_FIELD*) 0, |
|
883 |
protocol_41(mysql) ? 7 : 5))) |
|
884 |
DBUG_RETURN(NULL); |
|
885 |
if (!(mysql->fields=unpack_fields(fields,&mysql->field_alloc,field_count,0, |
|
886 |
mysql->server_capabilities))) |
|
887 |
DBUG_RETURN(0); |
|
888 |
mysql->status=MYSQL_STATUS_GET_RESULT; |
|
889 |
mysql->field_count=field_count; |
|
890 |
DBUG_RETURN(mysql_store_result(mysql)); |
|
891 |
}
|
|
892 |
||
893 |
||
894 |
#ifdef USE_OLD_FUNCTIONS
|
|
895 |
int STDCALL |
|
896 |
mysql_create_db(MYSQL *mysql, const char *db) |
|
897 |
{
|
|
898 |
DBUG_ENTER("mysql_createdb"); |
|
899 |
DBUG_PRINT("enter",("db: %s",db)); |
|
900 |
DBUG_RETURN(simple_command(mysql,COM_CREATE_DB,db, (ulong) strlen(db),0)); |
|
901 |
}
|
|
902 |
||
903 |
||
904 |
int STDCALL |
|
905 |
mysql_drop_db(MYSQL *mysql, const char *db) |
|
906 |
{
|
|
907 |
DBUG_ENTER("mysql_drop_db"); |
|
908 |
DBUG_PRINT("enter",("db: %s",db)); |
|
909 |
DBUG_RETURN(simple_command(mysql,COM_DROP_DB,db,(ulong) strlen(db),0)); |
|
910 |
}
|
|
911 |
#endif
|
|
912 |
||
913 |
||
914 |
int STDCALL |
|
915 |
mysql_shutdown(MYSQL *mysql, enum mysql_enum_shutdown_level shutdown_level) |
|
916 |
{
|
|
917 |
uchar level[1]; |
|
918 |
DBUG_ENTER("mysql_shutdown"); |
|
919 |
level[0]= (uchar) shutdown_level; |
|
920 |
DBUG_RETURN(simple_command(mysql, COM_SHUTDOWN, level, 1, 0)); |
|
921 |
}
|
|
922 |
||
923 |
||
924 |
int STDCALL |
|
925 |
mysql_refresh(MYSQL *mysql,uint options) |
|
926 |
{
|
|
927 |
uchar bits[1]; |
|
928 |
DBUG_ENTER("mysql_refresh"); |
|
929 |
bits[0]= (uchar) options; |
|
930 |
DBUG_RETURN(simple_command(mysql, COM_REFRESH, bits, 1, 0)); |
|
931 |
}
|
|
932 |
||
933 |
||
934 |
int STDCALL |
|
935 |
mysql_kill(MYSQL *mysql,ulong pid) |
|
936 |
{
|
|
937 |
uchar buff[4]; |
|
938 |
DBUG_ENTER("mysql_kill"); |
|
939 |
int4store(buff,pid); |
|
940 |
DBUG_RETURN(simple_command(mysql,COM_PROCESS_KILL,buff,sizeof(buff),0)); |
|
941 |
}
|
|
942 |
||
943 |
||
944 |
int STDCALL |
|
945 |
mysql_set_server_option(MYSQL *mysql, enum enum_mysql_set_option option) |
|
946 |
{
|
|
947 |
uchar buff[2]; |
|
948 |
DBUG_ENTER("mysql_set_server_option"); |
|
949 |
int2store(buff, (uint) option); |
|
950 |
DBUG_RETURN(simple_command(mysql, COM_SET_OPTION, buff, sizeof(buff), 0)); |
|
951 |
}
|
|
952 |
||
953 |
||
954 |
int STDCALL |
|
955 |
mysql_dump_debug_info(MYSQL *mysql) |
|
956 |
{
|
|
957 |
DBUG_ENTER("mysql_dump_debug_info"); |
|
958 |
DBUG_RETURN(simple_command(mysql,COM_DEBUG,0,0,0)); |
|
959 |
}
|
|
960 |
||
961 |
||
962 |
const char *cli_read_statistics(MYSQL *mysql) |
|
963 |
{
|
|
964 |
mysql->net.read_pos[mysql->packet_length]=0; /* End of stat string */ |
|
965 |
if (!mysql->net.read_pos[0]) |
|
966 |
{
|
|
967 |
set_mysql_error(mysql, CR_WRONG_HOST_INFO, unknown_sqlstate); |
|
968 |
return mysql->net.last_error; |
|
969 |
}
|
|
970 |
return (char*) mysql->net.read_pos; |
|
971 |
}
|
|
972 |
||
973 |
||
974 |
const char * STDCALL |
|
975 |
mysql_stat(MYSQL *mysql) |
|
976 |
{
|
|
977 |
DBUG_ENTER("mysql_stat"); |
|
978 |
if (simple_command(mysql,COM_STATISTICS,0,0,0)) |
|
979 |
DBUG_RETURN(mysql->net.last_error); |
|
980 |
DBUG_RETURN((*mysql->methods->read_statistics)(mysql)); |
|
981 |
}
|
|
982 |
||
983 |
||
984 |
int STDCALL |
|
985 |
mysql_ping(MYSQL *mysql) |
|
986 |
{
|
|
987 |
int res; |
|
988 |
DBUG_ENTER("mysql_ping"); |
|
989 |
res= simple_command(mysql,COM_PING,0,0,0); |
|
990 |
if (res == CR_SERVER_LOST && mysql->reconnect) |
|
991 |
res= simple_command(mysql,COM_PING,0,0,0); |
|
992 |
DBUG_RETURN(res); |
|
993 |
}
|
|
994 |
||
995 |
||
996 |
const char * STDCALL |
|
997 |
mysql_get_server_info(MYSQL *mysql) |
|
998 |
{
|
|
999 |
return((char*) mysql->server_version); |
|
1000 |
}
|
|
1001 |
||
1002 |
||
1003 |
const char * STDCALL |
|
1004 |
mysql_get_host_info(MYSQL *mysql) |
|
1005 |
{
|
|
1006 |
return(mysql->host_info); |
|
1007 |
}
|
|
1008 |
||
1009 |
||
1010 |
uint STDCALL |
|
1011 |
mysql_get_proto_info(MYSQL *mysql) |
|
1012 |
{
|
|
1013 |
return (mysql->protocol_version); |
|
1014 |
}
|
|
1015 |
||
1016 |
const char * STDCALL |
|
1017 |
mysql_get_client_info(void) |
|
1018 |
{
|
|
1019 |
return (char*) MYSQL_SERVER_VERSION; |
|
1020 |
}
|
|
1021 |
||
1022 |
ulong STDCALL mysql_get_client_version(void) |
|
1023 |
{
|
|
1024 |
return MYSQL_VERSION_ID; |
|
1025 |
}
|
|
1026 |
||
1027 |
my_bool STDCALL mysql_eof(MYSQL_RES *res) |
|
1028 |
{
|
|
1029 |
return res->eof; |
|
1030 |
}
|
|
1031 |
||
1032 |
MYSQL_FIELD * STDCALL mysql_fetch_field_direct(MYSQL_RES *res,uint fieldnr) |
|
1033 |
{
|
|
1034 |
return &(res)->fields[fieldnr]; |
|
1035 |
}
|
|
1036 |
||
1037 |
MYSQL_FIELD * STDCALL mysql_fetch_fields(MYSQL_RES *res) |
|
1038 |
{
|
|
1039 |
return (res)->fields; |
|
1040 |
}
|
|
1041 |
||
1042 |
MYSQL_ROW_OFFSET STDCALL mysql_row_tell(MYSQL_RES *res) |
|
1043 |
{
|
|
1044 |
return res->data_cursor; |
|
1045 |
}
|
|
1046 |
||
1047 |
MYSQL_FIELD_OFFSET STDCALL mysql_field_tell(MYSQL_RES *res) |
|
1048 |
{
|
|
1049 |
return (res)->current_field; |
|
1050 |
}
|
|
1051 |
||
1052 |
/* MYSQL */
|
|
1053 |
||
1054 |
unsigned int STDCALL mysql_field_count(MYSQL *mysql) |
|
1055 |
{
|
|
1056 |
return mysql->field_count; |
|
1057 |
}
|
|
1058 |
||
1059 |
my_ulonglong STDCALL mysql_affected_rows(MYSQL *mysql) |
|
1060 |
{
|
|
1061 |
return mysql->affected_rows; |
|
1062 |
}
|
|
1063 |
||
1064 |
my_ulonglong STDCALL mysql_insert_id(MYSQL *mysql) |
|
1065 |
{
|
|
1066 |
return mysql->insert_id; |
|
1067 |
}
|
|
1068 |
||
1069 |
const char *STDCALL mysql_sqlstate(MYSQL *mysql) |
|
1070 |
{
|
|
1071 |
return mysql ? mysql->net.sqlstate : cant_connect_sqlstate; |
|
1072 |
}
|
|
1073 |
||
1074 |
uint STDCALL mysql_warning_count(MYSQL *mysql) |
|
1075 |
{
|
|
1076 |
return mysql->warning_count; |
|
1077 |
}
|
|
1078 |
||
1079 |
const char *STDCALL mysql_info(MYSQL *mysql) |
|
1080 |
{
|
|
1081 |
return mysql->info; |
|
1082 |
}
|
|
1083 |
||
1084 |
ulong STDCALL mysql_thread_id(MYSQL *mysql) |
|
1085 |
{
|
|
1086 |
return (mysql)->thread_id; |
|
1087 |
}
|
|
1088 |
||
1089 |
const char * STDCALL mysql_character_set_name(MYSQL *mysql) |
|
1090 |
{
|
|
1091 |
return mysql->charset->csname; |
|
1092 |
}
|
|
1093 |
||
1094 |
void STDCALL mysql_get_character_set_info(MYSQL *mysql, MY_CHARSET_INFO *csinfo) |
|
1095 |
{
|
|
1096 |
csinfo->number = mysql->charset->number; |
|
1097 |
csinfo->state = mysql->charset->state; |
|
1098 |
csinfo->csname = mysql->charset->csname; |
|
1099 |
csinfo->name = mysql->charset->name; |
|
1100 |
csinfo->comment = mysql->charset->comment; |
|
1101 |
csinfo->mbminlen = mysql->charset->mbminlen; |
|
1102 |
csinfo->mbmaxlen = mysql->charset->mbmaxlen; |
|
1103 |
||
1104 |
if (mysql->options.charset_dir) |
|
1105 |
csinfo->dir = mysql->options.charset_dir; |
|
1106 |
else
|
|
1107 |
csinfo->dir = charsets_dir; |
|
1108 |
}
|
|
1109 |
||
1110 |
uint STDCALL mysql_thread_safe(void) |
|
1111 |
{
|
|
1112 |
return 1; |
|
1113 |
}
|
|
1114 |
||
1115 |
||
1116 |
my_bool STDCALL mysql_embedded(void) |
|
1117 |
{
|
|
1118 |
#ifdef EMBEDDED_LIBRARY
|
|
1119 |
return 1; |
|
1120 |
#else
|
|
1121 |
return 0; |
|
1122 |
#endif
|
|
1123 |
}
|
|
1124 |
||
1125 |
/****************************************************************************
|
|
1126 |
Some support functions
|
|
1127 |
****************************************************************************/
|
|
1128 |
||
1129 |
/*
|
|
1130 |
Functions called my my_net_init() to set some application specific variables
|
|
1131 |
*/
|
|
1132 |
||
1133 |
void my_net_local_init(NET *net) |
|
1134 |
{
|
|
1135 |
net->max_packet= (uint) net_buffer_length; |
|
1136 |
my_net_set_read_timeout(net, CLIENT_NET_READ_TIMEOUT); |
|
1137 |
my_net_set_write_timeout(net, CLIENT_NET_WRITE_TIMEOUT); |
|
1138 |
net->retry_count= 1; |
|
1139 |
net->max_packet_size= max(net_buffer_length, max_allowed_packet); |
|
1140 |
}
|
|
1141 |
||
1142 |
/*
|
|
1143 |
This function is used to create HEX string that you
|
|
1144 |
can use in a SQL statement in of the either ways:
|
|
1145 |
INSERT INTO blob_column VALUES (0xAABBCC); (any MySQL version)
|
|
1146 |
INSERT INTO blob_column VALUES (X'AABBCC'); (4.1 and higher)
|
|
1147 |
|
|
1148 |
The string in "from" is encoded to a HEX string.
|
|
1149 |
The result is placed in "to" and a terminating null byte is appended.
|
|
1150 |
|
|
1151 |
The string pointed to by "from" must be "length" bytes long.
|
|
1152 |
You must allocate the "to" buffer to be at least length*2+1 bytes long.
|
|
1153 |
Each character needs two bytes, and you need room for the terminating
|
|
1154 |
null byte. When mysql_hex_string() returns, the contents of "to" will
|
|
1155 |
be a null-terminated string. The return value is the length of the
|
|
1156 |
encoded string, not including the terminating null character.
|
|
1157 |
||
1158 |
The return value does not contain any leading 0x or a leading X' and
|
|
1159 |
trailing '. The caller must supply whichever of those is desired.
|
|
1160 |
*/
|
|
1161 |
||
1162 |
ulong STDCALL |
|
1163 |
mysql_hex_string(char *to, const char *from, ulong length) |
|
1164 |
{
|
|
1165 |
char *to0= to; |
|
1166 |
const char *end; |
|
1167 |
||
1168 |
for (end= from + length; from < end; from++) |
|
1169 |
{
|
|
1170 |
*to++= _dig_vec_upper[((unsigned char) *from) >> 4]; |
|
1171 |
*to++= _dig_vec_upper[((unsigned char) *from) & 0x0F]; |
|
1172 |
}
|
|
1173 |
*to= '\0'; |
|
1174 |
return (ulong) (to-to0); |
|
1175 |
}
|
|
1176 |
||
1177 |
/*
|
|
1178 |
Add escape characters to a string (blob?) to make it suitable for a insert
|
|
1179 |
to should at least have place for length*2+1 chars
|
|
1180 |
Returns the length of the to string
|
|
1181 |
*/
|
|
1182 |
||
1183 |
ulong STDCALL |
|
1184 |
mysql_escape_string(char *to,const char *from,ulong length) |
|
1185 |
{
|
|
1186 |
return escape_string_for_mysql(default_charset_info, to, 0, from, length); |
|
1187 |
}
|
|
1188 |
||
1189 |
ulong STDCALL |
|
1190 |
mysql_real_escape_string(MYSQL *mysql, char *to,const char *from, |
|
1191 |
ulong length) |
|
1192 |
{
|
|
1193 |
if (mysql->server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES) |
|
1194 |
return escape_quotes_for_mysql(mysql->charset, to, 0, from, length); |
|
1195 |
return escape_string_for_mysql(mysql->charset, to, 0, from, length); |
|
1196 |
}
|
|
1197 |
||
1198 |
void STDCALL |
|
1199 |
myodbc_remove_escape(MYSQL *mysql,char *name) |
|
1200 |
{
|
|
1201 |
char *to; |
|
1202 |
#ifdef USE_MB
|
|
1203 |
my_bool use_mb_flag=use_mb(mysql->charset); |
|
1204 |
char *end; |
|
1205 |
if (use_mb_flag) |
|
1206 |
for (end=name; *end ; end++) ; |
|
1207 |
#endif
|
|
1208 |
||
1209 |
for (to=name ; *name ; name++) |
|
1210 |
{
|
|
1211 |
#ifdef USE_MB
|
|
1212 |
int l; |
|
1213 |
if (use_mb_flag && (l = my_ismbchar( mysql->charset, name , end ) ) ) |
|
1214 |
{
|
|
1215 |
while (l--) |
|
1216 |
*to++ = *name++; |
|
1217 |
name--; |
|
1218 |
continue; |
|
1219 |
}
|
|
1220 |
#endif
|
|
1221 |
if (*name == '\\' && name[1]) |
|
1222 |
name++; |
|
1223 |
*to++= *name; |
|
1224 |
}
|
|
1225 |
*to=0; |
|
1226 |
}
|
|
1227 |
||
1228 |
int cli_unbuffered_fetch(MYSQL *mysql, char **row) |
|
1229 |
{
|
|
1230 |
if (packet_error == cli_safe_read(mysql)) |
|
1231 |
return 1; |
|
1232 |
||
1233 |
*row= ((mysql->net.read_pos[0] == 254) ? NULL : |
|
1234 |
(char*) (mysql->net.read_pos+1)); |
|
1235 |
return 0; |
|
1236 |
}
|
|
1237 |
||
1238 |
/********************************************************************
|
|
1239 |
Transactional APIs
|
|
1240 |
*********************************************************************/
|
|
1241 |
||
1242 |
/*
|
|
1243 |
Commit the current transaction
|
|
1244 |
*/
|
|
1245 |
||
1246 |
my_bool STDCALL mysql_commit(MYSQL * mysql) |
|
1247 |
{
|
|
1248 |
DBUG_ENTER("mysql_commit"); |
|
1249 |
DBUG_RETURN((my_bool) mysql_real_query(mysql, "commit", 6)); |
|
1250 |
}
|
|
1251 |
||
1252 |
/*
|
|
1253 |
Rollback the current transaction
|
|
1254 |
*/
|
|
1255 |
||
1256 |
my_bool STDCALL mysql_rollback(MYSQL * mysql) |
|
1257 |
{
|
|
1258 |
DBUG_ENTER("mysql_rollback"); |
|
1259 |
DBUG_RETURN((my_bool) mysql_real_query(mysql, "rollback", 8)); |
|
1260 |
}
|
|
1261 |
||
1262 |
||
1263 |
/*
|
|
1264 |
Set autocommit to either true or false
|
|
1265 |
*/
|
|
1266 |
||
1267 |
my_bool STDCALL mysql_autocommit(MYSQL * mysql, my_bool auto_mode) |
|
1268 |
{
|
|
1269 |
DBUG_ENTER("mysql_autocommit"); |
|
1270 |
DBUG_PRINT("enter", ("mode : %d", auto_mode)); |
|
1271 |
||
1272 |
DBUG_RETURN((my_bool) mysql_real_query(mysql, auto_mode ? |
|
1273 |
"set autocommit=1":"set autocommit=0", |
|
1274 |
16)); |
|
1275 |
}
|
|
1276 |
||
1277 |
||
1278 |
/********************************************************************
|
|
1279 |
Multi query execution + SPs APIs
|
|
1280 |
*********************************************************************/
|
|
1281 |
||
1282 |
/*
|
|
1283 |
Returns true/false to indicate whether any more query results exist
|
|
1284 |
to be read using mysql_next_result()
|
|
1285 |
*/
|
|
1286 |
||
1287 |
my_bool STDCALL mysql_more_results(MYSQL *mysql) |
|
1288 |
{
|
|
1289 |
my_bool res; |
|
1290 |
DBUG_ENTER("mysql_more_results"); |
|
1291 |
||
1292 |
res= ((mysql->server_status & SERVER_MORE_RESULTS_EXISTS) ? 1: 0); |
|
1293 |
DBUG_PRINT("exit",("More results exists ? %d", res)); |
|
1294 |
DBUG_RETURN(res); |
|
1295 |
}
|
|
1296 |
||
1297 |
||
1298 |
/*
|
|
1299 |
Reads and returns the next query results
|
|
1300 |
*/
|
|
1301 |
int STDCALL mysql_next_result(MYSQL *mysql) |
|
1302 |
{
|
|
1303 |
DBUG_ENTER("mysql_next_result"); |
|
1304 |
||
1305 |
if (mysql->status != MYSQL_STATUS_READY) |
|
1306 |
{
|
|
1307 |
set_mysql_error(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate); |
|
1308 |
DBUG_RETURN(1); |
|
1309 |
}
|
|
1310 |
||
1311 |
net_clear_error(&mysql->net); |
|
1312 |
mysql->affected_rows= ~(my_ulonglong) 0; |
|
1313 |
||
1314 |
if (mysql->server_status & SERVER_MORE_RESULTS_EXISTS) |
|
1315 |
DBUG_RETURN((*mysql->methods->next_result)(mysql)); |
|
1316 |
||
1317 |
DBUG_RETURN(-1); /* No more results */ |
|
1318 |
}
|
|
1319 |
||
1320 |
||
1321 |
MYSQL_RES * STDCALL mysql_use_result(MYSQL *mysql) |
|
1322 |
{
|
|
1323 |
return (*mysql->methods->use_result)(mysql); |
|
1324 |
}
|
|
1325 |
||
1326 |
my_bool STDCALL mysql_read_query_result(MYSQL *mysql) |
|
1327 |
{
|
|
1328 |
return (*mysql->methods->read_query_result)(mysql); |
|
1329 |
}
|
|
1330 |