390.1.5
by Monty Taylor
Moved more functions into drizzle.c as part of the split of code. |
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 |
*/
|
|
19 |
||
20 |
#include <config.h> |
|
492.3.25
by Lee
Changes to get drizzle building on Solaris 10 (SPARC) |
21 |
#include <signal.h> |
390.1.5
by Monty Taylor
Moved more functions into drizzle.c as part of the split of code. |
22 |
|
543
by Monty Taylor
Renamed drizzle_common again. Removed sql_common. (empty) |
23 |
#include <drizzled/common.h> |
390.1.5
by Monty Taylor
Moved more functions into drizzle.c as part of the split of code. |
24 |
#include <libdrizzle/libdrizzle.h> |
542
by Monty Taylor
Cleaned up the last commit. |
25 |
#include <libdrizzle/pack.h> |
390.1.5
by Monty Taylor
Moved more functions into drizzle.c as part of the split of code. |
26 |
#include <libdrizzle/errmsg.h> |
27 |
#include <libdrizzle/drizzle.h> |
|
538
by Monty Taylor
Moved gettext.h into drizzled in anticipation of the new client lib. |
28 |
#include <drizzled/gettext.h> |
390.1.6
by Monty Taylor
Oh dear god the changes. The changes. I'd tell you what they are, but I'd just be making stuff up. Suffice it to day it's mostly all around splitting files in libdrizzle into different files and removing interdepends. And whatever else I happened to see... |
29 |
#include <libdrizzle/net_serv.h> |
30 |
#include <libdrizzle/drizzle_data.h> |
|
31 |
#include <libdrizzle/local_infile.h> |
|
32 |
||
390.1.5
by Monty Taylor
Moved more functions into drizzle.c as part of the split of code. |
33 |
#include "libdrizzle_priv.h" |
34 |
||
35 |
#include <vio/violite.h> |
|
36 |
||
37 |
#include <stdio.h> |
|
38 |
#include <stdlib.h> |
|
39 |
#include <stdarg.h> |
|
40 |
#include <string.h> |
|
41 |
#include <netdb.h> |
|
42 |
#include <assert.h> |
|
390.1.6
by Monty Taylor
Oh dear god the changes. The changes. I'd tell you what they are, but I'd just be making stuff up. Suffice it to day it's mostly all around splitting files in libdrizzle into different files and removing interdepends. And whatever else I happened to see... |
43 |
#include <pwd.h> |
44 |
#include <sys/socket.h> |
|
45 |
||
390.1.5
by Monty Taylor
Moved more functions into drizzle.c as part of the split of code. |
46 |
|
47 |
#define CONNECT_TIMEOUT 0
|
|
48 |
||
49 |
static bool drizzle_client_init= false; |
|
50 |
unsigned int drizzle_server_last_errno; |
|
51 |
||
52 |
/* Server error code and message */
|
|
53 |
char drizzle_server_last_error[DRIZZLE_ERRMSG_SIZE]; |
|
54 |
||
390.1.6
by Monty Taylor
Oh dear god the changes. The changes. I'd tell you what they are, but I'd just be making stuff up. Suffice it to day it's mostly all around splitting files in libdrizzle into different files and removing interdepends. And whatever else I happened to see... |
55 |
/*
|
56 |
Note that the drizzle argument must be initialized with drizzle_init()
|
|
57 |
before calling drizzle_connect !
|
|
58 |
*/
|
|
59 |
||
60 |
||
61 |
||
62 |
static DRIZZLE_METHODS client_methods= |
|
63 |
{
|
|
64 |
cli_read_query_result, /* read_query_result */ |
|
65 |
cli_advanced_command, /* advanced_command */ |
|
66 |
cli_read_rows, /* read_rows */ |
|
67 |
cli_use_result, /* use_result */ |
|
68 |
cli_fetch_lengths, /* fetch_lengths */ |
|
69 |
cli_flush_use_result, /* flush_use_result */ |
|
70 |
cli_list_fields, /* list_fields */ |
|
71 |
cli_unbuffered_fetch, /* unbuffered_fetch */ |
|
72 |
cli_read_statistics, /* read_statistics */ |
|
73 |
cli_read_query_result, /* next_result */ |
|
74 |
cli_read_change_user_result, /* read_change_user_result */ |
|
75 |
};
|
|
76 |
||
77 |
||
78 |
||
390.1.5
by Monty Taylor
Moved more functions into drizzle.c as part of the split of code. |
79 |
/****************************************************************************
|
80 |
Init DRIZZLE structure or allocate one
|
|
81 |
****************************************************************************/
|
|
82 |
||
83 |
DRIZZLE * |
|
84 |
drizzle_create(DRIZZLE *ptr) |
|
85 |
{
|
|
86 |
||
87 |
if (!drizzle_client_init) |
|
88 |
{
|
|
89 |
drizzle_client_init=true; |
|
90 |
||
91 |
if (!drizzle_get_default_port()) |
|
92 |
{
|
|
93 |
drizzle_set_default_port(DRIZZLE_PORT); |
|
94 |
{
|
|
95 |
struct servent *serv_ptr; |
|
96 |
char *env; |
|
97 |
||
98 |
/*
|
|
99 |
if builder specifically requested a default port, use that
|
|
100 |
(even if it coincides with our factory default).
|
|
101 |
only if they didn't do we check /etc/services (and, failing
|
|
102 |
on that, fall back to the factory default of 4427).
|
|
103 |
either default can be overridden by the environment variable
|
|
104 |
DRIZZLE_TCP_PORT, which in turn can be overridden with command
|
|
105 |
line options.
|
|
106 |
*/
|
|
107 |
||
108 |
#if DRIZZLE_PORT_DEFAULT == 0
|
|
109 |
if ((serv_ptr = getservbyname("drizzle", "tcp"))) |
|
395
by Brian Aker
Fixed uint/ushort issue in libdrizzle |
110 |
drizzle_set_default_port((uint32_t) ntohs((uint16_t) serv_ptr->s_port)); |
390.1.5
by Monty Taylor
Moved more functions into drizzle.c as part of the split of code. |
111 |
#endif
|
112 |
if ((env = getenv("DRIZZLE_TCP_PORT"))) |
|
395
by Brian Aker
Fixed uint/ushort issue in libdrizzle |
113 |
drizzle_set_default_port((uint32_t) atoi(env)); |
390.1.5
by Monty Taylor
Moved more functions into drizzle.c as part of the split of code. |
114 |
}
|
115 |
}
|
|
116 |
#if defined(SIGPIPE)
|
|
117 |
(void) signal(SIGPIPE, SIG_IGN); |
|
118 |
#endif
|
|
119 |
}
|
|
120 |
||
121 |
if (ptr == NULL) |
|
122 |
{
|
|
123 |
ptr= (DRIZZLE *) malloc(sizeof(DRIZZLE)); |
|
124 |
||
125 |
if (ptr == NULL) |
|
126 |
{
|
|
390.1.6
by Monty Taylor
Oh dear god the changes. The changes. I'd tell you what they are, but I'd just be making stuff up. Suffice it to day it's mostly all around splitting files in libdrizzle into different files and removing interdepends. And whatever else I happened to see... |
127 |
drizzle_set_error(NULL, CR_OUT_OF_MEMORY, sqlstate_get_unknown()); |
390.1.5
by Monty Taylor
Moved more functions into drizzle.c as part of the split of code. |
128 |
return 0; |
129 |
}
|
|
130 |
memset(ptr, 0, sizeof(DRIZZLE)); |
|
131 |
ptr->free_me=1; |
|
132 |
}
|
|
133 |
else
|
|
134 |
{
|
|
135 |
memset(ptr, 0, sizeof(DRIZZLE)); |
|
136 |
}
|
|
137 |
||
138 |
ptr->options.connect_timeout= CONNECT_TIMEOUT; |
|
390.1.6
by Monty Taylor
Oh dear god the changes. The changes. I'd tell you what they are, but I'd just be making stuff up. Suffice it to day it's mostly all around splitting files in libdrizzle into different files and removing interdepends. And whatever else I happened to see... |
139 |
strcpy(ptr->net.sqlstate, sqlstate_get_not_error()); |
390.1.5
by Monty Taylor
Moved more functions into drizzle.c as part of the split of code. |
140 |
|
141 |
/*
|
|
142 |
Only enable LOAD DATA INFILE by default if configured with
|
|
143 |
--enable-local-infile
|
|
144 |
*/
|
|
145 |
||
146 |
#if defined(ENABLED_LOCAL_INFILE)
|
|
147 |
ptr->options.client_flag|= CLIENT_LOCAL_FILES; |
|
148 |
#endif
|
|
149 |
||
150 |
ptr->options.methods_to_use= DRIZZLE_OPT_GUESS_CONNECTION; |
|
151 |
ptr->options.report_data_truncation= true; /* default */ |
|
152 |
||
153 |
/*
|
|
154 |
By default we don't reconnect because it could silently corrupt data (after
|
|
155 |
reconnection you potentially lose table locks, user variables, session
|
|
156 |
variables (transactions but they are specifically dealt with in
|
|
157 |
drizzle_reconnect()).
|
|
158 |
This is a change: < 5.0.3 drizzle->reconnect was set to 1 by default.
|
|
159 |
How this change impacts existing apps:
|
|
160 |
- existing apps which relyed on the default will see a behaviour change;
|
|
161 |
they will have to set reconnect=1 after drizzle_connect().
|
|
162 |
- existing apps which explicitely asked for reconnection (the only way they
|
|
163 |
could do it was by setting drizzle.reconnect to 1 after drizzle_connect())
|
|
164 |
will not see a behaviour change.
|
|
165 |
- existing apps which explicitely asked for no reconnection
|
|
166 |
(drizzle.reconnect=0) will not see a behaviour change.
|
|
167 |
*/
|
|
168 |
ptr->reconnect= 0; |
|
169 |
||
170 |
return ptr; |
|
171 |
}
|
|
390.1.6
by Monty Taylor
Oh dear god the changes. The changes. I'd tell you what they are, but I'd just be making stuff up. Suffice it to day it's mostly all around splitting files in libdrizzle into different files and removing interdepends. And whatever else I happened to see... |
172 |
|
173 |
||
174 |
static void read_user_name(char *name) |
|
175 |
{
|
|
176 |
if (geteuid() == 0) |
|
177 |
strcpy(name,"root"); /* allow use of surun */ |
|
178 |
else
|
|
179 |
{
|
|
180 |
#ifdef HAVE_GETPWUID
|
|
181 |
struct passwd *skr; |
|
182 |
const char *str; |
|
183 |
if ((str=getlogin()) == NULL) |
|
184 |
{
|
|
185 |
if ((skr=getpwuid(geteuid())) != NULL) |
|
186 |
str=skr->pw_name; |
|
187 |
else if (!(str=getenv("USER")) && !(str=getenv("LOGNAME")) && |
|
188 |
!(str=getenv("LOGIN"))) |
|
189 |
str="UNKNOWN_USER"; |
|
190 |
}
|
|
191 |
strncpy(name,str,USERNAME_LENGTH); |
|
192 |
#elif HAVE_CUSERID
|
|
193 |
(void) cuserid(name); |
|
194 |
#else
|
|
195 |
strcpy(name,"UNKNOWN_USER"); |
|
196 |
#endif
|
|
197 |
}
|
|
198 |
return; |
|
199 |
}
|
|
200 |
||
201 |
DRIZZLE * |
|
202 |
drizzle_connect(DRIZZLE *drizzle,const char *host, const char *user, |
|
203 |
const char *passwd, const char *db, |
|
204 |
uint32_t port, |
|
205 |
const char * unix_port __attribute__((__unused__)), |
|
206 |
uint32_t client_flag) |
|
207 |
{
|
|
208 |
char buff[NAME_LEN+USERNAME_LENGTH+100]; |
|
209 |
char *end,*host_info=NULL; |
|
210 |
uint32_t pkt_length; |
|
211 |
NET *net= &drizzle->net; |
|
212 |
||
213 |
drizzle->methods= &client_methods; |
|
214 |
net->vio = 0; /* If something goes wrong */ |
|
215 |
drizzle->client_flag=0; /* For handshake */ |
|
216 |
||
217 |
/* Some empty-string-tests are done because of ODBC */
|
|
218 |
if (!host || !host[0]) |
|
219 |
host=drizzle->options.host; |
|
220 |
if (!user || !user[0]) |
|
221 |
{
|
|
222 |
user=drizzle->options.user; |
|
223 |
if (!user) |
|
224 |
user= ""; |
|
225 |
}
|
|
226 |
if (!passwd) |
|
227 |
{
|
|
228 |
passwd=drizzle->options.password; |
|
229 |
if (!passwd) |
|
230 |
passwd= ""; |
|
231 |
}
|
|
232 |
if (!db || !db[0]) |
|
233 |
db=drizzle->options.db; |
|
234 |
if (!port) |
|
235 |
port=drizzle->options.port; |
|
236 |
||
237 |
drizzle->server_status=SERVER_STATUS_AUTOCOMMIT; |
|
238 |
||
239 |
/*
|
|
240 |
Part 0: Grab a socket and connect it to the server
|
|
241 |
*/
|
|
242 |
if (!net->vio) |
|
243 |
{
|
|
244 |
struct addrinfo *res_lst, hints, *t_res; |
|
245 |
int gai_errno; |
|
246 |
char port_buf[NI_MAXSERV]; |
|
247 |
||
248 |
if (!port) |
|
249 |
port= drizzle_port; |
|
250 |
||
251 |
if (!host) |
|
252 |
host= LOCAL_HOST; |
|
253 |
||
254 |
snprintf(host_info=buff, sizeof(buff)-1, ER(CR_TCP_CONNECTION), host); |
|
255 |
||
256 |
memset(&hints, 0, sizeof(hints)); |
|
257 |
hints.ai_socktype= SOCK_STREAM; |
|
258 |
||
259 |
snprintf(port_buf, NI_MAXSERV, "%d", port); |
|
260 |
gai_errno= getaddrinfo(host, port_buf, &hints, &res_lst); |
|
261 |
||
262 |
if (gai_errno != 0) |
|
263 |
{
|
|
264 |
drizzle_set_extended_error(drizzle, CR_UNKNOWN_HOST, sqlstate_get_unknown(), |
|
265 |
ER(CR_UNKNOWN_HOST), host, errno); |
|
266 |
||
267 |
goto error; |
|
268 |
}
|
|
269 |
||
270 |
for (t_res= res_lst; t_res != NULL; t_res= t_res->ai_next) |
|
271 |
{
|
|
272 |
int sock= socket(t_res->ai_family, t_res->ai_socktype, |
|
273 |
t_res->ai_protocol); |
|
274 |
if (sock < 0) |
|
275 |
continue; |
|
276 |
||
277 |
net->vio= vio_new(sock, VIO_TYPE_TCPIP, VIO_BUFFERED_READ); |
|
278 |
if (! net->vio ) |
|
279 |
{
|
|
280 |
close(sock); |
|
281 |
continue; |
|
282 |
}
|
|
283 |
||
284 |
if (connect_with_timeout(sock, t_res->ai_addr, t_res->ai_addrlen, drizzle->options.connect_timeout)) |
|
285 |
{
|
|
286 |
vio_delete(net->vio); |
|
287 |
net->vio= 0; |
|
288 |
continue; |
|
289 |
}
|
|
290 |
break; |
|
291 |
}
|
|
292 |
||
293 |
freeaddrinfo(res_lst); |
|
294 |
}
|
|
295 |
||
296 |
if (!net->vio) |
|
297 |
{
|
|
298 |
drizzle_set_extended_error(drizzle, CR_CONN_HOST_ERROR, sqlstate_get_unknown(), |
|
299 |
ER(CR_CONN_HOST_ERROR), host, errno); |
|
300 |
goto error; |
|
301 |
}
|
|
302 |
||
303 |
if (my_net_init(net, net->vio)) |
|
304 |
{
|
|
305 |
vio_delete(net->vio); |
|
306 |
net->vio = 0; |
|
307 |
drizzle_set_error(drizzle, CR_OUT_OF_MEMORY, sqlstate_get_unknown()); |
|
308 |
goto error; |
|
309 |
}
|
|
310 |
vio_keepalive(net->vio,true); |
|
311 |
||
312 |
/* If user set read_timeout, let it override the default */
|
|
313 |
if (drizzle->options.read_timeout) |
|
314 |
my_net_set_read_timeout(net, drizzle->options.read_timeout); |
|
315 |
||
316 |
/* If user set write_timeout, let it override the default */
|
|
317 |
if (drizzle->options.write_timeout) |
|
318 |
my_net_set_write_timeout(net, drizzle->options.write_timeout); |
|
319 |
||
320 |
if (drizzle->options.max_allowed_packet) |
|
321 |
net->max_packet_size= drizzle->options.max_allowed_packet; |
|
322 |
||
323 |
/* Get version info */
|
|
324 |
drizzle->protocol_version= PROTOCOL_VERSION; /* Assume this */ |
|
325 |
if (drizzle->options.connect_timeout && |
|
326 |
vio_poll_read(net->vio, drizzle->options.connect_timeout)) |
|
327 |
{
|
|
328 |
drizzle_set_extended_error(drizzle, CR_SERVER_LOST, sqlstate_get_unknown(), |
|
329 |
ER(CR_SERVER_LOST_INITIAL_COMM_WAIT), |
|
330 |
errno); |
|
331 |
goto error; |
|
332 |
}
|
|
333 |
||
334 |
/*
|
|
335 |
Part 1: Connection established, read and parse first packet
|
|
336 |
*/
|
|
337 |
||
338 |
if ((pkt_length=cli_safe_read(drizzle)) == packet_error) |
|
339 |
{
|
|
340 |
if (drizzle->net.last_errno == CR_SERVER_LOST) |
|
341 |
drizzle_set_extended_error(drizzle, CR_SERVER_LOST, sqlstate_get_unknown(), |
|
342 |
ER(CR_SERVER_LOST_INITIAL_COMM_READ), |
|
343 |
errno); |
|
344 |
goto error; |
|
345 |
}
|
|
346 |
/* Check if version of protocol matches current one */
|
|
347 |
||
348 |
drizzle->protocol_version= net->read_pos[0]; |
|
349 |
if (drizzle->protocol_version != PROTOCOL_VERSION) |
|
350 |
{
|
|
351 |
drizzle_set_extended_error(drizzle, CR_VERSION_ERROR, sqlstate_get_unknown(), |
|
352 |
ER(CR_VERSION_ERROR), drizzle->protocol_version, |
|
353 |
PROTOCOL_VERSION); |
|
354 |
goto error; |
|
355 |
}
|
|
356 |
end= strchr((char*) net->read_pos+1, '\0'); |
|
357 |
drizzle->thread_id=uint4korr(end+1); |
|
358 |
end+=5; |
|
359 |
/*
|
|
360 |
Scramble is split into two parts because old clients does not understand
|
|
361 |
long scrambles; here goes the first part.
|
|
362 |
*/
|
|
363 |
strncpy(drizzle->scramble, end, SCRAMBLE_LENGTH_323); |
|
364 |
end+= SCRAMBLE_LENGTH_323+1; |
|
365 |
||
395
by Brian Aker
Fixed uint/ushort issue in libdrizzle |
366 |
if (pkt_length >= (uint32_t) (end+1 - (char*) net->read_pos)) |
390.1.6
by Monty Taylor
Oh dear god the changes. The changes. I'd tell you what they are, but I'd just be making stuff up. Suffice it to day it's mostly all around splitting files in libdrizzle into different files and removing interdepends. And whatever else I happened to see... |
367 |
drizzle->server_capabilities=uint2korr(end); |
395
by Brian Aker
Fixed uint/ushort issue in libdrizzle |
368 |
if (pkt_length >= (uint32_t) (end+18 - (char*) net->read_pos)) |
390.1.6
by Monty Taylor
Oh dear god the changes. The changes. I'd tell you what they are, but I'd just be making stuff up. Suffice it to day it's mostly all around splitting files in libdrizzle into different files and removing interdepends. And whatever else I happened to see... |
369 |
{
|
370 |
/* New protocol with 16 bytes to describe server characteristics */
|
|
371 |
drizzle->server_language=end[2]; |
|
372 |
drizzle->server_status=uint2korr(end+3); |
|
373 |
}
|
|
374 |
end+= 18; |
|
395
by Brian Aker
Fixed uint/ushort issue in libdrizzle |
375 |
if (pkt_length >= (uint32_t) (end + SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323 + 1 - |
390.1.6
by Monty Taylor
Oh dear god the changes. The changes. I'd tell you what they are, but I'd just be making stuff up. Suffice it to day it's mostly all around splitting files in libdrizzle into different files and removing interdepends. And whatever else I happened to see... |
376 |
(char *) net->read_pos)) |
377 |
strncpy(drizzle->scramble+SCRAMBLE_LENGTH_323, end, |
|
378 |
SCRAMBLE_LENGTH-SCRAMBLE_LENGTH_323); |
|
379 |
else
|
|
380 |
drizzle->server_capabilities&= ~CLIENT_SECURE_CONNECTION; |
|
381 |
||
382 |
if (drizzle->options.secure_auth && passwd[0] && |
|
383 |
!(drizzle->server_capabilities & CLIENT_SECURE_CONNECTION)) |
|
384 |
{
|
|
385 |
drizzle_set_error(drizzle, CR_SECURE_AUTH, sqlstate_get_unknown()); |
|
386 |
goto error; |
|
387 |
}
|
|
388 |
||
389 |
/* Save connection information */
|
|
390 |
if (!(drizzle->host_info= (char *)malloc(strlen(host_info)+1+strlen(host)+1 |
|
391 |
+(end - (char*) net->read_pos))) || |
|
392 |
!(drizzle->user=strdup(user)) || |
|
393 |
!(drizzle->passwd=strdup(passwd))) |
|
394 |
{
|
|
395 |
drizzle_set_error(drizzle, CR_OUT_OF_MEMORY, sqlstate_get_unknown()); |
|
396 |
goto error; |
|
397 |
}
|
|
398 |
drizzle->host= drizzle->host_info+strlen(host_info)+1; |
|
399 |
drizzle->server_version= drizzle->host+strlen(host)+1; |
|
400 |
strcpy(drizzle->host_info,host_info); |
|
401 |
strcpy(drizzle->host,host); |
|
402 |
strcpy(drizzle->server_version,(char*) net->read_pos+1); |
|
403 |
drizzle->port=port; |
|
404 |
||
405 |
/*
|
|
406 |
Part 2: format and send client info to the server for access check
|
|
407 |
*/
|
|
408 |
||
409 |
client_flag|=drizzle->options.client_flag; |
|
410 |
client_flag|=CLIENT_CAPABILITIES; |
|
411 |
if (client_flag & CLIENT_MULTI_STATEMENTS) |
|
412 |
client_flag|= CLIENT_MULTI_RESULTS; |
|
413 |
||
414 |
if (db) |
|
415 |
client_flag|=CLIENT_CONNECT_WITH_DB; |
|
416 |
||
417 |
/* Remove options that server doesn't support */
|
|
418 |
client_flag= ((client_flag & |
|
419 |
~(CLIENT_COMPRESS | CLIENT_SSL)) | |
|
420 |
(client_flag & drizzle->server_capabilities)); |
|
421 |
client_flag&= ~CLIENT_COMPRESS; |
|
422 |
||
423 |
int4store(buff, client_flag); |
|
424 |
int4store(buff+4, net->max_packet_size); |
|
425 |
buff[8]= (char) 45; // utf8 charset number |
|
426 |
memset(buff+9, 0, 32-9); |
|
427 |
end= buff+32; |
|
428 |
||
429 |
drizzle->client_flag=client_flag; |
|
430 |
||
431 |
/* This needs to be changed as it's not useful with big packets */
|
|
432 |
if (user && user[0]) |
|
433 |
strncpy(end,user,USERNAME_LENGTH); /* Max user name */ |
|
434 |
else
|
|
435 |
read_user_name((char*) end); |
|
436 |
||
437 |
/* We have to handle different version of handshake here */
|
|
438 |
end= strchr(end, '\0') + 1; |
|
439 |
if (passwd[0]) |
|
440 |
{
|
|
441 |
{
|
|
442 |
*end++= SCRAMBLE_LENGTH; |
|
443 |
memset(end, 0, SCRAMBLE_LENGTH-1); |
|
444 |
memcpy(end, passwd, strlen(passwd)); |
|
445 |
end+= SCRAMBLE_LENGTH; |
|
446 |
}
|
|
447 |
}
|
|
448 |
else
|
|
449 |
*end++= '\0'; /* empty password */ |
|
450 |
||
451 |
/* Add database if needed */
|
|
452 |
if (db && (drizzle->server_capabilities & CLIENT_CONNECT_WITH_DB)) |
|
453 |
{
|
|
454 |
end= strncpy(end, db, NAME_LEN) + NAME_LEN + 1; |
|
455 |
drizzle->db= strdup(db); |
|
456 |
db= 0; |
|
457 |
}
|
|
458 |
/* Write authentication package */
|
|
459 |
if (my_net_write(net, (unsigned char*) buff, (size_t) (end-buff)) || net_flush(net)) |
|
460 |
{
|
|
461 |
drizzle_set_extended_error(drizzle, CR_SERVER_LOST, sqlstate_get_unknown(), |
|
462 |
ER(CR_SERVER_LOST_SEND_AUTH), |
|
463 |
errno); |
|
464 |
goto error; |
|
465 |
}
|
|
466 |
||
467 |
/*
|
|
468 |
Part 3: Authorization data's been sent. Now server can reply with
|
|
469 |
OK-packet, or re-request scrambled password.
|
|
470 |
*/
|
|
471 |
||
472 |
if ((pkt_length=cli_safe_read(drizzle)) == packet_error) |
|
473 |
{
|
|
474 |
if (drizzle->net.last_errno == CR_SERVER_LOST) |
|
475 |
drizzle_set_extended_error(drizzle, CR_SERVER_LOST, sqlstate_get_unknown(), |
|
476 |
ER(CR_SERVER_LOST_READ_AUTH), |
|
477 |
errno); |
|
478 |
goto error; |
|
479 |
}
|
|
480 |
||
481 |
if (client_flag & CLIENT_COMPRESS) /* We will use compression */ |
|
482 |
net->compress=1; |
|
483 |
||
484 |
||
485 |
if (db && drizzle_select_db(drizzle, db)) |
|
486 |
{
|
|
487 |
if (drizzle->net.last_errno == CR_SERVER_LOST) |
|
488 |
drizzle_set_extended_error(drizzle, CR_SERVER_LOST, sqlstate_get_unknown(), |
|
489 |
ER(CR_SERVER_LOST_SETTING_DB), |
|
490 |
errno); |
|
491 |
goto error; |
|
492 |
}
|
|
493 |
||
494 |
||
495 |
return(drizzle); |
|
496 |
||
497 |
error: |
|
498 |
{
|
|
499 |
/* Free alloced memory */
|
|
500 |
drizzle_disconnect(drizzle); |
|
501 |
drizzle_close_free(drizzle); |
|
502 |
if (!(((uint32_t) client_flag) & CLIENT_REMEMBER_OPTIONS)) |
|
503 |
drizzle_close_free_options(drizzle); |
|
504 |
}
|
|
505 |
return(0); |
|
506 |
}
|
|
507 |
||
508 |
||
509 |
||
510 |
||
511 |
/**************************************************************************
|
|
512 |
Set current database
|
|
513 |
**************************************************************************/
|
|
514 |
||
515 |
int
|
|
516 |
drizzle_select_db(DRIZZLE *drizzle, const char *db) |
|
517 |
{
|
|
518 |
int error; |
|
519 |
||
520 |
if ((error=simple_command(drizzle,COM_INIT_DB, (const unsigned char*) db, |
|
521 |
(uint32_t) strlen(db),0))) |
|
522 |
return(error); |
|
523 |
if (drizzle->db != NULL) |
|
524 |
free(drizzle->db); |
|
525 |
drizzle->db=strdup(db); |
|
526 |
return(0); |
|
527 |
}
|
|
528 |
||
529 |
bool drizzle_reconnect(DRIZZLE *drizzle) |
|
530 |
{
|
|
531 |
DRIZZLE tmp_drizzle; |
|
532 |
assert(drizzle); |
|
533 |
||
534 |
if (!drizzle->reconnect || |
|
535 |
(drizzle->server_status & SERVER_STATUS_IN_TRANS) || !drizzle->host_info) |
|
536 |
{
|
|
537 |
/* Allow reconnect next time */
|
|
538 |
drizzle->server_status&= ~SERVER_STATUS_IN_TRANS; |
|
539 |
drizzle_set_error(drizzle, CR_SERVER_GONE_ERROR, sqlstate_get_unknown()); |
|
540 |
return(1); |
|
541 |
}
|
|
542 |
drizzle_create(&tmp_drizzle); |
|
543 |
tmp_drizzle.options= drizzle->options; |
|
544 |
tmp_drizzle.options.my_cnf_file= tmp_drizzle.options.my_cnf_group= 0; |
|
545 |
||
546 |
if (!drizzle_connect(&tmp_drizzle,drizzle->host,drizzle->user,drizzle->passwd, |
|
547 |
drizzle->db, drizzle->port, 0, |
|
548 |
drizzle->client_flag | CLIENT_REMEMBER_OPTIONS)) |
|
549 |
{
|
|
550 |
drizzle->net.last_errno= tmp_drizzle.net.last_errno; |
|
551 |
strcpy(drizzle->net.last_error, tmp_drizzle.net.last_error); |
|
552 |
strcpy(drizzle->net.sqlstate, tmp_drizzle.net.sqlstate); |
|
553 |
return(1); |
|
554 |
}
|
|
555 |
||
556 |
tmp_drizzle.reconnect= 1; |
|
557 |
tmp_drizzle.free_me= drizzle->free_me; |
|
558 |
||
559 |
/* Don't free options as these are now used in tmp_drizzle */
|
|
560 |
memset(&drizzle->options, 0, sizeof(drizzle->options)); |
|
561 |
drizzle->free_me=0; |
|
562 |
drizzle_close(drizzle); |
|
563 |
*drizzle=tmp_drizzle; |
|
564 |
net_clear(&drizzle->net, 1); |
|
565 |
drizzle->affected_rows= ~(uint64_t) 0; |
|
566 |
return(0); |
|
567 |
}
|
|
568 |
||
390.1.5
by Monty Taylor
Moved more functions into drizzle.c as part of the split of code. |
569 |
/**************************************************************************
|
570 |
Shut down connection
|
|
571 |
**************************************************************************/
|
|
572 |
||
573 |
void drizzle_disconnect(DRIZZLE *drizzle) |
|
574 |
{
|
|
575 |
int save_errno= errno; |
|
576 |
if (drizzle->net.vio != 0) |
|
577 |
{
|
|
578 |
vio_delete(drizzle->net.vio); |
|
579 |
drizzle->net.vio= 0; /* Marker */ |
|
580 |
}
|
|
581 |
net_end(&drizzle->net); |
|
582 |
free_old_query(drizzle); |
|
583 |
errno= save_errno; |
|
584 |
}
|
|
585 |
||
586 |
||
390.1.6
by Monty Taylor
Oh dear god the changes. The changes. I'd tell you what they are, but I'd just be making stuff up. Suffice it to day it's mostly all around splitting files in libdrizzle into different files and removing interdepends. And whatever else I happened to see... |
587 |
/*************************************************************************
|
588 |
Send a QUIT to the server and close the connection
|
|
589 |
If handle is alloced by DRIZZLE connect free it.
|
|
590 |
*************************************************************************/
|
|
591 |
||
592 |
void drizzle_close_free_options(DRIZZLE *drizzle) |
|
593 |
{
|
|
594 |
if (drizzle->options.user != NULL) |
|
595 |
free(drizzle->options.user); |
|
596 |
if (drizzle->options.host != NULL) |
|
597 |
free(drizzle->options.host); |
|
598 |
if (drizzle->options.password != NULL) |
|
599 |
free(drizzle->options.password); |
|
600 |
if (drizzle->options.db != NULL) |
|
601 |
free(drizzle->options.db); |
|
602 |
if (drizzle->options.my_cnf_file != NULL) |
|
603 |
free(drizzle->options.my_cnf_file); |
|
604 |
if (drizzle->options.my_cnf_group != NULL) |
|
605 |
free(drizzle->options.my_cnf_group); |
|
606 |
if (drizzle->options.client_ip != NULL) |
|
607 |
free(drizzle->options.client_ip); |
|
608 |
memset(&drizzle->options, 0, sizeof(drizzle->options)); |
|
609 |
return; |
|
610 |
}
|
|
611 |
||
612 |
||
613 |
void drizzle_close_free(DRIZZLE *drizzle) |
|
614 |
{
|
|
615 |
if (drizzle->host_info != NULL) |
|
616 |
free((unsigned char*) drizzle->host_info); |
|
617 |
if (drizzle->user != NULL) |
|
618 |
free(drizzle->user); |
|
619 |
if (drizzle->passwd != NULL) |
|
620 |
free(drizzle->passwd); |
|
621 |
if (drizzle->db != NULL) |
|
622 |
free(drizzle->db); |
|
623 |
if (drizzle->info_buffer != NULL) |
|
624 |
free(drizzle->info_buffer); |
|
625 |
drizzle->info_buffer= 0; |
|
626 |
||
627 |
/* Clear pointers for better safety */
|
|
628 |
drizzle->host_info= drizzle->user= drizzle->passwd= drizzle->db= 0; |
|
629 |
}
|
|
630 |
||
631 |
||
632 |
void drizzle_close(DRIZZLE *drizzle) |
|
633 |
{
|
|
634 |
if (drizzle) /* Some simple safety */ |
|
635 |
{
|
|
636 |
/* If connection is still up, send a QUIT message */
|
|
637 |
if (drizzle->net.vio != 0) |
|
638 |
{
|
|
639 |
free_old_query(drizzle); |
|
640 |
drizzle->status=DRIZZLE_STATUS_READY; /* Force command */ |
|
641 |
drizzle->reconnect=0; |
|
642 |
simple_command(drizzle,COM_QUIT,(unsigned char*) 0,0,1); |
|
643 |
drizzle_disconnect(drizzle); /* Sets drizzle->net.vio= 0 */ |
|
644 |
}
|
|
645 |
drizzle_close_free_options(drizzle); |
|
646 |
drizzle_close_free(drizzle); |
|
647 |
if (drizzle->free_me) |
|
648 |
free((unsigned char*) drizzle); |
|
649 |
}
|
|
650 |
return; |
|
651 |
}
|
|
652 |
||
653 |
||
654 |
bool cli_read_query_result(DRIZZLE *drizzle) |
|
655 |
{
|
|
656 |
unsigned char *pos; |
|
657 |
uint32_t field_count; |
|
658 |
DRIZZLE_DATA *fields; |
|
659 |
uint32_t length; |
|
660 |
||
661 |
if ((length = cli_safe_read(drizzle)) == packet_error) |
|
662 |
return(1); |
|
663 |
free_old_query(drizzle); /* Free old result */ |
|
664 |
get_info: |
|
665 |
pos=(unsigned char*) drizzle->net.read_pos; |
|
666 |
if ((field_count= net_field_length(&pos)) == 0) |
|
667 |
{
|
|
668 |
drizzle->affected_rows= net_field_length_ll(&pos); |
|
669 |
drizzle->insert_id= net_field_length_ll(&pos); |
|
670 |
||
671 |
drizzle->server_status= uint2korr(pos); pos+=2; |
|
672 |
drizzle->warning_count= uint2korr(pos); pos+=2; |
|
673 |
||
674 |
if (pos < drizzle->net.read_pos+length && net_field_length(&pos)) |
|
675 |
drizzle->info=(char*) pos; |
|
676 |
return(0); |
|
677 |
}
|
|
678 |
if (field_count == NULL_LENGTH) /* LOAD DATA LOCAL INFILE */ |
|
679 |
{
|
|
680 |
int error; |
|
681 |
||
682 |
if (!(drizzle->options.client_flag & CLIENT_LOCAL_FILES)) |
|
683 |
{
|
|
684 |
drizzle_set_error(drizzle, CR_MALFORMED_PACKET, sqlstate_get_unknown()); |
|
685 |
return(1); |
|
686 |
}
|
|
687 |
||
688 |
error= handle_local_infile(drizzle,(char*) pos); |
|
689 |
if ((length= cli_safe_read(drizzle)) == packet_error || error) |
|
690 |
return(1); |
|
691 |
goto get_info; /* Get info packet */ |
|
692 |
}
|
|
693 |
if (!(drizzle->server_status & SERVER_STATUS_AUTOCOMMIT)) |
|
694 |
drizzle->server_status|= SERVER_STATUS_IN_TRANS; |
|
695 |
||
696 |
if (!(fields=cli_read_rows(drizzle,(DRIZZLE_FIELD*)0, 7))) |
|
697 |
return(1); |
|
395
by Brian Aker
Fixed uint/ushort issue in libdrizzle |
698 |
if (!(drizzle->fields= unpack_fields(fields, (uint32_t) field_count, 0))) |
390.1.6
by Monty Taylor
Oh dear god the changes. The changes. I'd tell you what they are, but I'd just be making stuff up. Suffice it to day it's mostly all around splitting files in libdrizzle into different files and removing interdepends. And whatever else I happened to see... |
699 |
return(1); |
700 |
drizzle->status= DRIZZLE_STATUS_GET_RESULT; |
|
395
by Brian Aker
Fixed uint/ushort issue in libdrizzle |
701 |
drizzle->field_count= (uint32_t) field_count; |
390.1.6
by Monty Taylor
Oh dear god the changes. The changes. I'd tell you what they are, but I'd just be making stuff up. Suffice it to day it's mostly all around splitting files in libdrizzle into different files and removing interdepends. And whatever else I happened to see... |
702 |
return(0); |
703 |
}
|
|
704 |
||
705 |
||
706 |
/*
|
|
707 |
Send the query and return so we can do something else.
|
|
708 |
Needs to be followed by drizzle_read_query_result() when we want to
|
|
709 |
finish processing it.
|
|
710 |
*/
|
|
711 |
||
712 |
int32_t
|
|
713 |
drizzle_send_query(DRIZZLE *drizzle, const char* query, uint32_t length) |
|
714 |
{
|
|
715 |
return(simple_command(drizzle, COM_QUERY, (unsigned char*) query, length, 1)); |
|
716 |
}
|
|
717 |
||
718 |
||
719 |
int32_t
|
|
720 |
drizzle_real_query(DRIZZLE *drizzle, const char *query, uint32_t length) |
|
721 |
{
|
|
722 |
if (drizzle_send_query(drizzle,query,length)) |
|
723 |
return(1); |
|
724 |
return((int) (*drizzle->methods->read_query_result)(drizzle)); |
|
725 |
}
|
|
726 |
||
727 |
||
728 |
/**************************************************************************
|
|
729 |
Alloc result struct for buffered results. All rows are read to buffer.
|
|
730 |
drizzle_data_seek may be used.
|
|
731 |
**************************************************************************/
|
|
732 |
||
733 |
DRIZZLE_RES * drizzle_store_result(DRIZZLE *drizzle) |
|
734 |
{
|
|
735 |
DRIZZLE_RES *result; |
|
736 |
||
737 |
if (!drizzle->fields) |
|
738 |
return(0); |
|
739 |
if (drizzle->status != DRIZZLE_STATUS_GET_RESULT) |
|
740 |
{
|
|
741 |
drizzle_set_error(drizzle, CR_COMMANDS_OUT_OF_SYNC, sqlstate_get_unknown()); |
|
742 |
return(0); |
|
743 |
}
|
|
744 |
drizzle->status=DRIZZLE_STATUS_READY; /* server is ready */ |
|
395
by Brian Aker
Fixed uint/ushort issue in libdrizzle |
745 |
if (!(result=(DRIZZLE_RES*) malloc((uint32_t) (sizeof(DRIZZLE_RES)+ |
390.1.6
by Monty Taylor
Oh dear god the changes. The changes. I'd tell you what they are, but I'd just be making stuff up. Suffice it to day it's mostly all around splitting files in libdrizzle into different files and removing interdepends. And whatever else I happened to see... |
746 |
sizeof(uint32_t) * |
747 |
drizzle->field_count)))) |
|
748 |
{
|
|
749 |
drizzle_set_error(drizzle, CR_OUT_OF_MEMORY, sqlstate_get_unknown()); |
|
750 |
return(0); |
|
751 |
}
|
|
752 |
memset(result, 0,(sizeof(DRIZZLE_RES)+ sizeof(uint32_t) * |
|
753 |
drizzle->field_count)); |
|
754 |
result->methods= drizzle->methods; |
|
755 |
result->eof= 1; /* Marker for buffered */ |
|
756 |
result->lengths= (uint32_t*) (result+1); |
|
757 |
if (!(result->data= |
|
758 |
(*drizzle->methods->read_rows)(drizzle,drizzle->fields,drizzle->field_count))) |
|
759 |
{
|
|
760 |
free((unsigned char*) result); |
|
761 |
return(0); |
|
762 |
}
|
|
763 |
drizzle->affected_rows= result->row_count= result->data->rows; |
|
764 |
result->data_cursor= result->data->data; |
|
765 |
result->fields= drizzle->fields; |
|
766 |
result->field_count= drizzle->field_count; |
|
767 |
/* The rest of result members is zeroed in malloc */
|
|
768 |
drizzle->fields=0; /* fields is now in result */ |
|
769 |
/* just in case this was mistakenly called after drizzle_stmt_execute() */
|
|
770 |
drizzle->unbuffered_fetch_owner= 0; |
|
771 |
return(result); /* Data fetched */ |
|
772 |
}
|
|
773 |
||
774 |
||
775 |
/**************************************************************************
|
|
776 |
Alloc struct for use with unbuffered reads. Data is fetched by domand
|
|
777 |
when calling to drizzle_fetch_row.
|
|
778 |
DRIZZLE_DATA_seek is a noop.
|
|
779 |
||
780 |
No other queries may be specified with the same DRIZZLE handle.
|
|
781 |
There shouldn't be much processing per row because DRIZZLE server shouldn't
|
|
782 |
have to wait for the client (and will not wait more than 30 sec/packet).
|
|
783 |
**************************************************************************/
|
|
784 |
||
785 |
DRIZZLE_RES * cli_use_result(DRIZZLE *drizzle) |
|
786 |
{
|
|
787 |
DRIZZLE_RES *result; |
|
788 |
||
789 |
if (!drizzle->fields) |
|
790 |
return(0); |
|
791 |
if (drizzle->status != DRIZZLE_STATUS_GET_RESULT) |
|
792 |
{
|
|
793 |
drizzle_set_error(drizzle, CR_COMMANDS_OUT_OF_SYNC, sqlstate_get_unknown()); |
|
794 |
return(0); |
|
795 |
}
|
|
796 |
if (!(result=(DRIZZLE_RES*) malloc(sizeof(*result)+ |
|
797 |
sizeof(uint32_t)*drizzle->field_count))) |
|
798 |
return(0); |
|
799 |
memset(result, 0, sizeof(*result)+ sizeof(uint32_t)*drizzle->field_count); |
|
800 |
result->lengths=(uint32_t*) (result+1); |
|
801 |
result->methods= drizzle->methods; |
|
802 |
if (!(result->row=(DRIZZLE_ROW) |
|
803 |
malloc(sizeof(result->row[0])*(drizzle->field_count+1)))) |
|
804 |
{ /* Ptrs: to one row */ |
|
805 |
free((unsigned char*) result); |
|
806 |
return(0); |
|
807 |
}
|
|
808 |
result->fields= drizzle->fields; |
|
809 |
result->field_count= drizzle->field_count; |
|
810 |
result->current_field=0; |
|
811 |
result->handle= drizzle; |
|
812 |
result->current_row= 0; |
|
813 |
drizzle->fields=0; /* fields is now in result */ |
|
814 |
drizzle->status=DRIZZLE_STATUS_USE_RESULT; |
|
815 |
drizzle->unbuffered_fetch_owner= &result->unbuffered_fetch_cancelled; |
|
816 |
return(result); /* Data is read to be fetched */ |
|
817 |
}
|
|
818 |
||
819 |
||
820 |
||
390.1.5
by Monty Taylor
Moved more functions into drizzle.c as part of the split of code. |
821 |
/**
|
822 |
Set the internal error message to DRIZZLE handler
|
|
823 |
||
824 |
@param drizzle connection handle (client side)
|
|
825 |
@param errcode CR_ error code, passed to ER macro to get
|
|
826 |
error text
|
|
827 |
@parma sqlstate SQL standard sqlstate
|
|
828 |
*/
|
|
829 |
||
830 |
void drizzle_set_error(DRIZZLE *drizzle, int errcode, const char *sqlstate) |
|
831 |
{
|
|
832 |
NET *net; |
|
833 |
assert(drizzle != 0); |
|
834 |
||
835 |
if (drizzle) |
|
836 |
{
|
|
837 |
net= &drizzle->net; |
|
838 |
net->last_errno= errcode; |
|
839 |
strcpy(net->last_error, ER(errcode)); |
|
840 |
strcpy(net->sqlstate, sqlstate); |
|
841 |
}
|
|
842 |
else
|
|
843 |
{
|
|
844 |
drizzle_server_last_errno= errcode; |
|
845 |
strcpy(drizzle_server_last_error, ER(errcode)); |
|
846 |
}
|
|
847 |
return; |
|
848 |
}
|
|
849 |
||
850 |
||
851 |
unsigned int drizzle_errno(const DRIZZLE *drizzle) |
|
852 |
{
|
|
853 |
return drizzle ? drizzle->net.last_errno : drizzle_server_last_errno; |
|
854 |
}
|
|
855 |
||
856 |
||
857 |
const char * drizzle_error(const DRIZZLE *drizzle) |
|
858 |
{
|
|
859 |
return drizzle ? _(drizzle->net.last_error) : _(drizzle_server_last_error); |
|
860 |
}
|
|
861 |
||
862 |
/**
|
|
863 |
Set an error message on the client.
|
|
864 |
||
865 |
@param drizzle connection handle
|
|
866 |
@param errcode CR_* errcode, for client errors
|
|
390.1.6
by Monty Taylor
Oh dear god the changes. The changes. I'd tell you what they are, but I'd just be making stuff up. Suffice it to day it's mostly all around splitting files in libdrizzle into different files and removing interdepends. And whatever else I happened to see... |
867 |
@param sqlstate SQL standard sql state, sqlstate_get_unknown() for the
|
390.1.5
by Monty Taylor
Moved more functions into drizzle.c as part of the split of code. |
868 |
majority of client errors.
|
869 |
@param format error message template, in sprintf format
|
|
870 |
@param ... variable number of arguments
|
|
871 |
*/
|
|
872 |
||
873 |
void drizzle_set_extended_error(DRIZZLE *drizzle, int errcode, |
|
874 |
const char *sqlstate, |
|
875 |
const char *format, ...) |
|
876 |
{
|
|
877 |
NET *net; |
|
878 |
va_list args; |
|
879 |
assert(drizzle != 0); |
|
880 |
||
881 |
net= &drizzle->net; |
|
882 |
net->last_errno= errcode; |
|
883 |
va_start(args, format); |
|
884 |
vsnprintf(net->last_error, sizeof(net->last_error)-1, |
|
885 |
format, args); |
|
886 |
va_end(args); |
|
887 |
strcpy(net->sqlstate, sqlstate); |
|
888 |
||
889 |
return; |
|
890 |
}
|
|
390.1.6
by Monty Taylor
Oh dear god the changes. The changes. I'd tell you what they are, but I'd just be making stuff up. Suffice it to day it's mostly all around splitting files in libdrizzle into different files and removing interdepends. And whatever else I happened to see... |
891 |
|
892 |
||
893 |
||
894 |
/*
|
|
895 |
Flush result set sent from server
|
|
896 |
*/
|
|
897 |
||
898 |
void cli_flush_use_result(DRIZZLE *drizzle) |
|
899 |
{
|
|
900 |
/* Clear the current execution status */
|
|
901 |
for (;;) |
|
902 |
{
|
|
903 |
uint32_t pkt_len; |
|
904 |
if ((pkt_len=cli_safe_read(drizzle)) == packet_error) |
|
905 |
break; |
|
906 |
if (pkt_len <= 8 && drizzle->net.read_pos[0] == DRIZZLE_PROTOCOL_NO_MORE_DATA) |
|
907 |
{
|
|
908 |
char *pos= (char*) drizzle->net.read_pos + 1; |
|
909 |
drizzle->warning_count=uint2korr(pos); pos+=2; |
|
910 |
drizzle->server_status=uint2korr(pos); pos+=2; |
|
911 |
||
912 |
break; /* End of data */ |
|
913 |
}
|
|
914 |
}
|
|
915 |
return; |
|
916 |
}
|
|
917 |
||
918 |
/**************************************************************************
|
|
919 |
Get column lengths of the current row
|
|
920 |
If one uses drizzle_use_result, res->lengths contains the length information,
|
|
921 |
else the lengths are calculated from the offset between pointers.
|
|
922 |
**************************************************************************/
|
|
923 |
||
924 |
void cli_fetch_lengths(uint32_t *to, DRIZZLE_ROW column, uint32_t field_count) |
|
925 |
{
|
|
926 |
uint32_t *prev_length; |
|
927 |
char *start=0; |
|
928 |
DRIZZLE_ROW end; |
|
929 |
||
930 |
prev_length=0; /* Keep gcc happy */ |
|
931 |
for (end=column + field_count + 1 ; column != end ; column++, to++) |
|
932 |
{
|
|
933 |
if (!*column) |
|
934 |
{
|
|
935 |
*to= 0; /* Null */ |
|
936 |
continue; |
|
937 |
}
|
|
938 |
if (start) /* Found end of prev string */ |
|
939 |
*prev_length= (uint32_t) (*column-start-1); |
|
940 |
start= *column; |
|
941 |
prev_length= to; |
|
942 |
}
|
|
943 |
}
|
|
944 |