This source file includes following definitions.
- MYSQLND_METHOD
- MYSQLND_METHOD
- MYSQLND_METHOD
- MYSQLND_METHOD
- MYSQLND_METHOD
- MYSQLND_METHOD
- mysqlnd_query_read_result_set_header
- MYSQLND_METHOD
- MYSQLND_METHOD
- MYSQLND_METHOD
- MYSQLND_METHOD
- MYSQLND_METHOD
- MYSQLND_METHOD
- MYSQLND_METHOD
- MYSQLND_METHOD
- MYSQLND_METHOD
- MYSQLND_METHOD
- MYSQLND_METHOD
- MYSQLND_METHOD
- MYSQLND_METHOD
- MYSQLND_CLASS_METHODS_START
- mysqlnd_result_unbuffered_init
- mysqlnd_result_buffered_zval_init
- mysqlnd_result_buffered_c_init
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 #include "php.h"
23 #include "mysqlnd.h"
24 #include "mysqlnd_wireprotocol.h"
25 #include "mysqlnd_block_alloc.h"
26 #include "mysqlnd_priv.h"
27 #include "mysqlnd_result.h"
28 #include "mysqlnd_result_meta.h"
29 #include "mysqlnd_statistics.h"
30 #include "mysqlnd_debug.h"
31 #include "mysqlnd_ext_plugin.h"
32
33 #define MYSQLND_SILENT
34
35
36 static enum_func_status
37 MYSQLND_METHOD(mysqlnd_result_buffered_zval, initialize_result_set_rest)(MYSQLND_RES_BUFFERED * const result, MYSQLND_RES_METADATA * const meta,
38 MYSQLND_STATS * stats, zend_bool int_and_float_native)
39 {
40 unsigned int i;
41 enum_func_status ret = PASS;
42 const unsigned int field_count = meta->field_count;
43 const uint64_t row_count = result->row_count;
44 enum_func_status rc;
45
46 zval *data_begin = ((MYSQLND_RES_BUFFERED_ZVAL *) result)->data;
47 zval *data_cursor = data_begin;
48
49 DBG_ENTER("mysqlnd_result_buffered_zval::initialize_result_set_rest");
50
51 if (!data_cursor || row_count == result->initialized_rows) {
52 DBG_RETURN(ret);
53 }
54 while ((data_cursor - data_begin) < (int)(row_count * field_count)) {
55 if (Z_ISUNDEF(data_cursor[0])) {
56 rc = result->m.row_decoder(result->row_buffers[(data_cursor - data_begin) / field_count],
57 data_cursor,
58 field_count,
59 meta->fields,
60 int_and_float_native,
61 stats);
62 if (rc != PASS) {
63 ret = FAIL;
64 break;
65 }
66 result->initialized_rows++;
67 for (i = 0; i < field_count; i++) {
68
69
70
71
72
73 if (Z_TYPE(data_cursor[i]) == IS_STRING) {
74 zend_ulong len = Z_STRLEN(data_cursor[i]);
75 if (meta->fields[i].max_length < len) {
76 meta->fields[i].max_length = len;
77 }
78 }
79 }
80 }
81 data_cursor += field_count;
82 }
83 DBG_RETURN(ret);
84 }
85
86
87
88
89 static enum_func_status
90 MYSQLND_METHOD(mysqlnd_result_buffered_c, initialize_result_set_rest)(MYSQLND_RES_BUFFERED * const result, MYSQLND_RES_METADATA * const meta,
91 MYSQLND_STATS * stats, zend_bool int_and_float_native)
92 {
93 unsigned int i;
94 enum_func_status ret = PASS;
95 const unsigned int field_count = meta->field_count;
96 const uint64_t row_count = result->row_count;
97 enum_func_status rc;
98 DBG_ENTER("mysqlnd_result_buffered_c::initialize_result_set_rest");
99
100 if (result->initialized_rows < row_count) {
101 zend_uchar * initialized = ((MYSQLND_RES_BUFFERED_C *) result)->initialized;
102 zval * current_row = mnd_emalloc(field_count * sizeof(zval));
103
104 if (!current_row) {
105 DBG_RETURN(FAIL);
106 }
107
108 for (i = 0; i < result->row_count; i++) {
109
110 if (initialized[i >> 3] & (1 << (i & 7))) {
111 continue;
112 }
113
114 rc = result->m.row_decoder(result->row_buffers[i], current_row, field_count, meta->fields, int_and_float_native, stats);
115
116 if (rc != PASS) {
117 ret = FAIL;
118 break;
119 }
120 result->initialized_rows++;
121 initialized[i >> 3] |= (1 << (i & 7));
122 for (i = 0; i < field_count; i++) {
123
124
125
126
127
128 if (Z_TYPE(current_row[i]) == IS_STRING) {
129 zend_ulong len = Z_STRLEN(current_row[i]);
130 if (meta->fields[i].max_length < len) {
131 meta->fields[i].max_length = len;
132 }
133 }
134 zval_ptr_dtor(¤t_row[i]);
135 }
136 }
137 mnd_efree(current_row);
138 }
139 DBG_RETURN(ret);
140 }
141
142
143
144
145 static void
146 MYSQLND_METHOD(mysqlnd_result_unbuffered, free_last_data)(MYSQLND_RES_UNBUFFERED * unbuf, MYSQLND_STATS * const global_stats)
147 {
148 DBG_ENTER("mysqlnd_res::unbuffered_free_last_data");
149
150 if (!unbuf) {
151 DBG_VOID_RETURN;
152 }
153
154 DBG_INF_FMT("field_count=%u", unbuf->field_count);
155 if (unbuf->last_row_data) {
156 unsigned int i;
157 for (i = 0; i < unbuf->field_count; i++) {
158 zval_ptr_dtor(&(unbuf->last_row_data[i]));
159 }
160
161
162 mnd_efree(unbuf->last_row_data);
163 unbuf->last_row_data = NULL;
164 }
165 if (unbuf->last_row_buffer) {
166 DBG_INF("Freeing last row buffer");
167
168 unbuf->last_row_buffer->free_chunk(unbuf->last_row_buffer);
169 unbuf->last_row_buffer = NULL;
170 }
171
172 DBG_VOID_RETURN;
173 }
174
175
176
177
178 static void
179 MYSQLND_METHOD(mysqlnd_result_unbuffered, free_result)(MYSQLND_RES_UNBUFFERED * const result, MYSQLND_STATS * const global_stats)
180 {
181 DBG_ENTER("mysqlnd_result_unbuffered, free_result");
182 result->m.free_last_data(result, global_stats);
183
184 if (result->lengths) {
185 mnd_pefree(result->lengths, result->persistent);
186 result->lengths = NULL;
187 }
188
189
190 if (result->row_packet) {
191 PACKET_FREE(result->row_packet);
192 result->row_packet = NULL;
193 }
194
195 if (result->result_set_memory_pool) {
196 mysqlnd_mempool_destroy(result->result_set_memory_pool);
197 result->result_set_memory_pool = NULL;
198 }
199
200
201 mnd_pefree(result, result->persistent);
202 DBG_VOID_RETURN;
203 }
204
205
206
207
208 static void
209 MYSQLND_METHOD(mysqlnd_result_buffered_zval, free_result)(MYSQLND_RES_BUFFERED_ZVAL * const set)
210 {
211 zval * data = set->data;
212
213 DBG_ENTER("mysqlnd_result_buffered_zval::free_result");
214
215 set->data = NULL;
216 if (data) {
217 unsigned int field_count = set->field_count;
218 int64_t row;
219
220 for (row = set->row_count - 1; row >= 0; row--) {
221 zval *current_row = data + row * field_count;
222 int64_t col;
223
224 if (current_row != NULL) {
225 for (col = field_count - 1; col >= 0; --col) {
226 zval_ptr_dtor(&(current_row[col]));
227 }
228 }
229 }
230 mnd_efree(data);
231 }
232 set->data_cursor = NULL;
233 DBG_VOID_RETURN;
234 }
235
236
237
238
239 static void
240 MYSQLND_METHOD(mysqlnd_result_buffered_c, free_result)(MYSQLND_RES_BUFFERED_C * const set)
241 {
242 DBG_ENTER("mysqlnd_result_buffered_c::free_result");
243 mnd_pefree(set->initialized, set->persistent);
244 set->initialized = NULL;
245 DBG_VOID_RETURN;
246 }
247
248
249
250
251 static void
252 MYSQLND_METHOD(mysqlnd_result_buffered, free_result)(MYSQLND_RES_BUFFERED * const set)
253 {
254 int64_t row;
255
256 DBG_ENTER("mysqlnd_result_buffered::free_result");
257 DBG_INF_FMT("Freeing "MYSQLND_LLU_SPEC" row(s)", set->row_count);
258
259 if (set->type == MYSQLND_BUFFERED_TYPE_ZVAL) {
260 MYSQLND_METHOD(mysqlnd_result_buffered_zval, free_result)((MYSQLND_RES_BUFFERED_ZVAL *) set);
261 } if (set->type == MYSQLND_BUFFERED_TYPE_C) {
262 MYSQLND_METHOD(mysqlnd_result_buffered_c, free_result)((MYSQLND_RES_BUFFERED_C *) set);
263 }
264
265 for (row = set->row_count - 1; row >= 0; row--) {
266 MYSQLND_MEMORY_POOL_CHUNK *current_buffer = set->row_buffers[row];
267 current_buffer->free_chunk(current_buffer);
268 }
269
270 if (set->lengths) {
271 mnd_pefree(set->lengths, set->persistent);
272 set->lengths = NULL;
273 }
274
275 if (set->row_buffers) {
276 mnd_pefree(set->row_buffers, 0);
277 set->row_buffers = NULL;
278 }
279
280 if (set->result_set_memory_pool) {
281 mysqlnd_mempool_destroy(set->result_set_memory_pool);
282 set->result_set_memory_pool = NULL;
283 }
284
285
286 set->row_count = 0;
287
288 mnd_pefree(set, set->persistent);
289
290 DBG_VOID_RETURN;
291 }
292
293
294
295
296 static void
297 MYSQLND_METHOD(mysqlnd_res, free_result_buffers)(MYSQLND_RES * result)
298 {
299 DBG_ENTER("mysqlnd_res::free_result_buffers");
300 DBG_INF_FMT("%s", result->unbuf? "unbuffered":(result->stored_data? "buffered":"unknown"));
301
302 if (result->unbuf) {
303 result->unbuf->m.free_result(result->unbuf, result->conn? result->conn->stats : NULL);
304 result->unbuf = NULL;
305 } else if (result->stored_data) {
306 result->stored_data->m.free_result(result->stored_data);
307 result->stored_data = NULL;
308 }
309
310
311 DBG_VOID_RETURN;
312 }
313
314
315
316
317 static
318 void MYSQLND_METHOD(mysqlnd_res, free_result_contents_internal)(MYSQLND_RES * result)
319 {
320 DBG_ENTER("mysqlnd_res::free_result_contents_internal");
321
322 result->m.free_result_buffers(result);
323
324 if (result->meta) {
325 result->meta->m->free_metadata(result->meta);
326 result->meta = NULL;
327 }
328
329 DBG_VOID_RETURN;
330 }
331
332
333
334
335 static
336 void MYSQLND_METHOD(mysqlnd_res, free_result_internal)(MYSQLND_RES * result)
337 {
338 DBG_ENTER("mysqlnd_res::free_result_internal");
339 result->m.skip_result(result);
340
341 result->m.free_result_contents(result);
342
343 if (result->conn) {
344 result->conn->m->free_reference(result->conn);
345 result->conn = NULL;
346 }
347
348 mnd_pefree(result, result->persistent);
349
350 DBG_VOID_RETURN;
351 }
352
353
354
355
356 static enum_func_status
357 MYSQLND_METHOD(mysqlnd_res, read_result_metadata)(MYSQLND_RES * result, MYSQLND_CONN_DATA * conn)
358 {
359 DBG_ENTER("mysqlnd_res::read_result_metadata");
360
361
362
363
364
365
366
367 if (result->meta) {
368 result->meta->m->free_metadata(result->meta);
369 result->meta = NULL;
370 }
371
372 result->meta = result->m.result_meta_init(result->field_count, result->persistent);
373 if (!result->meta) {
374 SET_OOM_ERROR(*conn->error_info);
375 DBG_RETURN(FAIL);
376 }
377
378
379
380
381 if (FAIL == result->meta->m->read_metadata(result->meta, conn)) {
382 result->m.free_result_contents(result);
383 DBG_RETURN(FAIL);
384 }
385
386 result->field_count = result->meta->field_count;
387
388
389
390
391
392
393
394
395 DBG_RETURN(PASS);
396 }
397
398
399
400
401 enum_func_status
402 mysqlnd_query_read_result_set_header(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * s)
403 {
404 MYSQLND_STMT_DATA * stmt = s ? s->data:NULL;
405 enum_func_status ret;
406 MYSQLND_PACKET_RSET_HEADER * rset_header = NULL;
407 MYSQLND_PACKET_EOF * fields_eof = NULL;
408
409 DBG_ENTER("mysqlnd_query_read_result_set_header");
410 DBG_INF_FMT("stmt=%lu", stmt? stmt->stmt_id:0);
411
412 ret = FAIL;
413 do {
414 rset_header = conn->protocol->m.get_rset_header_packet(conn->protocol, FALSE);
415 if (!rset_header) {
416 SET_OOM_ERROR(*conn->error_info);
417 ret = FAIL;
418 break;
419 }
420
421 SET_ERROR_AFF_ROWS(conn);
422
423 if (FAIL == (ret = PACKET_READ(rset_header, conn))) {
424 php_error_docref(NULL, E_WARNING, "Error reading result set's header");
425 break;
426 }
427
428 if (rset_header->error_info.error_no) {
429
430
431
432
433
434
435
436
437
438 conn->upsert_status->server_status &= ~SERVER_MORE_RESULTS_EXISTS;
439
440
441
442
443 COPY_CLIENT_ERROR(*conn->error_info, rset_header->error_info);
444 ret = FAIL;
445 DBG_ERR_FMT("error=%s", rset_header->error_info.error);
446
447 CONN_SET_STATE(conn, CONN_READY);
448 break;
449 }
450 conn->error_info->error_no = 0;
451
452 switch (rset_header->field_count) {
453 case MYSQLND_NULL_LENGTH: {
454 zend_bool is_warning;
455 DBG_INF("LOAD DATA");
456 conn->last_query_type = QUERY_LOAD_LOCAL;
457 conn->field_count = 0;
458 CONN_SET_STATE(conn, CONN_SENDING_LOAD_DATA);
459 ret = mysqlnd_handle_local_infile(conn, rset_header->info_or_local_file, &is_warning);
460 CONN_SET_STATE(conn, (ret == PASS || is_warning == TRUE)? CONN_READY:CONN_QUIT_SENT);
461 MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_NON_RSET_QUERY);
462 break;
463 }
464 case 0:
465 DBG_INF("UPSERT");
466 conn->last_query_type = QUERY_UPSERT;
467 conn->field_count = rset_header->field_count;
468 memset(conn->upsert_status, 0, sizeof(*conn->upsert_status));
469 conn->upsert_status->warning_count = rset_header->warning_count;
470 conn->upsert_status->server_status = rset_header->server_status;
471 conn->upsert_status->affected_rows = rset_header->affected_rows;
472 conn->upsert_status->last_insert_id = rset_header->last_insert_id;
473 SET_NEW_MESSAGE(conn->last_message, conn->last_message_len,
474 rset_header->info_or_local_file, rset_header->info_or_local_file_len,
475 conn->persistent);
476
477 if (conn->upsert_status->server_status & SERVER_MORE_RESULTS_EXISTS) {
478 CONN_SET_STATE(conn, CONN_NEXT_RESULT_PENDING);
479 } else {
480 CONN_SET_STATE(conn, CONN_READY);
481 }
482 ret = PASS;
483 MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_NON_RSET_QUERY);
484 break;
485 default: do {
486 MYSQLND_RES * result;
487 enum_mysqlnd_collected_stats statistic = STAT_LAST;
488
489 DBG_INF("Result set pending");
490 SET_EMPTY_MESSAGE(conn->last_message, conn->last_message_len, conn->persistent);
491
492 MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_RSET_QUERY);
493 memset(conn->upsert_status, 0, sizeof(*conn->upsert_status));
494
495 SET_ERROR_AFF_ROWS(conn);
496
497 conn->last_query_type = QUERY_SELECT;
498 CONN_SET_STATE(conn, CONN_FETCHING_DATA);
499
500 conn->field_count = rset_header->field_count;
501 if (!stmt) {
502 result = conn->current_result = conn->m->result_init(rset_header->field_count, conn->persistent);
503 } else {
504 if (!stmt->result) {
505 DBG_INF("This is 'SHOW'/'EXPLAIN'-like query.");
506
507
508
509
510
511 result = stmt->result = conn->m->result_init(rset_header->field_count, stmt->persistent);
512 } else {
513
514
515
516
517
518
519
520
521
522
523
524
525 }
526 result = stmt->result;
527 }
528 if (!result) {
529 SET_OOM_ERROR(*conn->error_info);
530 ret = FAIL;
531 break;
532 }
533
534 if (FAIL == (ret = result->m.read_result_metadata(result, conn))) {
535
536 if (!stmt && conn->current_result) {
537 mnd_efree(conn->current_result);
538 conn->current_result = NULL;
539 }
540 DBG_ERR("Error occurred while reading metadata");
541 break;
542 }
543
544
545 fields_eof = conn->protocol->m.get_eof_packet(conn->protocol, FALSE);
546 if (!fields_eof) {
547 SET_OOM_ERROR(*conn->error_info);
548 ret = FAIL;
549 break;
550 }
551 if (FAIL == (ret = PACKET_READ(fields_eof, conn))) {
552 DBG_ERR("Error occurred while reading the EOF packet");
553 result->m.free_result_contents(result);
554 mnd_efree(result);
555 if (!stmt) {
556 conn->current_result = NULL;
557 } else {
558 stmt->result = NULL;
559 memset(stmt, 0, sizeof(*stmt));
560 stmt->state = MYSQLND_STMT_INITTED;
561 }
562 } else {
563 DBG_INF_FMT("warnings=%u server_status=%u", fields_eof->warning_count, fields_eof->server_status);
564 conn->upsert_status->warning_count = fields_eof->warning_count;
565
566
567
568
569
570
571
572 conn->upsert_status->server_status = fields_eof->server_status;
573 if (fields_eof->server_status & SERVER_QUERY_NO_GOOD_INDEX_USED) {
574 statistic = STAT_BAD_INDEX_USED;
575 } else if (fields_eof->server_status & SERVER_QUERY_NO_INDEX_USED) {
576 statistic = STAT_NO_INDEX_USED;
577 } else if (fields_eof->server_status & SERVER_QUERY_WAS_SLOW) {
578 statistic = STAT_QUERY_WAS_SLOW;
579 }
580 MYSQLND_INC_CONN_STATISTIC(conn->stats, statistic);
581 }
582 } while (0);
583 PACKET_FREE(fields_eof);
584 break;
585 }
586 } while (0);
587 PACKET_FREE(rset_header);
588
589 DBG_INF(ret == PASS? "PASS":"FAIL");
590 DBG_RETURN(ret);
591 }
592
593
594
595
596
597
598
599
600
601
602 static zend_ulong *
603 MYSQLND_METHOD(mysqlnd_result_buffered_zval, fetch_lengths)(MYSQLND_RES_BUFFERED * const result)
604 {
605 const MYSQLND_RES_BUFFERED_ZVAL * set = (MYSQLND_RES_BUFFERED_ZVAL *) result;
606
607
608
609
610
611
612 DBG_ENTER("mysqlnd_result_buffered_zval::fetch_lengths");
613
614 if (set->data_cursor == NULL ||
615 set->data_cursor == set->data ||
616 ((set->data_cursor - set->data) > (result->row_count * result->field_count) ))
617 {
618 DBG_INF("EOF");
619 DBG_RETURN(NULL);
620 }
621 DBG_INF("non NULL");
622 DBG_RETURN(result->lengths);
623 }
624
625
626
627
628
629
630
631
632
633
634 static zend_ulong *
635 MYSQLND_METHOD(mysqlnd_result_buffered_c, fetch_lengths)(MYSQLND_RES_BUFFERED * const result)
636 {
637 const MYSQLND_RES_BUFFERED_C * set = (MYSQLND_RES_BUFFERED_C *) result;
638 DBG_ENTER("mysqlnd_result_buffered_c::fetch_lengths");
639
640 if (set->current_row > set->row_count || set->current_row == 0) {
641 DBG_INF("EOF");
642 DBG_RETURN(NULL);
643 }
644 DBG_INF("non NULL");
645 DBG_RETURN(result->lengths);
646 }
647
648
649
650
651 static zend_ulong *
652 MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_lengths)(MYSQLND_RES_UNBUFFERED * const result)
653 {
654
655 return (result->last_row_data || result->eof_reached)? result->lengths : NULL;
656 }
657
658
659
660
661 static zend_ulong *
662 MYSQLND_METHOD(mysqlnd_res, fetch_lengths)(MYSQLND_RES * const result)
663 {
664 zend_ulong * ret;
665 DBG_ENTER("mysqlnd_res::fetch_lengths");
666 ret = result->stored_data && result->stored_data->m.fetch_lengths ?
667 result->stored_data->m.fetch_lengths(result->stored_data) :
668 (result->unbuf && result->unbuf->m.fetch_lengths ?
669 result->unbuf->m.fetch_lengths(result->unbuf) :
670 NULL
671 );
672 DBG_RETURN(ret);
673 }
674
675
676
677
678 static enum_func_status
679 MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row_c)(MYSQLND_RES * result, void * param, unsigned int flags, zend_bool * fetched_anything)
680 {
681 enum_func_status ret;
682 MYSQLND_ROW_C *row = (MYSQLND_ROW_C *) param;
683 MYSQLND_PACKET_ROW *row_packet = result->unbuf->row_packet;
684 const MYSQLND_RES_METADATA * const meta = result->meta;
685
686 DBG_ENTER("mysqlnd_result_unbuffered::fetch_row_c");
687
688 *fetched_anything = FALSE;
689 if (result->unbuf->eof_reached) {
690
691 DBG_RETURN(PASS);
692 }
693 if (CONN_GET_STATE(result->conn) != CONN_FETCHING_DATA) {
694 SET_CLIENT_ERROR(*result->conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
695 DBG_RETURN(FAIL);
696 }
697 if (!row_packet) {
698
699 DBG_RETURN(FAIL);
700 }
701
702 row_packet->skip_extraction = FALSE;
703
704
705
706
707
708 if (PASS == (ret = PACKET_READ(row_packet, result->conn)) && !row_packet->eof) {
709 result->unbuf->m.free_last_data(result->unbuf, result->conn? result->conn->stats : NULL);
710
711 result->unbuf->last_row_data = row_packet->fields;
712 result->unbuf->last_row_buffer = row_packet->row_buffer;
713 row_packet->fields = NULL;
714 row_packet->row_buffer = NULL;
715
716 MYSQLND_INC_CONN_STATISTIC(result->conn->stats, STAT_ROWS_FETCHED_FROM_CLIENT_NORMAL_UNBUF);
717
718 if (!row_packet->skip_extraction) {
719 unsigned int i, field_count = meta->field_count;
720
721 enum_func_status rc = result->unbuf->m.row_decoder(result->unbuf->last_row_buffer,
722 result->unbuf->last_row_data,
723 field_count,
724 row_packet->fields_metadata,
725 result->conn->options->int_and_float_native,
726 result->conn->stats);
727 if (PASS != rc) {
728 DBG_RETURN(FAIL);
729 }
730 {
731 *row = mnd_malloc(field_count * sizeof(char *));
732 if (*row) {
733 MYSQLND_FIELD * field = meta->fields;
734 zend_ulong * lengths = result->unbuf->lengths;
735
736 for (i = 0; i < field_count; i++, field++) {
737 zval * data = &result->unbuf->last_row_data[i];
738 unsigned int len = (Z_TYPE_P(data) == IS_STRING)? Z_STRLEN_P(data) : 0;
739
740
741 if (Z_TYPE_P(data) != IS_NULL) {
742 convert_to_string(data);
743 (*row)[i] = Z_STRVAL_P(data);
744 } else {
745 (*row)[i] = NULL;
746 }
747
748
749 if (lengths) {
750 lengths[i] = len;
751 }
752
753 if (field->max_length < len) {
754 field->max_length = len;
755 }
756 }
757 } else {
758 SET_OOM_ERROR(*result->conn->error_info);
759 }
760 }
761 }
762 result->unbuf->row_count++;
763 *fetched_anything = TRUE;
764 } else if (ret == FAIL) {
765 if (row_packet->error_info.error_no) {
766 COPY_CLIENT_ERROR(*result->conn->error_info, row_packet->error_info);
767 DBG_ERR_FMT("errorno=%u error=%s", row_packet->error_info.error_no, row_packet->error_info.error);
768 }
769 CONN_SET_STATE(result->conn, CONN_READY);
770 result->unbuf->eof_reached = TRUE;
771 } else if (row_packet->eof) {
772
773 DBG_INF_FMT("warnings=%u server_status=%u", row_packet->warning_count, row_packet->server_status);
774 result->unbuf->eof_reached = TRUE;
775 memset(result->conn->upsert_status, 0, sizeof(*result->conn->upsert_status));
776 result->conn->upsert_status->warning_count = row_packet->warning_count;
777 result->conn->upsert_status->server_status = row_packet->server_status;
778
779
780
781
782 if (result->conn->upsert_status->server_status & SERVER_MORE_RESULTS_EXISTS) {
783 CONN_SET_STATE(result->conn, CONN_NEXT_RESULT_PENDING);
784 } else {
785 CONN_SET_STATE(result->conn, CONN_READY);
786 }
787 result->unbuf->m.free_last_data(result->unbuf, result->conn? result->conn->stats : NULL);
788 }
789
790 DBG_INF_FMT("ret=%s fetched=%u", ret == PASS? "PASS":"FAIL", *fetched_anything);
791 DBG_RETURN(PASS);
792 }
793
794
795
796
797 static enum_func_status
798 MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row)(MYSQLND_RES * result, void * param, const unsigned int flags, zend_bool * fetched_anything)
799 {
800 enum_func_status ret;
801 zval *row = (zval *) param;
802 MYSQLND_PACKET_ROW *row_packet = result->unbuf->row_packet;
803 const MYSQLND_RES_METADATA * const meta = result->meta;
804
805 DBG_ENTER("mysqlnd_result_unbuffered::fetch_row");
806
807 *fetched_anything = FALSE;
808 if (result->unbuf->eof_reached) {
809
810 DBG_RETURN(PASS);
811 }
812 if (CONN_GET_STATE(result->conn) != CONN_FETCHING_DATA) {
813 SET_CLIENT_ERROR(*result->conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
814 DBG_RETURN(FAIL);
815 }
816 if (!row_packet) {
817
818 DBG_RETURN(FAIL);
819 }
820
821 row_packet->skip_extraction = row? FALSE:TRUE;
822
823
824
825
826
827 if (PASS == (ret = PACKET_READ(row_packet, result->conn)) && !row_packet->eof) {
828 result->unbuf->m.free_last_data(result->unbuf, result->conn? result->conn->stats : NULL);
829
830 result->unbuf->last_row_data = row_packet->fields;
831 result->unbuf->last_row_buffer = row_packet->row_buffer;
832 row_packet->fields = NULL;
833 row_packet->row_buffer = NULL;
834
835 MYSQLND_INC_CONN_STATISTIC(result->conn->stats, STAT_ROWS_FETCHED_FROM_CLIENT_NORMAL_UNBUF);
836
837 if (!row_packet->skip_extraction) {
838 unsigned int i, field_count = meta->field_count;
839
840 enum_func_status rc = result->unbuf->m.row_decoder(result->unbuf->last_row_buffer,
841 result->unbuf->last_row_data,
842 field_count,
843 row_packet->fields_metadata,
844 result->conn->options->int_and_float_native,
845 result->conn->stats);
846 if (PASS != rc) {
847 DBG_RETURN(FAIL);
848 }
849 {
850 HashTable * row_ht = Z_ARRVAL_P(row);
851 MYSQLND_FIELD * field = meta->fields;
852 zend_ulong * lengths = result->unbuf->lengths;
853
854 for (i = 0; i < field_count; i++, field++) {
855 zval * data = &result->unbuf->last_row_data[i];
856 unsigned int len = (Z_TYPE_P(data) == IS_STRING)? Z_STRLEN_P(data) : 0;
857
858 if (flags & MYSQLND_FETCH_NUM) {
859 Z_TRY_ADDREF_P(data);
860 zend_hash_next_index_insert(row_ht, data);
861 }
862 if (flags & MYSQLND_FETCH_ASSOC) {
863
864
865
866
867
868
869
870 Z_TRY_ADDREF_P(data);
871 if (meta->zend_hash_keys[i].is_numeric == FALSE) {
872 zend_hash_update(Z_ARRVAL_P(row), meta->fields[i].sname, data);
873 } else {
874 zend_hash_index_update(Z_ARRVAL_P(row), meta->zend_hash_keys[i].key, data);
875 }
876 }
877
878 if (lengths) {
879 lengths[i] = len;
880 }
881
882 if (field->max_length < len) {
883 field->max_length = len;
884 }
885 }
886 }
887 }
888 result->unbuf->row_count++;
889 *fetched_anything = TRUE;
890 } else if (ret == FAIL) {
891 if (row_packet->error_info.error_no) {
892 COPY_CLIENT_ERROR(*result->conn->error_info, row_packet->error_info);
893 DBG_ERR_FMT("errorno=%u error=%s", row_packet->error_info.error_no, row_packet->error_info.error);
894 }
895 CONN_SET_STATE(result->conn, CONN_READY);
896 result->unbuf->eof_reached = TRUE;
897 } else if (row_packet->eof) {
898
899 DBG_INF_FMT("warnings=%u server_status=%u", row_packet->warning_count, row_packet->server_status);
900 result->unbuf->eof_reached = TRUE;
901 memset(result->conn->upsert_status, 0, sizeof(*result->conn->upsert_status));
902 result->conn->upsert_status->warning_count = row_packet->warning_count;
903 result->conn->upsert_status->server_status = row_packet->server_status;
904
905
906
907
908 if (result->conn->upsert_status->server_status & SERVER_MORE_RESULTS_EXISTS) {
909 CONN_SET_STATE(result->conn, CONN_NEXT_RESULT_PENDING);
910 } else {
911 CONN_SET_STATE(result->conn, CONN_READY);
912 }
913 result->unbuf->m.free_last_data(result->unbuf, result->conn? result->conn->stats : NULL);
914 }
915
916 DBG_INF_FMT("ret=%s fetched=%u", ret == PASS? "PASS":"FAIL", *fetched_anything);
917 DBG_RETURN(PASS);
918 }
919
920
921
922
923 static MYSQLND_RES *
924 MYSQLND_METHOD(mysqlnd_res, use_result)(MYSQLND_RES * const result, zend_bool ps)
925 {
926 DBG_ENTER("mysqlnd_res::use_result");
927
928 SET_EMPTY_ERROR(*result->conn->error_info);
929
930 if (ps == FALSE) {
931 result->type = MYSQLND_RES_NORMAL;
932 } else {
933 result->type = MYSQLND_RES_PS_UNBUF;
934 }
935
936 result->unbuf = mysqlnd_result_unbuffered_init(result->field_count, ps, result->persistent);
937 if (!result->unbuf) {
938 goto oom;
939 }
940
941
942
943
944
945
946
947 result->unbuf->row_packet = result->conn->protocol->m.get_row_packet(result->conn->protocol, FALSE);
948 if (!result->unbuf->row_packet) {
949 goto oom;
950 }
951 result->unbuf->row_packet->result_set_memory_pool = result->unbuf->result_set_memory_pool;
952 result->unbuf->row_packet->field_count = result->field_count;
953 result->unbuf->row_packet->binary_protocol = ps;
954 result->unbuf->row_packet->fields_metadata = result->meta->fields;
955 result->unbuf->row_packet->bit_fields_count = result->meta->bit_fields_count;
956 result->unbuf->row_packet->bit_fields_total_len = result->meta->bit_fields_total_len;
957
958 DBG_RETURN(result);
959 oom:
960 SET_OOM_ERROR(*result->conn->error_info);
961 DBG_RETURN(NULL);
962 }
963
964
965
966
967 static enum_func_status
968 MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row_c)(MYSQLND_RES * result, void * param, unsigned int flags, zend_bool * fetched_anything)
969 {
970 MYSQLND_ROW_C * row = (MYSQLND_ROW_C *) param;
971 const MYSQLND_RES_METADATA * const meta = result->meta;
972 unsigned int field_count = meta->field_count;
973 enum_func_status ret = FAIL;
974 DBG_ENTER("mysqlnd_result_buffered::fetch_row_c");
975
976 if (result->stored_data->type == MYSQLND_BUFFERED_TYPE_ZVAL) {
977 MYSQLND_RES_BUFFERED_ZVAL * set = (MYSQLND_RES_BUFFERED_ZVAL *) result->stored_data;
978
979
980 if (set->data_cursor &&
981 (set->data_cursor - set->data) < (result->stored_data->row_count * field_count))
982 {
983 zval *current_row = set->data_cursor;
984 unsigned int i;
985
986 if (Z_ISUNDEF(current_row[0])) {
987 uint64_t row_num = (set->data_cursor - set->data) / field_count;
988 enum_func_status rc = set->m.row_decoder(set->row_buffers[row_num],
989 current_row,
990 field_count,
991 meta->fields,
992 result->conn->options->int_and_float_native,
993 result->conn->stats);
994 if (rc != PASS) {
995 DBG_RETURN(FAIL);
996 }
997 set->initialized_rows++;
998 for (i = 0; i < field_count; i++) {
999
1000
1001
1002
1003
1004 if (Z_TYPE(current_row[i]) == IS_STRING) {
1005 zend_ulong len = Z_STRLEN(current_row[i]);
1006 if (meta->fields[i].max_length < len) {
1007 meta->fields[i].max_length = len;
1008 }
1009 }
1010 }
1011 }
1012
1013
1014
1015 *row = mnd_malloc(field_count * sizeof(char *));
1016 if (*row) {
1017 for (i = 0; i < field_count; i++) {
1018 zval * data = ¤t_row[i];
1019
1020 set->lengths[i] = (Z_TYPE_P(data) == IS_STRING)? Z_STRLEN_P(data) : 0;
1021
1022 if (Z_TYPE_P(data) != IS_NULL) {
1023 convert_to_string(data);
1024 (*row)[i] = Z_STRVAL_P(data);
1025 } else {
1026 (*row)[i] = NULL;
1027 }
1028 }
1029 set->data_cursor += field_count;
1030 MYSQLND_INC_GLOBAL_STATISTIC(STAT_ROWS_FETCHED_FROM_CLIENT_NORMAL_BUF);
1031 } else {
1032 SET_OOM_ERROR(*result->conn->error_info);
1033 }
1034
1035
1036 *fetched_anything = *row? TRUE:FALSE;
1037 ret = *row? PASS:FAIL;
1038 } else {
1039 set->data_cursor = NULL;
1040 DBG_INF("EOF reached");
1041 *fetched_anything = FALSE;
1042 ret = PASS;
1043 }
1044 } else if (result->stored_data->type == MYSQLND_BUFFERED_TYPE_C) {
1045
1046
1047
1048
1049 *fetched_anything = FALSE;
1050 DBG_RETURN(FAIL);
1051 }
1052 DBG_INF_FMT("ret=PASS fetched=%u", *fetched_anything);
1053 DBG_RETURN(ret);
1054 }
1055
1056
1057
1058
1059 static enum_func_status
1060 MYSQLND_METHOD(mysqlnd_result_buffered_zval, fetch_row)(MYSQLND_RES * result, void * param, const unsigned int flags, zend_bool * fetched_anything)
1061 {
1062 zval * row = (zval *) param;
1063 const MYSQLND_RES_METADATA * const meta = result->meta;
1064 unsigned int field_count = meta->field_count;
1065 enum_func_status ret = FAIL;
1066 MYSQLND_RES_BUFFERED_ZVAL * set = (MYSQLND_RES_BUFFERED_ZVAL *) result->stored_data;
1067
1068 DBG_ENTER("mysqlnd_result_buffered_zval::fetch_row");
1069
1070
1071 if (set->data_cursor &&
1072 (set->data_cursor - set->data) < (set->row_count * field_count))
1073 {
1074 unsigned int i;
1075 zval *current_row = set->data_cursor;
1076
1077 if (Z_ISUNDEF(current_row[0])) {
1078 uint64_t row_num = (set->data_cursor - set->data) / field_count;
1079 enum_func_status rc = set->m.row_decoder(set->row_buffers[row_num],
1080 current_row,
1081 field_count,
1082 meta->fields,
1083 result->conn->options->int_and_float_native,
1084 result->conn->stats);
1085 if (rc != PASS) {
1086 DBG_RETURN(FAIL);
1087 }
1088 set->initialized_rows++;
1089 for (i = 0; i < field_count; i++) {
1090
1091
1092
1093
1094
1095 if (Z_TYPE(current_row[i]) == IS_STRING) {
1096 zend_ulong len = Z_STRLEN(current_row[i]);
1097 if (meta->fields[i].max_length < len) {
1098 meta->fields[i].max_length = len;
1099 }
1100 }
1101 }
1102 }
1103
1104 for (i = 0; i < field_count; i++) {
1105 zval * data = ¤t_row[i];
1106
1107 set->lengths[i] = (Z_TYPE_P(data) == IS_STRING)? Z_STRLEN_P(data) : 0;
1108
1109 if (flags & MYSQLND_FETCH_NUM) {
1110 Z_TRY_ADDREF_P(data);
1111 zend_hash_next_index_insert(Z_ARRVAL_P(row), data);
1112 }
1113 if (flags & MYSQLND_FETCH_ASSOC) {
1114
1115
1116
1117
1118
1119
1120
1121 Z_TRY_ADDREF_P(data);
1122 if (meta->zend_hash_keys[i].is_numeric == FALSE) {
1123 zend_hash_update(Z_ARRVAL_P(row), meta->fields[i].sname, data);
1124 } else {
1125 zend_hash_index_update(Z_ARRVAL_P(row), meta->zend_hash_keys[i].key, data);
1126 }
1127 }
1128 }
1129 set->data_cursor += field_count;
1130 MYSQLND_INC_GLOBAL_STATISTIC(STAT_ROWS_FETCHED_FROM_CLIENT_NORMAL_BUF);
1131 *fetched_anything = TRUE;
1132 ret = PASS;
1133 } else {
1134 set->data_cursor = NULL;
1135 DBG_INF("EOF reached");
1136 *fetched_anything = FALSE;
1137 ret = PASS;
1138 }
1139 DBG_INF_FMT("ret=PASS fetched=%u", *fetched_anything);
1140 DBG_RETURN(ret);
1141 }
1142
1143
1144
1145
1146 static enum_func_status
1147 MYSQLND_METHOD(mysqlnd_result_buffered_c, fetch_row)(MYSQLND_RES * result, void * param, const unsigned int flags, zend_bool * fetched_anything)
1148 {
1149 zval * row = (zval *) param;
1150 const MYSQLND_RES_METADATA * const meta = result->meta;
1151 unsigned int field_count = meta->field_count;
1152 enum_func_status ret = FAIL;
1153
1154 MYSQLND_RES_BUFFERED_C * set = (MYSQLND_RES_BUFFERED_C *) result->stored_data;
1155
1156 DBG_ENTER("mysqlnd_result_buffered_c::fetch_row");
1157
1158
1159 if (set->current_row < set->row_count) {
1160 zval *current_row;
1161 enum_func_status rc;
1162 unsigned int i;
1163
1164 current_row = mnd_emalloc(field_count * sizeof(zval));
1165 if (!current_row) {
1166 SET_OOM_ERROR(*result->conn->error_info);
1167 DBG_RETURN(FAIL);
1168 }
1169
1170 rc = result->stored_data->m.row_decoder(result->stored_data->row_buffers[set->current_row],
1171 current_row,
1172 field_count,
1173 meta->fields,
1174 result->conn->options->int_and_float_native,
1175 result->conn->stats);
1176 if (rc != PASS) {
1177 DBG_RETURN(FAIL);
1178 }
1179 if (!(set->initialized[set->current_row >> 3] & (1 << (set->current_row & 7)))) {
1180 set->initialized[set->current_row >> 3] |= (1 << (set->current_row & 7));
1181
1182 set->initialized_rows++;
1183
1184 for (i = 0; i < field_count; i++) {
1185
1186
1187
1188
1189
1190 if (Z_TYPE(current_row[i]) == IS_STRING) {
1191 zend_ulong len = Z_STRLEN(current_row[i]);
1192 if (meta->fields[i].max_length < len) {
1193 meta->fields[i].max_length = len;
1194 }
1195 }
1196 }
1197 }
1198
1199 for (i = 0; i < field_count; i++) {
1200 zval * data = ¤t_row[i];
1201
1202 set->lengths[i] = (Z_TYPE_P(data) == IS_STRING)? Z_STRLEN_P(data) : 0;
1203
1204 if (flags & MYSQLND_FETCH_NUM) {
1205 Z_TRY_ADDREF_P(data);
1206 zend_hash_next_index_insert(Z_ARRVAL_P(row), data);
1207 }
1208 if (flags & MYSQLND_FETCH_ASSOC) {
1209
1210
1211
1212
1213
1214
1215
1216 Z_TRY_ADDREF_P(data);
1217 if (meta->zend_hash_keys[i].is_numeric == FALSE) {
1218 zend_hash_update(Z_ARRVAL_P(row), meta->fields[i].sname, data);
1219 } else {
1220 zend_hash_index_update(Z_ARRVAL_P(row), meta->zend_hash_keys[i].key, data);
1221 }
1222 }
1223
1224
1225
1226
1227
1228
1229 zval_ptr_dtor(data);
1230 }
1231 mnd_efree(current_row);
1232 set->current_row++;
1233 MYSQLND_INC_GLOBAL_STATISTIC(STAT_ROWS_FETCHED_FROM_CLIENT_NORMAL_BUF);
1234 *fetched_anything = TRUE;
1235 ret = PASS;
1236 } else {
1237 if (set->current_row == set->row_count) {
1238 set->current_row = set->row_count + 1;
1239 }
1240 DBG_INF_FMT("EOF reached. current_row=%llu", (unsigned long long) set->current_row);
1241 *fetched_anything = FALSE;
1242 ret = PASS;
1243 }
1244
1245 DBG_INF_FMT("ret=PASS fetched=%u", *fetched_anything);
1246 DBG_RETURN(ret);
1247 }
1248
1249
1250
1251
1252 static enum_func_status
1253 MYSQLND_METHOD(mysqlnd_res, fetch_row)(MYSQLND_RES * result, void * param, const unsigned int flags, zend_bool *fetched_anything)
1254 {
1255 const mysqlnd_fetch_row_func f = result->stored_data? result->stored_data->m.fetch_row:(result->unbuf? result->unbuf->m.fetch_row:NULL);
1256 if (f) {
1257 return f(result, param, flags, fetched_anything);
1258 }
1259 *fetched_anything = FALSE;
1260 return PASS;
1261 }
1262
1263
1264
1265 #define STORE_RESULT_PREALLOCATED_SET_IF_NOT_EMPTY 2
1266
1267
1268 enum_func_status
1269 MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND_CONN_DATA * const conn, MYSQLND_RES * result,
1270 MYSQLND_RES_METADATA * meta,
1271 MYSQLND_MEMORY_POOL_CHUNK ***row_buffers,
1272 zend_bool binary_protocol)
1273 {
1274 enum_func_status ret;
1275 MYSQLND_PACKET_ROW * row_packet = NULL;
1276 unsigned int next_extend = STORE_RESULT_PREALLOCATED_SET_IF_NOT_EMPTY, free_rows = 1;
1277 MYSQLND_RES_BUFFERED *set;
1278
1279 DBG_ENTER("mysqlnd_res::store_result_fetch_data");
1280
1281 set = result->stored_data;
1282
1283 if (!set || !row_buffers) {
1284 ret = FAIL;
1285 goto end;
1286 }
1287 if (free_rows) {
1288 *row_buffers = mnd_pemalloc((size_t)(free_rows * sizeof(MYSQLND_MEMORY_POOL_CHUNK *)), 0);
1289 if (!*row_buffers) {
1290 SET_OOM_ERROR(*conn->error_info);
1291 ret = FAIL;
1292 goto end;
1293 }
1294 }
1295 set->references = 1;
1296
1297
1298 row_packet = conn->protocol->m.get_row_packet(conn->protocol, FALSE);
1299 if (!row_packet) {
1300 SET_OOM_ERROR(*conn->error_info);
1301 ret = FAIL;
1302 goto end;
1303 }
1304 row_packet->result_set_memory_pool = result->stored_data->result_set_memory_pool;
1305 row_packet->field_count = meta->field_count;
1306 row_packet->binary_protocol = binary_protocol;
1307 row_packet->fields_metadata = meta->fields;
1308 row_packet->bit_fields_count = meta->bit_fields_count;
1309 row_packet->bit_fields_total_len = meta->bit_fields_total_len;
1310
1311 row_packet->skip_extraction = TRUE;
1312
1313 while (FAIL != (ret = PACKET_READ(row_packet, conn)) && !row_packet->eof) {
1314 if (!free_rows) {
1315 uint64_t total_allocated_rows = free_rows = next_extend = next_extend * 11 / 10;
1316 MYSQLND_MEMORY_POOL_CHUNK ** new_row_buffers;
1317 total_allocated_rows += set->row_count;
1318
1319
1320 if (total_allocated_rows * sizeof(MYSQLND_MEMORY_POOL_CHUNK *) > SIZE_MAX) {
1321 SET_OOM_ERROR(*conn->error_info);
1322 ret = FAIL;
1323 goto end;
1324 }
1325 new_row_buffers = mnd_perealloc(*row_buffers, (size_t)(total_allocated_rows * sizeof(MYSQLND_MEMORY_POOL_CHUNK *)), 0);
1326 if (!new_row_buffers) {
1327 SET_OOM_ERROR(*conn->error_info);
1328 ret = FAIL;
1329 goto end;
1330 }
1331 *row_buffers = new_row_buffers;
1332 }
1333 free_rows--;
1334 (*row_buffers)[set->row_count] = row_packet->row_buffer;
1335
1336 set->row_count++;
1337
1338
1339 row_packet->fields = NULL;
1340 row_packet->row_buffer = NULL;
1341
1342
1343
1344
1345
1346
1347
1348 }
1349
1350 MYSQLND_INC_CONN_STATISTIC_W_VALUE(conn->stats,
1351 binary_protocol? STAT_ROWS_BUFFERED_FROM_CLIENT_PS:
1352 STAT_ROWS_BUFFERED_FROM_CLIENT_NORMAL,
1353 set->row_count);
1354
1355
1356 if (row_packet->eof) {
1357 memset(conn->upsert_status, 0, sizeof(*conn->upsert_status));
1358 conn->upsert_status->warning_count = row_packet->warning_count;
1359 conn->upsert_status->server_status = row_packet->server_status;
1360 }
1361
1362 if (free_rows) {
1363
1364 if (set->row_count * sizeof(MYSQLND_MEMORY_POOL_CHUNK *) > SIZE_MAX) {
1365 SET_OOM_ERROR(*conn->error_info);
1366 ret = FAIL;
1367 goto end;
1368 }
1369 *row_buffers = mnd_perealloc(*row_buffers, (size_t) (set->row_count * sizeof(MYSQLND_MEMORY_POOL_CHUNK *)), 0);
1370 }
1371
1372 if (conn->upsert_status->server_status & SERVER_MORE_RESULTS_EXISTS) {
1373 CONN_SET_STATE(conn, CONN_NEXT_RESULT_PENDING);
1374 } else {
1375 CONN_SET_STATE(conn, CONN_READY);
1376 }
1377
1378 if (ret == FAIL) {
1379 COPY_CLIENT_ERROR(set->error_info, row_packet->error_info);
1380 } else {
1381
1382 conn->upsert_status->affected_rows = set->row_count;
1383 }
1384 DBG_INF_FMT("ret=%s row_count=%u warnings=%u server_status=%u",
1385 ret == PASS? "PASS":"FAIL", (uint) set->row_count, conn->upsert_status->warning_count, conn->upsert_status->server_status);
1386 end:
1387 PACKET_FREE(row_packet);
1388 DBG_INF_FMT("rows=%llu", (unsigned long long)result->stored_data->row_count);
1389 DBG_RETURN(ret);
1390 }
1391
1392
1393
1394
1395 static MYSQLND_RES *
1396 MYSQLND_METHOD(mysqlnd_res, store_result)(MYSQLND_RES * result,
1397 MYSQLND_CONN_DATA * const conn,
1398 const unsigned int flags)
1399 {
1400 enum_func_status ret;
1401 MYSQLND_MEMORY_POOL_CHUNK ***row_buffers = NULL;
1402
1403 DBG_ENTER("mysqlnd_res::store_result");
1404
1405
1406
1407 result->conn = conn->m->get_reference(conn);
1408 result->type = MYSQLND_RES_NORMAL;
1409
1410 CONN_SET_STATE(conn, CONN_FETCHING_DATA);
1411
1412 if (flags & MYSQLND_STORE_NO_COPY) {
1413 result->stored_data = (MYSQLND_RES_BUFFERED *) mysqlnd_result_buffered_zval_init(result->field_count, flags & MYSQLND_STORE_PS, result->persistent);
1414 if (!result->stored_data) {
1415 SET_OOM_ERROR(*conn->error_info);
1416 DBG_RETURN(NULL);
1417 }
1418 row_buffers = &result->stored_data->row_buffers;
1419 } else if (flags & MYSQLND_STORE_COPY) {
1420 result->stored_data = (MYSQLND_RES_BUFFERED *) mysqlnd_result_buffered_c_init(result->field_count, flags & MYSQLND_STORE_PS, result->persistent);
1421 if (!result->stored_data) {
1422 SET_OOM_ERROR(*conn->error_info);
1423 DBG_RETURN(NULL);
1424 }
1425 row_buffers = &result->stored_data->row_buffers;
1426 }
1427 ret = result->m.store_result_fetch_data(conn, result, result->meta, row_buffers, flags & MYSQLND_STORE_PS);
1428
1429 if (FAIL == ret) {
1430 if (result->stored_data) {
1431 COPY_CLIENT_ERROR(*conn->error_info, result->stored_data->error_info);
1432 } else {
1433 SET_OOM_ERROR(*conn->error_info);
1434 }
1435 DBG_RETURN(NULL);
1436 } else {
1437
1438 if (flags & MYSQLND_STORE_NO_COPY) {
1439 MYSQLND_RES_METADATA * meta = result->meta;
1440 MYSQLND_RES_BUFFERED_ZVAL * set = (MYSQLND_RES_BUFFERED_ZVAL *) result->stored_data;
1441 if (set->row_count) {
1442
1443 if (set->row_count * meta->field_count * sizeof(zval *) > SIZE_MAX) {
1444 SET_OOM_ERROR(*conn->error_info);
1445 DBG_RETURN(NULL);
1446 }
1447
1448 set->data = mnd_emalloc((size_t)(set->row_count * meta->field_count * sizeof(zval)));
1449 if (!set->data) {
1450 SET_OOM_ERROR(*conn->error_info);
1451 DBG_RETURN(NULL);
1452 }
1453 memset(set->data, 0, (size_t)(set->row_count * meta->field_count * sizeof(zval)));
1454 }
1455
1456 set->data_cursor = set->data;
1457 } else if (flags & MYSQLND_STORE_COPY) {
1458 MYSQLND_RES_BUFFERED_C * set = (MYSQLND_RES_BUFFERED_C *) result->stored_data;
1459 set->current_row = 0;
1460 set->initialized = mnd_pecalloc((set->row_count / 8) + 1, sizeof(zend_uchar), set->persistent);
1461 }
1462 }
1463
1464
1465 conn->upsert_status->affected_rows = result->stored_data->row_count;
1466
1467 DBG_RETURN(result);
1468 }
1469
1470
1471
1472
1473 static enum_func_status
1474 MYSQLND_METHOD(mysqlnd_res, skip_result)(MYSQLND_RES * const result)
1475 {
1476 zend_bool fetched_anything;
1477
1478 DBG_ENTER("mysqlnd_res::skip_result");
1479
1480
1481
1482
1483
1484 if (result->unbuf && !result->unbuf->eof_reached) {
1485 DBG_INF("skipping result");
1486
1487 MYSQLND_INC_CONN_STATISTIC(result->conn->stats,
1488 result->type == MYSQLND_RES_NORMAL? STAT_FLUSHED_NORMAL_SETS:
1489 STAT_FLUSHED_PS_SETS);
1490
1491 while ((PASS == result->m.fetch_row(result, NULL, 0, &fetched_anything)) && fetched_anything == TRUE) {
1492 ;
1493 }
1494 }
1495 DBG_RETURN(PASS);
1496 }
1497
1498
1499
1500
1501 static enum_func_status
1502 MYSQLND_METHOD(mysqlnd_res, free_result)(MYSQLND_RES * result, zend_bool implicit)
1503 {
1504 DBG_ENTER("mysqlnd_res::free_result");
1505
1506 MYSQLND_INC_CONN_STATISTIC(result->conn? result->conn->stats : NULL,
1507 implicit == TRUE? STAT_FREE_RESULT_IMPLICIT:
1508 STAT_FREE_RESULT_EXPLICIT);
1509
1510 result->m.free_result_internal(result);
1511 DBG_RETURN(PASS);
1512 }
1513
1514
1515
1516
1517 static enum_func_status
1518 MYSQLND_METHOD(mysqlnd_res, data_seek)(MYSQLND_RES * const result, const uint64_t row)
1519 {
1520 DBG_ENTER("mysqlnd_res::data_seek");
1521 DBG_INF_FMT("row=%lu", row);
1522
1523 DBG_RETURN(result->stored_data? result->stored_data->m.data_seek(result->stored_data, row) : FAIL);
1524 }
1525
1526
1527
1528
1529 static enum_func_status
1530 MYSQLND_METHOD(mysqlnd_result_buffered_zval, data_seek)(MYSQLND_RES_BUFFERED * const result, const uint64_t row)
1531 {
1532 MYSQLND_RES_BUFFERED_ZVAL * set = (MYSQLND_RES_BUFFERED_ZVAL *) result;
1533 DBG_ENTER("mysqlnd_result_buffered_zval::data_seek");
1534
1535
1536 if (row >= set->row_count) {
1537 set->data_cursor = NULL;
1538 } else {
1539 set->data_cursor = set->data + row * result->field_count;
1540 }
1541 DBG_RETURN(PASS);
1542 }
1543
1544
1545
1546
1547 static enum_func_status
1548 MYSQLND_METHOD(mysqlnd_result_buffered_c, data_seek)(MYSQLND_RES_BUFFERED * const result, const uint64_t row)
1549 {
1550 MYSQLND_RES_BUFFERED_C * set = (MYSQLND_RES_BUFFERED_C *) result;
1551 DBG_ENTER("mysqlnd_result_buffered_c::data_seek");
1552
1553
1554 if (row >= set->row_count) {
1555 set->current_row = set->row_count;
1556 } else {
1557 set->current_row = row;
1558 }
1559 DBG_RETURN(PASS);
1560 }
1561
1562
1563
1564
1565 static uint64_t
1566 MYSQLND_METHOD(mysqlnd_result_unbuffered, num_rows)(const MYSQLND_RES_UNBUFFERED * const result)
1567 {
1568
1569 return result->eof_reached? result->row_count:0;
1570 }
1571
1572
1573
1574
1575 static uint64_t
1576 MYSQLND_METHOD(mysqlnd_result_buffered, num_rows)(const MYSQLND_RES_BUFFERED * const result)
1577 {
1578 return result->row_count;
1579 }
1580
1581
1582
1583
1584 static uint64_t
1585 MYSQLND_METHOD(mysqlnd_res, num_rows)(const MYSQLND_RES * const result)
1586 {
1587 return result->stored_data?
1588 result->stored_data->m.num_rows(result->stored_data) :
1589 (result->unbuf? result->unbuf->m.num_rows(result->unbuf) : 0);
1590 }
1591
1592
1593
1594
1595 static unsigned int
1596 MYSQLND_METHOD(mysqlnd_res, num_fields)(const MYSQLND_RES * const result)
1597 {
1598 return result->field_count;
1599 }
1600
1601
1602
1603
1604 static const MYSQLND_FIELD *
1605 MYSQLND_METHOD(mysqlnd_res, fetch_field)(MYSQLND_RES * const result)
1606 {
1607 DBG_ENTER("mysqlnd_res::fetch_field");
1608 do {
1609 if (result->meta) {
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620 if (result->stored_data && (result->stored_data->initialized_rows < result->stored_data->row_count)) {
1621 DBG_INF_FMT("We have decode the whole result set to be able to satisfy this meta request");
1622
1623 if (PASS != result->stored_data->m.initialize_result_set_rest(result->stored_data, result->meta, result->conn->stats,
1624 result->conn->options->int_and_float_native))
1625 {
1626 break;
1627 }
1628 }
1629 DBG_RETURN(result->meta->m->fetch_field(result->meta));
1630 }
1631 } while (0);
1632 DBG_RETURN(NULL);
1633 }
1634
1635
1636
1637
1638 static const MYSQLND_FIELD *
1639 MYSQLND_METHOD(mysqlnd_res, fetch_field_direct)(MYSQLND_RES * const result, const MYSQLND_FIELD_OFFSET fieldnr)
1640 {
1641 DBG_ENTER("mysqlnd_res::fetch_field_direct");
1642 do {
1643 if (result->meta) {
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654 if (result->stored_data && (result->stored_data->initialized_rows < result->stored_data->row_count)) {
1655 DBG_INF_FMT("We have decode the whole result set to be able to satisfy this meta request");
1656
1657 if (PASS != result->stored_data->m.initialize_result_set_rest(result->stored_data, result->meta, result->conn->stats,
1658 result->conn->options->int_and_float_native))
1659 {
1660 break;
1661 }
1662 }
1663 DBG_RETURN(result->meta->m->fetch_field_direct(result->meta, fieldnr));
1664 }
1665 } while (0);
1666
1667 DBG_RETURN(NULL);
1668 }
1669
1670
1671
1672
1673 static const MYSQLND_FIELD *
1674 MYSQLND_METHOD(mysqlnd_res, fetch_fields)(MYSQLND_RES * const result)
1675 {
1676 DBG_ENTER("mysqlnd_res::fetch_fields");
1677 do {
1678 if (result->meta) {
1679 if (result->stored_data && (result->stored_data->initialized_rows < result->stored_data->row_count)) {
1680
1681 if (PASS != result->stored_data->m.initialize_result_set_rest(result->stored_data, result->meta, result->conn->stats,
1682 result->conn->options->int_and_float_native))
1683 {
1684 break;
1685 }
1686 }
1687 DBG_RETURN(result->meta->m->fetch_fields(result->meta));
1688 }
1689 } while (0);
1690 DBG_RETURN(NULL);
1691 }
1692
1693
1694
1695
1696 static MYSQLND_FIELD_OFFSET
1697 MYSQLND_METHOD(mysqlnd_res, field_seek)(MYSQLND_RES * const result, const MYSQLND_FIELD_OFFSET field_offset)
1698 {
1699 return result->meta? result->meta->m->field_seek(result->meta, field_offset) : 0;
1700 }
1701
1702
1703
1704
1705 static MYSQLND_FIELD_OFFSET
1706 MYSQLND_METHOD(mysqlnd_res, field_tell)(const MYSQLND_RES * const result)
1707 {
1708 return result->meta? result->meta->m->field_tell(result->meta) : 0;
1709 }
1710
1711
1712
1713
1714 static void
1715 MYSQLND_METHOD(mysqlnd_res, fetch_into)(MYSQLND_RES * result, const unsigned int flags,
1716 zval *return_value,
1717 enum_mysqlnd_extension extension ZEND_FILE_LINE_DC)
1718 {
1719 zend_bool fetched_anything;
1720
1721 DBG_ENTER("mysqlnd_res::fetch_into");
1722
1723
1724
1725
1726
1727 array_init_size(return_value, mysqlnd_num_fields(result) * 2);
1728 if (FAIL == result->m.fetch_row(result, (void *)return_value, flags, &fetched_anything)) {
1729 php_error_docref(NULL, E_WARNING, "Error while reading a row");
1730 zval_dtor(return_value);
1731 RETVAL_FALSE;
1732 } else if (fetched_anything == FALSE) {
1733 zval_dtor(return_value);
1734 switch (extension) {
1735 case MYSQLND_MYSQLI:
1736 RETVAL_NULL();
1737 break;
1738 case MYSQLND_MYSQL:
1739 RETVAL_FALSE;
1740 break;
1741 default:exit(0);
1742 }
1743 }
1744
1745
1746
1747
1748 DBG_VOID_RETURN;
1749 }
1750
1751
1752
1753
1754 static MYSQLND_ROW_C
1755 MYSQLND_METHOD(mysqlnd_res, fetch_row_c)(MYSQLND_RES * result)
1756 {
1757 zend_bool fetched_anything;
1758 MYSQLND_ROW_C ret = NULL;
1759 DBG_ENTER("mysqlnd_res::fetch_row_c");
1760
1761 if (result->stored_data && result->stored_data->m.fetch_row == MYSQLND_METHOD(mysqlnd_result_buffered_zval, fetch_row)) {
1762 MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row_c)(result, (void *) &ret, 0, &fetched_anything);
1763 } else if (result->unbuf && result->unbuf->m.fetch_row == MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row)) {
1764 MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row_c)(result, (void *) &ret, 0, &fetched_anything);
1765 } else {
1766 ret = NULL;
1767 php_error_docref(NULL, E_ERROR, "result->m.fetch_row has invalid value. Report to the developers");
1768 }
1769 DBG_RETURN(ret);
1770 }
1771
1772
1773
1774
1775 static void
1776 MYSQLND_METHOD(mysqlnd_res, fetch_all)(MYSQLND_RES * result, const unsigned int flags, zval *return_value ZEND_FILE_LINE_DC)
1777 {
1778 zval row;
1779 zend_ulong i = 0;
1780 MYSQLND_RES_BUFFERED *set = result->stored_data;
1781
1782 DBG_ENTER("mysqlnd_res::fetch_all");
1783
1784 if ((!result->unbuf && !set)) {
1785 php_error_docref(NULL, E_WARNING, "fetch_all can be used only with buffered sets");
1786 if (result->conn) {
1787 SET_CLIENT_ERROR(*result->conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE, "fetch_all can be used only with buffered sets");
1788 }
1789 RETVAL_NULL();
1790 DBG_VOID_RETURN;
1791 }
1792
1793
1794 array_init_size(return_value, set? (unsigned int) set->row_count : 4);
1795
1796 do {
1797 mysqlnd_fetch_into(result, flags, &row, MYSQLND_MYSQLI);
1798 if (Z_TYPE(row) != IS_ARRAY) {
1799 zval_ptr_dtor(&row);
1800 break;
1801 }
1802 add_index_zval(return_value, i++, &row);
1803 } while (1);
1804
1805 DBG_VOID_RETURN;
1806 }
1807
1808
1809
1810
1811 static void
1812 MYSQLND_METHOD(mysqlnd_res, fetch_field_data)(MYSQLND_RES * result, unsigned int offset, zval *return_value)
1813 {
1814 zval row;
1815 zval *entry;
1816 unsigned int i = 0;
1817
1818 DBG_ENTER("mysqlnd_res::fetch_field_data");
1819 DBG_INF_FMT("offset=%u", offset);
1820
1821
1822
1823
1824 mysqlnd_fetch_into(result, MYSQLND_FETCH_NUM, &row, MYSQLND_MYSQL);
1825 if (Z_TYPE(row) != IS_ARRAY) {
1826 zval_dtor(&row);
1827 RETVAL_NULL();
1828 DBG_VOID_RETURN;
1829 }
1830
1831 zend_hash_internal_pointer_reset(Z_ARRVAL(row));
1832 while (i++ < offset) {
1833 zend_hash_move_forward(Z_ARRVAL(row));
1834 }
1835
1836 entry = zend_hash_get_current_data(Z_ARRVAL(row));
1837
1838 ZVAL_COPY(return_value, entry);
1839 zval_dtor(&row);
1840
1841 DBG_VOID_RETURN;
1842 }
1843
1844
1845
1846 MYSQLND_CLASS_METHODS_START(mysqlnd_res)
1847 MYSQLND_METHOD(mysqlnd_res, fetch_row),
1848 MYSQLND_METHOD(mysqlnd_res, use_result),
1849 MYSQLND_METHOD(mysqlnd_res, store_result),
1850 MYSQLND_METHOD(mysqlnd_res, fetch_into),
1851 MYSQLND_METHOD(mysqlnd_res, fetch_row_c),
1852 MYSQLND_METHOD(mysqlnd_res, fetch_all),
1853 MYSQLND_METHOD(mysqlnd_res, fetch_field_data),
1854 MYSQLND_METHOD(mysqlnd_res, num_rows),
1855 MYSQLND_METHOD(mysqlnd_res, num_fields),
1856 MYSQLND_METHOD(mysqlnd_res, skip_result),
1857 MYSQLND_METHOD(mysqlnd_res, data_seek),
1858 MYSQLND_METHOD(mysqlnd_res, field_seek),
1859 MYSQLND_METHOD(mysqlnd_res, field_tell),
1860 MYSQLND_METHOD(mysqlnd_res, fetch_field),
1861 MYSQLND_METHOD(mysqlnd_res, fetch_field_direct),
1862 MYSQLND_METHOD(mysqlnd_res, fetch_fields),
1863 MYSQLND_METHOD(mysqlnd_res, read_result_metadata),
1864 MYSQLND_METHOD(mysqlnd_res, fetch_lengths),
1865 MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data),
1866 MYSQLND_METHOD(mysqlnd_res, free_result_buffers),
1867 MYSQLND_METHOD(mysqlnd_res, free_result),
1868 MYSQLND_METHOD(mysqlnd_res, free_result_internal),
1869 MYSQLND_METHOD(mysqlnd_res, free_result_contents_internal),
1870 mysqlnd_result_meta_init
1871 MYSQLND_CLASS_METHODS_END;
1872
1873
1874 MYSQLND_CLASS_METHODS_START(mysqlnd_result_unbuffered)
1875 MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row),
1876 NULL,
1877 MYSQLND_METHOD(mysqlnd_result_unbuffered, num_rows),
1878 MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_lengths),
1879 MYSQLND_METHOD(mysqlnd_result_unbuffered, free_last_data),
1880 MYSQLND_METHOD(mysqlnd_result_unbuffered, free_result)
1881 MYSQLND_CLASS_METHODS_END;
1882
1883
1884 MYSQLND_CLASS_METHODS_START(mysqlnd_result_buffered)
1885 NULL,
1886 NULL,
1887 MYSQLND_METHOD(mysqlnd_result_buffered, num_rows),
1888 NULL,
1889 NULL,
1890 NULL,
1891 MYSQLND_METHOD(mysqlnd_result_buffered, free_result)
1892 MYSQLND_CLASS_METHODS_END;
1893
1894
1895
1896 PHPAPI MYSQLND_RES *
1897 mysqlnd_result_init(unsigned int field_count, zend_bool persistent)
1898 {
1899 size_t alloc_size = sizeof(MYSQLND_RES) + mysqlnd_plugin_count() * sizeof(void *);
1900 MYSQLND_RES * ret = mnd_pecalloc(1, alloc_size, persistent);
1901
1902 DBG_ENTER("mysqlnd_result_init");
1903
1904 if (!ret) {
1905 DBG_RETURN(NULL);
1906 }
1907
1908 ret->persistent = persistent;
1909 ret->field_count = field_count;
1910 ret->m = *mysqlnd_result_get_methods();
1911
1912 DBG_RETURN(ret);
1913 }
1914
1915
1916
1917
1918 PHPAPI MYSQLND_RES_UNBUFFERED *
1919 mysqlnd_result_unbuffered_init(unsigned int field_count, zend_bool ps, zend_bool persistent)
1920 {
1921 size_t alloc_size = sizeof(MYSQLND_RES_UNBUFFERED) + mysqlnd_plugin_count() * sizeof(void *);
1922 MYSQLND_RES_UNBUFFERED * ret = mnd_pecalloc(1, alloc_size, persistent);
1923
1924 DBG_ENTER("mysqlnd_result_unbuffered_init");
1925
1926 if (!ret) {
1927 DBG_RETURN(NULL);
1928 }
1929
1930 if (!(ret->lengths = mnd_pecalloc(field_count, sizeof(zend_ulong), persistent))) {
1931 mnd_pefree(ret, persistent);
1932 DBG_RETURN(NULL);
1933 }
1934 if (!(ret->result_set_memory_pool = mysqlnd_mempool_create(MYSQLND_G(mempool_default_size)))) {
1935 mnd_efree(ret->lengths);
1936 mnd_pefree(ret, persistent);
1937 DBG_RETURN(NULL);
1938 }
1939
1940 ret->persistent = persistent;
1941 ret->field_count= field_count;
1942 ret->ps = ps;
1943
1944 ret->m = *mysqlnd_result_unbuffered_get_methods();
1945
1946 if (ps) {
1947 ret->m.fetch_lengths = NULL;
1948 ret->m.row_decoder = php_mysqlnd_rowp_read_binary_protocol;
1949 } else {
1950 ret->m.row_decoder = php_mysqlnd_rowp_read_text_protocol_zval;
1951 }
1952
1953 DBG_RETURN(ret);
1954 }
1955
1956
1957
1958
1959 PHPAPI MYSQLND_RES_BUFFERED_ZVAL *
1960 mysqlnd_result_buffered_zval_init(unsigned int field_count, zend_bool ps, zend_bool persistent)
1961 {
1962 size_t alloc_size = sizeof(MYSQLND_RES_BUFFERED_ZVAL) + mysqlnd_plugin_count() * sizeof(void *);
1963 MYSQLND_RES_BUFFERED_ZVAL * ret = mnd_pecalloc(1, alloc_size, persistent);
1964
1965 DBG_ENTER("mysqlnd_result_buffered_zval_init");
1966
1967 if (!ret) {
1968 DBG_RETURN(NULL);
1969 }
1970 if (!(ret->lengths = mnd_pecalloc(field_count, sizeof(zend_ulong), persistent))) {
1971 mnd_pefree(ret, persistent);
1972 DBG_RETURN(NULL);
1973 }
1974 if (!(ret->result_set_memory_pool = mysqlnd_mempool_create(MYSQLND_G(mempool_default_size)))) {
1975 mnd_efree(ret->lengths);
1976 mnd_pefree(ret, persistent);
1977 DBG_RETURN(NULL);
1978 }
1979
1980 ret->persistent = persistent;
1981 ret->field_count= field_count;
1982 ret->ps = ps;
1983 ret->m = *mysqlnd_result_buffered_get_methods();
1984 ret->type = MYSQLND_BUFFERED_TYPE_ZVAL;
1985
1986 if (ps) {
1987 ret->m.fetch_lengths = NULL;
1988 ret->m.row_decoder = php_mysqlnd_rowp_read_binary_protocol;
1989 } else {
1990 ret->m.row_decoder = php_mysqlnd_rowp_read_text_protocol_zval;
1991 }
1992 ret->m.fetch_row = MYSQLND_METHOD(mysqlnd_result_buffered_zval, fetch_row);
1993 ret->m.fetch_lengths = MYSQLND_METHOD(mysqlnd_result_buffered_zval, fetch_lengths);
1994 ret->m.data_seek = MYSQLND_METHOD(mysqlnd_result_buffered_zval, data_seek);
1995 ret->m.initialize_result_set_rest = MYSQLND_METHOD(mysqlnd_result_buffered_zval, initialize_result_set_rest);
1996 DBG_RETURN(ret);
1997 }
1998
1999
2000
2001
2002 PHPAPI MYSQLND_RES_BUFFERED_C *
2003 mysqlnd_result_buffered_c_init(unsigned int field_count, zend_bool ps, zend_bool persistent)
2004 {
2005 size_t alloc_size = sizeof(MYSQLND_RES_BUFFERED_C) + mysqlnd_plugin_count() * sizeof(void *);
2006 MYSQLND_RES_BUFFERED_C * ret = mnd_pecalloc(1, alloc_size, persistent);
2007
2008 DBG_ENTER("mysqlnd_result_buffered_c_init");
2009
2010 if (!ret) {
2011 DBG_RETURN(NULL);
2012 }
2013 if (!(ret->lengths = mnd_pecalloc(field_count, sizeof(zend_ulong), persistent))) {
2014 mnd_pefree(ret, persistent);
2015 DBG_RETURN(NULL);
2016 }
2017 if (!(ret->result_set_memory_pool = mysqlnd_mempool_create(MYSQLND_G(mempool_default_size)))) {
2018 mnd_efree(ret->lengths);
2019 mnd_pefree(ret, persistent);
2020 DBG_RETURN(NULL);
2021 }
2022
2023 ret->persistent = persistent;
2024 ret->field_count= field_count;
2025 ret->ps = ps;
2026 ret->m = *mysqlnd_result_buffered_get_methods();
2027 ret->type = MYSQLND_BUFFERED_TYPE_C;
2028
2029 if (ps) {
2030 ret->m.fetch_lengths = NULL;
2031 ret->m.row_decoder = php_mysqlnd_rowp_read_binary_protocol;
2032 } else {
2033 ret->m.row_decoder = php_mysqlnd_rowp_read_text_protocol_c;
2034 }
2035 ret->m.fetch_row = MYSQLND_METHOD(mysqlnd_result_buffered_c, fetch_row);
2036 ret->m.fetch_lengths = MYSQLND_METHOD(mysqlnd_result_buffered_c, fetch_lengths);
2037 ret->m.data_seek = MYSQLND_METHOD(mysqlnd_result_buffered_c, data_seek);
2038 ret->m.initialize_result_set_rest = MYSQLND_METHOD(mysqlnd_result_buffered_c, initialize_result_set_rest);
2039
2040 DBG_RETURN(ret);
2041 }
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052