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