libdrizzle Developer Documentation
Main Page
Related Pages
Modules
Data Structures
Files
File List
Globals
libdrizzle
result.c
Go to the documentation of this file.
1
/*
2
* Drizzle Client & Protocol Library
3
*
4
* Copyright (C) 2008 Eric Day (eday@oddments.org)
5
* All rights reserved.
6
*
7
* Use and distribution licensed under the BSD license. See
8
* the COPYING file in this directory for full text.
9
*/
10
16
#include "
common.h
"
17
18
/*
19
* Common definitions
20
*/
21
22
drizzle_result_st
*
drizzle_result_create
(
drizzle_con_st
*con,
23
drizzle_result_st
*result)
24
{
25
if
(result == NULL)
26
{
27
result= malloc(
sizeof
(
drizzle_result_st
));
28
if
(result == NULL)
29
{
30
drizzle_set_error
(con->
drizzle
,
"drizzle_result_create"
,
"malloc"
);
31
return
NULL;
32
}
33
34
memset(result, 0,
sizeof
(
drizzle_result_st
));
35
result->
options
|=
DRIZZLE_RESULT_ALLOCATED
;
36
}
37
else
38
memset(result, 0,
sizeof
(
drizzle_result_st
));
39
40
result->
con
= con;
41
con->
result
= result;
42
43
if
(con->
result_list
)
44
con->
result_list
->
prev
= result;
45
result->
next
= con->
result_list
;
46
con->
result_list
= result;
47
con->
result_count
++;
48
49
return
result;
50
}
51
52
drizzle_result_st
*
drizzle_result_clone
(
drizzle_con_st
*con,
53
drizzle_result_st
*result,
54
drizzle_result_st
*from)
55
{
56
result=
drizzle_result_create
(con, result);
57
if
(result == NULL)
58
return
NULL;
59
60
result->
options
|= (from->
options
&
61
(
drizzle_result_options_t
)~
DRIZZLE_RESULT_ALLOCATED
);
62
63
drizzle_result_set_info
(result, from->
info
);
64
result->
error_code
= from->
error_code
;
65
drizzle_result_set_sqlstate
(result, from->
sqlstate
);
66
result->
warning_count
= from->
warning_count
;
67
result->
insert_id
= from->
insert_id
;
68
result->
affected_rows
= from->
affected_rows
;
69
result->
column_count
= from->
column_count
;
70
result->
row_count
= from->
row_count
;
71
72
return
result;
73
}
74
75
void
drizzle_result_free
(
drizzle_result_st
*result)
76
{
77
drizzle_column_st
*column;
78
uint64_t x;
79
80
for
(column= result->
column_list
; column != NULL; column= result->
column_list
)
81
drizzle_column_free
(column);
82
83
if
(result->
column_buffer
!= NULL)
84
free(result->
column_buffer
);
85
86
if
(result->
options
&
DRIZZLE_RESULT_BUFFER_ROW
)
87
{
88
for
(x= 0; x < result->
row_count
; x++)
89
drizzle_row_free
(result, result->
row_list
[x]);
90
91
free(result->
row_list
);
92
free(result->
field_sizes_list
);
93
}
94
95
if
(result->
con
->
result_list
== result)
96
result->
con
->
result_list
= result->
next
;
97
if
(result->
prev
)
98
result->
prev
->
next
= result->
next
;
99
if
(result->
next
)
100
result->
next
->
prev
= result->
prev
;
101
result->
con
->
result_count
--;
102
103
if
(result->
options
&
DRIZZLE_RESULT_ALLOCATED
)
104
free(result);
105
}
106
107
void
drizzle_result_free_all
(
drizzle_con_st
*con)
108
{
109
while
(con->
result_list
!= NULL)
110
drizzle_result_free
(con->
result_list
);
111
}
112
113
drizzle_con_st
*
drizzle_result_drizzle_con
(
drizzle_result_st
*result)
114
{
115
return
result->
con
;
116
}
117
118
bool
drizzle_result_eof
(
drizzle_result_st
*result)
119
{
120
return
result->
options
&
DRIZZLE_RESULT_EOF_PACKET
;
121
}
122
123
const
char
*
drizzle_result_info
(
drizzle_result_st
*result)
124
{
125
return
result->
info
;
126
}
127
128
const
char
*
drizzle_result_error
(
drizzle_result_st
*result)
129
{
130
return
result->
info
;
131
}
132
133
uint16_t
drizzle_result_error_code
(
drizzle_result_st
*result)
134
{
135
return
result->
error_code
;
136
}
137
138
const
char
*
drizzle_result_sqlstate
(
drizzle_result_st
*result)
139
{
140
return
result->
sqlstate
;
141
}
142
143
uint16_t
drizzle_result_warning_count
(
drizzle_result_st
*result)
144
{
145
return
result->
warning_count
;
146
}
147
148
uint64_t
drizzle_result_insert_id
(
drizzle_result_st
*result)
149
{
150
return
result->
insert_id
;
151
}
152
153
uint64_t
drizzle_result_affected_rows
(
drizzle_result_st
*result)
154
{
155
return
result->
affected_rows
;
156
}
157
158
uint16_t
drizzle_result_column_count
(
drizzle_result_st
*result)
159
{
160
return
result->
column_count
;
161
}
162
163
uint64_t
drizzle_result_row_count
(
drizzle_result_st
*result)
164
{
165
return
result->
row_count
;
166
}
167
168
/*
169
* Client definitions
170
*/
171
172
drizzle_result_st
*
drizzle_result_read
(
drizzle_con_st
*con,
173
drizzle_result_st
*result,
174
drizzle_return_t
*ret_ptr)
175
{
176
if
(
drizzle_state_none
(con))
177
{
178
con->
result
=
drizzle_result_create
(con, result);
179
if
(con->
result
== NULL)
180
{
181
*ret_ptr=
DRIZZLE_RETURN_MEMORY
;
182
return
NULL;
183
}
184
185
drizzle_state_push
(con,
drizzle_state_result_read
);
186
drizzle_state_push
(con,
drizzle_state_packet_read
);
187
}
188
189
*ret_ptr=
drizzle_state_loop
(con);
190
return
con->
result
;
191
}
192
193
drizzle_return_t
drizzle_result_buffer
(
drizzle_result_st
*result)
194
{
195
drizzle_return_t
ret;
196
drizzle_row_t
row;
197
drizzle_row_t
*row_list;
198
size_t
**field_sizes_list;
199
200
if
(!(result->
options
&
DRIZZLE_RESULT_BUFFER_COLUMN
))
201
{
202
ret=
drizzle_column_buffer
(result);
203
if
(ret !=
DRIZZLE_RETURN_OK
)
204
return
ret;
205
}
206
207
if
(result->
column_count
== 0)
208
{
209
result->
options
|=
DRIZZLE_RESULT_BUFFER_ROW
;
210
return
DRIZZLE_RETURN_OK
;
211
}
212
213
while
(1)
214
{
215
row=
drizzle_row_buffer
(result, &ret);
216
if
(ret !=
DRIZZLE_RETURN_OK
)
217
return
ret;
218
219
if
(row == NULL)
220
break
;
221
222
if
(result->
row_list_size
< result->
row_count
)
223
{
224
row_list= realloc(result->
row_list
,
sizeof
(
drizzle_row_t
) *
225
((
size_t
)(result->
row_list_size
) +
226
DRIZZLE_ROW_GROW_SIZE
));
227
if
(row_list == NULL)
228
{
229
drizzle_row_free
(result, row);
230
drizzle_set_error
(result->
con
->
drizzle
,
"drizzle_result_buffer"
,
231
"realloc"
);
232
return
DRIZZLE_RETURN_MEMORY
;
233
}
234
235
result->
row_list
= row_list;
236
237
field_sizes_list= realloc(result->
field_sizes_list
,
sizeof
(
size_t
*) *
238
((
size_t
)(result->
row_list_size
) +
239
DRIZZLE_ROW_GROW_SIZE
));
240
if
(field_sizes_list == NULL)
241
{
242
drizzle_row_free
(result, row);
243
drizzle_set_error
(result->
con
->
drizzle
,
"drizzle_result_buffer"
,
244
"realloc"
);
245
return
DRIZZLE_RETURN_MEMORY
;
246
}
247
248
result->
field_sizes_list
= field_sizes_list;
249
250
result->
row_list_size
+=
DRIZZLE_ROW_GROW_SIZE
;
251
}
252
253
result->
row_list
[result->
row_current
- 1]= row;
254
result->
field_sizes_list
[result->
row_current
- 1]= result->
field_sizes
;
255
}
256
257
result->
options
|=
DRIZZLE_RESULT_BUFFER_ROW
;
258
return
DRIZZLE_RETURN_OK
;
259
}
260
261
size_t
drizzle_result_row_size
(
drizzle_result_st
*result)
262
{
263
return
result->
con
->
packet_size
;
264
}
265
266
/*
267
* Server definitions
268
*/
269
270
drizzle_return_t
drizzle_result_write
(
drizzle_con_st
*con,
271
drizzle_result_st
*result,
bool
flush)
272
{
273
if
(
drizzle_state_none
(con))
274
{
275
con->
result
= result;
276
277
if
(flush)
278
drizzle_state_push
(con,
drizzle_state_write
);
279
280
drizzle_state_push
(con,
drizzle_state_result_write
);
281
}
282
283
return
drizzle_state_loop
(con);
284
}
285
286
void
drizzle_result_set_row_size
(
drizzle_result_st
*result,
size_t
size)
287
{
288
result->
con
->
packet_size
= size;
289
}
290
291
void
drizzle_result_calc_row_size
(
drizzle_result_st
*result,
292
const
drizzle_field_t
*field,
293
const
size_t
*size)
294
{
295
uint16_t x;
296
297
result->
con
->
packet_size
= 0;
298
299
for
(x= 0; x < result->
column_count
; x++)
300
{
301
if
(field[x] == NULL)
302
result->
con
->
packet_size
++;
303
else
if
(size[x] < 251)
304
result->
con
->
packet_size
+= (1 + size[x]);
305
else
if
(size[x] < 65536)
306
result->
con
->
packet_size
+= (3 + size[x]);
307
else
if
(size[x] < 16777216)
308
result->
con
->
packet_size
+= (4 + size[x]);
309
else
310
result->
con
->
packet_size
+= (9 + size[x]);
311
}
312
}
313
314
void
drizzle_result_set_eof
(
drizzle_result_st
*result,
bool
eof)
315
{
316
if
(eof)
317
result->
options
|=
DRIZZLE_RESULT_EOF_PACKET
;
318
else
319
result->
options
&= (
drizzle_result_options_t
)~
DRIZZLE_RESULT_EOF_PACKET
;
320
}
321
322
void
drizzle_result_set_info
(
drizzle_result_st
*result,
const
char
*info)
323
{
324
if
(info == NULL)
325
result->
info
[0]= 0;
326
else
327
{
328
strncpy(result->
info
, info,
DRIZZLE_MAX_INFO_SIZE
);
329
result->
info
[
DRIZZLE_MAX_INFO_SIZE
- 1]= 0;
330
}
331
}
332
333
void
drizzle_result_set_error
(
drizzle_result_st
*result,
const
char
*error)
334
{
335
drizzle_result_set_info
(result, error);
336
}
337
338
void
drizzle_result_set_error_code
(
drizzle_result_st
*result,
339
uint16_t error_code)
340
{
341
result->
error_code
= error_code;
342
}
343
344
void
drizzle_result_set_sqlstate
(
drizzle_result_st
*result,
345
const
char
*sqlstate)
346
{
347
if
(sqlstate == NULL)
348
result->
sqlstate
[0]= 0;
349
else
350
{
351
strncpy(result->
sqlstate
, sqlstate,
DRIZZLE_MAX_SQLSTATE_SIZE
+ 1);
352
result->
sqlstate
[
DRIZZLE_MAX_SQLSTATE_SIZE
]= 0;
353
}
354
}
355
356
void
drizzle_result_set_warning_count
(
drizzle_result_st
*result,
357
uint16_t warning_count)
358
{
359
result->
warning_count
= warning_count;
360
}
361
362
void
drizzle_result_set_insert_id
(
drizzle_result_st
*result,
363
uint64_t insert_id)
364
{
365
result->
insert_id
= insert_id;
366
}
367
368
void
drizzle_result_set_affected_rows
(
drizzle_result_st
*result,
369
uint64_t affected_rows)
370
{
371
result->
affected_rows
= affected_rows;
372
}
373
374
void
drizzle_result_set_column_count
(
drizzle_result_st
*result,
375
uint16_t column_count)
376
{
377
result->
column_count
= column_count;
378
}
379
380
/*
381
* Internal state functions.
382
*/
383
384
drizzle_return_t
drizzle_state_result_read
(
drizzle_con_st
*con)
385
{
386
drizzle_return_t
ret;
387
388
drizzle_log_debug
(con->
drizzle
,
"drizzle_state_result_read"
);
389
390
/* Assume the entire result packet will fit in the buffer. */
391
if
(con->
buffer_size
< con->
packet_size
)
392
{
393
drizzle_state_push
(con,
drizzle_state_read
);
394
return
DRIZZLE_RETURN_OK
;
395
}
396
397
if
(con->
buffer_ptr
[0] == 0)
398
{
399
con->
buffer_ptr
++;
400
/* We can ignore the returns since we've buffered the entire packet. */
401
con->
result
->
affected_rows
=
drizzle_unpack_length
(con, &ret);
402
con->
result
->
insert_id
=
drizzle_unpack_length
(con, &ret);
403
con->
status
=
drizzle_get_byte2
(con->
buffer_ptr
);
404
con->
result
->
warning_count
=
drizzle_get_byte2
(con->
buffer_ptr
+ 2);
405
con->
buffer_ptr
+= 4;
406
con->
buffer_size
-= 5;
407
con->
packet_size
-= 5;
408
if
(con->
packet_size
> 0)
409
{
410
/* Skip one byte for message size. */
411
con->
buffer_ptr
+= 1;
412
con->
buffer_size
-= 1;
413
con->
packet_size
-= 1;
414
}
415
ret=
DRIZZLE_RETURN_OK
;
416
}
417
else
if
(con->
buffer_ptr
[0] == 254)
418
{
419
con->
result
->
options
=
DRIZZLE_RESULT_EOF_PACKET
;
420
con->
result
->
warning_count
=
drizzle_get_byte2
(con->
buffer_ptr
+ 1);
421
con->
status
=
drizzle_get_byte2
(con->
buffer_ptr
+ 3);
422
con->
buffer_ptr
+= 5;
423
con->
buffer_size
-= 5;
424
con->
packet_size
-= 5;
425
ret=
DRIZZLE_RETURN_OK
;
426
}
427
else
if
(con->
buffer_ptr
[0] == 255)
428
{
429
con->
result
->
error_code
=
drizzle_get_byte2
(con->
buffer_ptr
+ 1);
430
con->
drizzle
->
error_code
= con->
result
->
error_code
;
431
/* Byte 3 is always a '#' character, skip it. */
432
memcpy(con->
result
->
sqlstate
, con->
buffer_ptr
+ 4,
433
DRIZZLE_MAX_SQLSTATE_SIZE
);
434
con->
result
->
sqlstate
[
DRIZZLE_MAX_SQLSTATE_SIZE
]= 0;
435
memcpy(con->
drizzle
->
sqlstate
, con->
result
->
sqlstate
,
436
DRIZZLE_MAX_SQLSTATE_SIZE
+ 1);
437
con->
buffer_ptr
+= 9;
438
con->
buffer_size
-= 9;
439
con->
packet_size
-= 9;
440
ret=
DRIZZLE_RETURN_ERROR_CODE
;
441
}
442
else
443
{
444
/* We can ignore the return since we've buffered the entire packet. */
445
con->
result
->
column_count
= (uint16_t)
drizzle_unpack_length
(con, &ret);
446
ret=
DRIZZLE_RETURN_OK
;
447
}
448
449
if
(con->
packet_size
> 0)
450
{
451
snprintf(con->
drizzle
->
last_error
,
DRIZZLE_MAX_ERROR_SIZE
,
"%.*s"
,
452
(int32_t)con->
packet_size
, con->
buffer_ptr
);
453
snprintf(con->
result
->
info
,
DRIZZLE_MAX_INFO_SIZE
,
"%.*s"
,
454
(int32_t)con->
packet_size
, con->
buffer_ptr
);
455
con->
buffer_ptr
+= con->
packet_size
;
456
con->
buffer_size
-= con->
packet_size
;
457
con->
packet_size
= 0;
458
}
459
460
drizzle_state_pop
(con);
461
return
ret;
462
}
463
464
drizzle_return_t
drizzle_state_result_write
(
drizzle_con_st
*con)
465
{
466
uint8_t *start= con->
buffer_ptr
+ con->
buffer_size
;
467
uint8_t *ptr;
468
drizzle_result_st
*result= con->
result
;
469
470
drizzle_log_debug
(con->
drizzle
,
"drizzle_state_result_write"
);
471
472
/* Calculate max packet size. */
473
con->
packet_size
= 1
/* OK/Field Count/EOF/Error */
474
+ 9
/* Affected rows */
475
+ 9
/* Insert ID */
476
+ 2
/* Status */
477
+ 2
/* Warning count */
478
+ strlen(result->
info
);
/* Info/error message */
479
480
/* Assume the entire result packet will fit in the buffer. */
481
if
((con->
packet_size
+ 4) >
DRIZZLE_MAX_BUFFER_SIZE
)
482
{
483
drizzle_set_error
(con->
drizzle
,
"drizzle_state_result_write"
,
484
"buffer too small:%zu"
, con->
packet_size
+ 4);
485
return
DRIZZLE_RETURN_INTERNAL_ERROR
;
486
}
487
488
/* Flush buffer if there is not enough room. */
489
if
(((
size_t
)
DRIZZLE_MAX_BUFFER_SIZE
- (
size_t
)(start - con->
buffer
)) <
490
con->
packet_size
)
491
{
492
drizzle_state_push
(con,
drizzle_state_write
);
493
return
DRIZZLE_RETURN_OK
;
494
}
495
496
/* Store packet size at the end since it may change. */
497
ptr= start;
498
ptr[3]= con->
packet_number
;
499
con->
packet_number
++;
500
ptr+= 4;
501
502
if
(result->
options
&
DRIZZLE_RESULT_EOF_PACKET
)
503
{
504
ptr[0]= 254;
505
ptr++;
506
507
drizzle_set_byte2
(ptr, result->
warning_count
);
508
ptr+= 2;
509
510
drizzle_set_byte2
(ptr, con->
status
);
511
ptr+= 2;
512
}
513
else
if
(result->
error_code
!= 0)
514
{
515
ptr[0]= 255;
516
ptr++;
517
518
drizzle_set_byte2
(ptr, result->
error_code
);
519
ptr+= 2;
520
521
ptr[0]=
'#'
;
522
ptr++;
523
524
memcpy(ptr, result->
sqlstate
,
DRIZZLE_MAX_SQLSTATE_SIZE
);
525
ptr+=
DRIZZLE_MAX_SQLSTATE_SIZE
;
526
527
memcpy(ptr, result->
info
, strlen(result->
info
));
528
ptr+= strlen(result->
info
);
529
}
530
else
if
(result->
column_count
== 0)
531
{
532
ptr[0]= 0;
533
ptr++;
534
535
ptr=
drizzle_pack_length
(result->
affected_rows
, ptr);
536
ptr=
drizzle_pack_length
(result->
insert_id
, ptr);
537
538
drizzle_set_byte2
(ptr, con->
status
);
539
ptr+= 2;
540
541
drizzle_set_byte2
(ptr, result->
warning_count
);
542
ptr+= 2;
543
544
memcpy(ptr, result->
info
, strlen(result->
info
));
545
ptr+= strlen(result->
info
);
546
}
547
else
548
ptr=
drizzle_pack_length
(result->
column_count
, ptr);
549
550
con->
packet_size
= ((size_t)(ptr - start) - 4);
551
con->
buffer_size
+= (4 + con->
packet_size
);
552
553
/* Store packet size now. */
554
drizzle_set_byte3
(start, con->
packet_size
);
555
556
drizzle_state_pop
(con);
557
return
DRIZZLE_RETURN_OK
;
558
}
Generated by
1.8.1.1