This source file includes following definitions.
- PHP_FUNCTION
- rewrite_name_to_position
- dispatch_param_event
- pdo_stmt_describe_columns
- get_lazy_object
- param_dtor
- really_register_bound_param
- PHP_METHOD
- fetch_value
- do_fetch_common
- do_fetch_class_prepare
- make_callable_ex
- do_fetch_func_prepare
- do_fetch_opt_finish
- do_fetch
- pdo_stmt_verify_mode
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- register_bound_param
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- generic_stmt_attr_get
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- pdo_stmt_setup_fetch_mode
- PHP_METHOD
- pdo_stmt_do_next_rowset
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- PHP_METHOD
- dbstmt_prop_write
- dbstmt_prop_delete
- dbstmt_method_get
- dbstmt_compare
- dbstmt_clone_obj
- pdo_stmt_init
- php_pdo_free_statement
- pdo_dbstmt_free_storage
- pdo_dbstmt_new
- pdo_stmt_iter_dtor
- pdo_stmt_iter_valid
- pdo_stmt_iter_get_data
- pdo_stmt_iter_get_key
- pdo_stmt_iter_move_forwards
- pdo_stmt_iter_get
- row_prop_read
- row_dim_read
- row_prop_write
- row_dim_write
- row_prop_exists
- row_dim_exists
- row_prop_delete
- row_dim_delete
- row_get_properties
- row_method_get
- row_call_method
- row_get_ctor
- row_get_classname
- row_compare
- pdo_row_free_storage
- pdo_row_new
- pdo_row_serialize
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #include "php.h"
30 #include "php_ini.h"
31 #include "ext/standard/info.h"
32 #include "ext/standard/php_var.h"
33 #include "php_pdo.h"
34 #include "php_pdo_driver.h"
35 #include "php_pdo_int.h"
36 #include "zend_exceptions.h"
37 #include "zend_interfaces.h"
38 #include "php_memory_streams.h"
39
40
41 ZEND_BEGIN_ARG_INFO(arginfo_pdostatement__void, 0)
42 ZEND_END_ARG_INFO()
43
44 ZEND_BEGIN_ARG_INFO_EX(arginfo_pdostatement_execute, 0, 0, 0)
45 ZEND_ARG_INFO(0, bound_input_params)
46 ZEND_END_ARG_INFO()
47
48 ZEND_BEGIN_ARG_INFO_EX(arginfo_pdostatement_fetch, 0, 0, 0)
49 ZEND_ARG_INFO(0, how)
50 ZEND_ARG_INFO(0, orientation)
51 ZEND_ARG_INFO(0, offset)
52 ZEND_END_ARG_INFO()
53
54 ZEND_BEGIN_ARG_INFO_EX(arginfo_pdostatement_fetchobject, 0, 0, 0)
55 ZEND_ARG_INFO(0, class_name)
56 ZEND_ARG_INFO(0, ctor_args)
57 ZEND_END_ARG_INFO()
58
59 ZEND_BEGIN_ARG_INFO_EX(arginfo_pdostatement_fetchcolumn, 0, 0, 0)
60 ZEND_ARG_INFO(0, column_number)
61 ZEND_END_ARG_INFO()
62
63 ZEND_BEGIN_ARG_INFO_EX(arginfo_pdostatement_fetchall, 0, 0, 0)
64 ZEND_ARG_INFO(0, how)
65 ZEND_ARG_INFO(0, class_name)
66 ZEND_ARG_INFO(0, ctor_args)
67 ZEND_END_ARG_INFO()
68
69 ZEND_BEGIN_ARG_INFO_EX(arginfo_pdostatement_bindvalue, 0, 0, 2)
70 ZEND_ARG_INFO(0, paramno)
71 ZEND_ARG_INFO(0, param)
72 ZEND_ARG_INFO(0, type)
73 ZEND_END_ARG_INFO()
74
75 ZEND_BEGIN_ARG_INFO_EX(arginfo_pdostatement_bindparam, 0, 0, 2)
76 ZEND_ARG_INFO(0, paramno)
77 ZEND_ARG_INFO(1, param)
78 ZEND_ARG_INFO(0, type)
79 ZEND_ARG_INFO(0, maxlen)
80 ZEND_ARG_INFO(0, driverdata)
81 ZEND_END_ARG_INFO()
82
83 ZEND_BEGIN_ARG_INFO_EX(arginfo_pdostatement_bindcolumn, 0, 0, 2)
84 ZEND_ARG_INFO(0, column)
85 ZEND_ARG_INFO(1, param)
86 ZEND_ARG_INFO(0, type)
87 ZEND_ARG_INFO(0, maxlen)
88 ZEND_ARG_INFO(0, driverdata)
89 ZEND_END_ARG_INFO()
90
91 ZEND_BEGIN_ARG_INFO(arginfo_pdostatement_setattribute, 0)
92 ZEND_ARG_INFO(0, attribute)
93 ZEND_ARG_INFO(0, value)
94 ZEND_END_ARG_INFO()
95
96 ZEND_BEGIN_ARG_INFO(arginfo_pdostatement_getattribute, 0)
97 ZEND_ARG_INFO(0, attribute)
98 ZEND_END_ARG_INFO()
99
100 ZEND_BEGIN_ARG_INFO(arginfo_pdostatement_getcolumnmeta, 0)
101 ZEND_ARG_INFO(0, column)
102 ZEND_END_ARG_INFO()
103
104 ZEND_BEGIN_ARG_INFO_EX(arginfo_pdostatement_setfetchmode, 0, 0, 1)
105 ZEND_ARG_INFO(0, mode)
106 ZEND_ARG_INFO(0, params)
107 ZEND_END_ARG_INFO()
108
109
110 #define PHP_STMT_GET_OBJ \
111 pdo_stmt_t *stmt = Z_PDO_STMT_P(getThis()); \
112 if (!stmt->dbh) { \
113 RETURN_FALSE; \
114 } \
115
116 static PHP_FUNCTION(dbrow_constructor)
117 {
118 zend_throw_exception_ex(php_pdo_get_exception(), 0, "You may not create a PDORow manually");
119 }
120
121
122 static inline int rewrite_name_to_position(pdo_stmt_t *stmt, struct pdo_bound_param_data *param)
123 {
124 if (stmt->bound_param_map) {
125
126
127
128
129
130
131 char *name;
132 int position = 0;
133
134 if (stmt->named_rewrite_template) {
135
136 return 1;
137 }
138 if (!param->name) {
139
140 if ((name = zend_hash_index_find_ptr(stmt->bound_param_map, param->paramno)) != NULL) {
141 param->name = zend_string_init(name, strlen(name), 0);
142 return 1;
143 }
144 pdo_raise_impl_error(stmt->dbh, stmt, "HY093", "parameter was not defined");
145 return 0;
146 }
147
148 ZEND_HASH_FOREACH_PTR(stmt->bound_param_map, name) {
149 if (strncmp(name, ZSTR_VAL(param->name), ZSTR_LEN(param->name) + 1)) {
150 position++;
151 continue;
152 }
153 if (param->paramno >= 0) {
154 pdo_raise_impl_error(stmt->dbh, stmt, "IM001", "PDO refuses to handle repeating the same :named parameter for multiple positions with this driver, as it might be unsafe to do so. Consider using a separate name for each parameter instead");
155 return -1;
156 }
157 param->paramno = position;
158 return 1;
159 } ZEND_HASH_FOREACH_END();
160 pdo_raise_impl_error(stmt->dbh, stmt, "HY093", "parameter was not defined");
161 return 0;
162 }
163 return 1;
164 }
165
166
167
168 static int dispatch_param_event(pdo_stmt_t *stmt, enum pdo_param_event event_type)
169 {
170 int ret = 1, is_param = 1;
171 struct pdo_bound_param_data *param;
172 HashTable *ht;
173
174 if (!stmt->methods->param_hook) {
175 return 1;
176 }
177
178 ht = stmt->bound_params;
179
180 iterate:
181 if (ht) {
182 ZEND_HASH_FOREACH_PTR(ht, param) {
183 if (!stmt->methods->param_hook(stmt, param, event_type)) {
184 ret = 0;
185 break;
186 }
187 } ZEND_HASH_FOREACH_END();
188 }
189 if (ret && is_param) {
190 ht = stmt->bound_columns;
191 is_param = 0;
192 goto iterate;
193 }
194
195 return ret;
196 }
197
198
199 int pdo_stmt_describe_columns(pdo_stmt_t *stmt)
200 {
201 int col;
202
203 stmt->columns = ecalloc(stmt->column_count, sizeof(struct pdo_column_data));
204
205 for (col = 0; col < stmt->column_count; col++) {
206 if (!stmt->methods->describer(stmt, col)) {
207 return 0;
208 }
209
210
211 if (stmt->dbh->native_case != stmt->dbh->desired_case && stmt->dbh->desired_case != PDO_CASE_NATURAL) {
212 char *s = ZSTR_VAL(stmt->columns[col].name);
213
214 switch (stmt->dbh->desired_case) {
215 case PDO_CASE_UPPER:
216 while (*s != '\0') {
217 *s = toupper(*s);
218 s++;
219 }
220 break;
221 case PDO_CASE_LOWER:
222 while (*s != '\0') {
223 *s = tolower(*s);
224 s++;
225 }
226 break;
227 default:
228 ;
229 }
230 }
231
232 #if 0
233
234 if (stmt->bound_params) {
235 struct pdo_bound_param_data *param;
236
237 if (SUCCESS == zend_hash_find(stmt->bound_params, stmt->columns[col].name,
238 stmt->columns[col].namelen, (void**)¶m)) {
239 param->paramno = col;
240 }
241 }
242 #endif
243 if (stmt->bound_columns) {
244 struct pdo_bound_param_data *param;
245
246 if ((param = zend_hash_find_ptr(stmt->bound_columns,
247 stmt->columns[col].name)) != NULL) {
248 param->paramno = col;
249 }
250 }
251
252 }
253 return 1;
254 }
255
256
257 static void get_lazy_object(pdo_stmt_t *stmt, zval *return_value)
258 {
259 if (Z_ISUNDEF(stmt->lazy_object_ref)) {
260 pdo_row_t *row = ecalloc(1, sizeof(pdo_row_t));
261 row->stmt = stmt;
262 zend_object_std_init(&row->std, pdo_row_ce);
263 ZVAL_OBJ(&stmt->lazy_object_ref, &row->std);
264 row->std.handlers = &pdo_row_object_handlers;
265 GC_REFCOUNT(&stmt->std)++;
266 GC_REFCOUNT(&row->std)--;
267 }
268 ZVAL_COPY(return_value, &stmt->lazy_object_ref);
269 }
270
271
272 static void param_dtor(zval *el)
273 {
274 struct pdo_bound_param_data *param = (struct pdo_bound_param_data *)Z_PTR_P(el);
275
276
277 if (param->stmt->methods->param_hook) {
278 param->stmt->methods->param_hook(param->stmt, param, PDO_PARAM_EVT_FREE);
279 }
280
281 if (param->name) {
282 zend_string_release(param->name);
283 }
284
285 if (!Z_ISUNDEF(param->parameter)) {
286 zval_ptr_dtor(¶m->parameter);
287 ZVAL_UNDEF(¶m->parameter);
288 }
289 if (!Z_ISUNDEF(param->driver_params)) {
290 zval_ptr_dtor(¶m->driver_params);
291 }
292 efree(param);
293 }
294
295
296 static int really_register_bound_param(struct pdo_bound_param_data *param, pdo_stmt_t *stmt, int is_param)
297 {
298 HashTable *hash;
299 zval *parameter;
300 struct pdo_bound_param_data *pparam = NULL;
301
302 hash = is_param ? stmt->bound_params : stmt->bound_columns;
303
304 if (!hash) {
305 ALLOC_HASHTABLE(hash);
306 zend_hash_init(hash, 13, NULL, param_dtor, 0);
307
308 if (is_param) {
309 stmt->bound_params = hash;
310 } else {
311 stmt->bound_columns = hash;
312 }
313 }
314
315 if (!Z_ISREF(param->parameter)) {
316 parameter = ¶m->parameter;
317 } else {
318 parameter = Z_REFVAL(param->parameter);
319 }
320
321 if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_STR && param->max_value_len <= 0 && !Z_ISNULL_P(parameter)) {
322 if (Z_TYPE_P(parameter) == IS_DOUBLE) {
323 char *p;
324 int len = spprintf(&p, 0, "%.*H", (int) EG(precision), Z_DVAL_P(parameter));
325 ZVAL_STRINGL(parameter, p, len);
326 efree(p);
327 } else {
328 convert_to_string(parameter);
329 }
330 } else if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_INT && (Z_TYPE_P(parameter) == IS_FALSE || Z_TYPE_P(parameter) == IS_TRUE)) {
331 convert_to_long(parameter);
332 } else if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_BOOL && Z_TYPE_P(parameter) == IS_LONG) {
333 convert_to_boolean(parameter);
334 }
335
336 param->stmt = stmt;
337 param->is_param = is_param;
338
339 if (Z_REFCOUNTED(param->driver_params)) {
340 Z_ADDREF(param->driver_params);
341 }
342
343 if (!is_param && param->name && stmt->columns) {
344
345 int i;
346
347 for (i = 0; i < stmt->column_count; i++) {
348 if (ZSTR_LEN(stmt->columns[i].name) == ZSTR_LEN(param->name) &&
349 strncmp(ZSTR_VAL(stmt->columns[i].name), ZSTR_VAL(param->name), ZSTR_LEN(param->name) + 1) == 0) {
350 param->paramno = i;
351 break;
352 }
353 }
354
355
356
357 if (param->paramno == -1) {
358 char *tmp;
359 spprintf(&tmp, 0, "Did not find column name '%s' in the defined columns; it will not be bound", ZSTR_VAL(param->name));
360 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", tmp);
361 efree(tmp);
362 }
363 }
364
365 if (param->name) {
366 if (is_param && ZSTR_VAL(param->name)[0] != ':') {
367 zend_string *temp = zend_string_alloc(ZSTR_LEN(param->name) + 1, 0);
368 ZSTR_VAL(temp)[0] = ':';
369 memmove(ZSTR_VAL(temp) + 1, ZSTR_VAL(param->name), ZSTR_LEN(param->name) + 1);
370 param->name = temp;
371 } else {
372 param->name = zend_string_init(ZSTR_VAL(param->name), ZSTR_LEN(param->name), 0);
373 }
374 }
375
376 if (is_param && !rewrite_name_to_position(stmt, param)) {
377 if (param->name) {
378 zend_string_release(param->name);
379 param->name = NULL;
380 }
381 return 0;
382 }
383
384
385
386
387
388 if (stmt->methods->param_hook) {
389 if (!stmt->methods->param_hook(stmt, param, PDO_PARAM_EVT_NORMALIZE
390 )) {
391 if (param->name) {
392 zend_string_release(param->name);
393 param->name = NULL;
394 }
395 return 0;
396 }
397 }
398
399
400
401
402 if (param->paramno >= 0) {
403 zend_hash_index_del(hash, param->paramno);
404 }
405
406
407 if (param->name) {
408 pparam = zend_hash_update_mem(hash, param->name, param, sizeof(struct pdo_bound_param_data));
409 } else {
410 pparam = zend_hash_index_update_mem(hash, param->paramno, param, sizeof(struct pdo_bound_param_data));
411 }
412
413
414 if (stmt->methods->param_hook) {
415 if (!stmt->methods->param_hook(stmt, pparam, PDO_PARAM_EVT_ALLOC
416 )) {
417
418
419 if (pparam->name) {
420 zend_hash_del(hash, pparam->name);
421 } else {
422 zend_hash_index_del(hash, pparam->paramno);
423 }
424
425 ZVAL_UNDEF(¶m->parameter);
426 return 0;
427 }
428 }
429 return 1;
430 }
431
432
433
434
435 static PHP_METHOD(PDOStatement, execute)
436 {
437 zval *input_params = NULL;
438 int ret = 1;
439 PHP_STMT_GET_OBJ;
440
441 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "|a!", &input_params)) {
442 RETURN_FALSE;
443 }
444
445 PDO_STMT_CLEAR_ERR();
446
447 if (input_params) {
448 struct pdo_bound_param_data param;
449 zval *tmp;
450 zend_string *key = NULL;
451 zend_ulong num_index;
452
453 if (stmt->bound_params) {
454 zend_hash_destroy(stmt->bound_params);
455 FREE_HASHTABLE(stmt->bound_params);
456 stmt->bound_params = NULL;
457 }
458
459 ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(input_params), num_index, key, tmp) {
460 memset(¶m, 0, sizeof(param));
461
462 if (key) {
463
464 param.name = key;
465 param.paramno = -1;
466 } else {
467
468
469
470
471
472
473
474 param.paramno = num_index;
475 }
476
477 param.param_type = PDO_PARAM_STR;
478 ZVAL_COPY(¶m.parameter, tmp);
479
480 if (!really_register_bound_param(¶m, stmt, 1)) {
481 if (!Z_ISUNDEF(param.parameter)) {
482 zval_ptr_dtor(¶m.parameter);
483 }
484 RETURN_FALSE;
485 }
486 } ZEND_HASH_FOREACH_END();
487 }
488
489 if (PDO_PLACEHOLDER_NONE == stmt->supports_placeholders) {
490
491
492
493
494
495 ret = pdo_parse_params(stmt, stmt->query_string, stmt->query_stringlen,
496 &stmt->active_query_string, &stmt->active_query_stringlen);
497
498 if (ret == 0) {
499
500 stmt->active_query_string = stmt->query_string;
501 stmt->active_query_stringlen = stmt->query_stringlen;
502 ret = 1;
503 } else if (ret == -1) {
504
505 PDO_HANDLE_STMT_ERR();
506 RETURN_FALSE;
507 }
508 } else if (!dispatch_param_event(stmt, PDO_PARAM_EVT_EXEC_PRE)) {
509 PDO_HANDLE_STMT_ERR();
510 RETURN_FALSE;
511 }
512 if (stmt->methods->executer(stmt)) {
513 if (stmt->active_query_string && stmt->active_query_string != stmt->query_string) {
514 efree(stmt->active_query_string);
515 }
516 stmt->active_query_string = NULL;
517 if (!stmt->executed) {
518
519
520 if (stmt->dbh->alloc_own_columns && !stmt->columns) {
521
522
523 ret = pdo_stmt_describe_columns(stmt);
524 }
525
526 stmt->executed = 1;
527 }
528
529 if (ret && !dispatch_param_event(stmt, PDO_PARAM_EVT_EXEC_POST)) {
530 RETURN_FALSE;
531 }
532
533 RETURN_BOOL(ret);
534 }
535 if (stmt->active_query_string && stmt->active_query_string != stmt->query_string) {
536 efree(stmt->active_query_string);
537 }
538 stmt->active_query_string = NULL;
539 PDO_HANDLE_STMT_ERR();
540 RETURN_FALSE;
541 }
542
543
544 static inline void fetch_value(pdo_stmt_t *stmt, zval *dest, int colno, int *type_override)
545 {
546 struct pdo_column_data *col;
547 char *value = NULL;
548 size_t value_len = 0;
549 int caller_frees = 0;
550 int type, new_type;
551
552 col = &stmt->columns[colno];
553 type = PDO_PARAM_TYPE(col->param_type);
554 new_type = type_override ? PDO_PARAM_TYPE(*type_override) : type;
555
556 value = NULL;
557 value_len = 0;
558
559 stmt->methods->get_col(stmt, colno, &value, &value_len, &caller_frees);
560
561 switch (type) {
562 case PDO_PARAM_ZVAL:
563 if (value && value_len == sizeof(zval)) {
564 ZVAL_COPY_VALUE(dest, (zval *)value);
565 } else {
566 ZVAL_NULL(dest);
567 }
568
569 if (Z_TYPE_P(dest) == IS_NULL) {
570 type = new_type;
571 }
572 break;
573
574 case PDO_PARAM_INT:
575 if (value && value_len == sizeof(zend_long)) {
576 ZVAL_LONG(dest, *(zend_long*)value);
577 break;
578 }
579 ZVAL_NULL(dest);
580 break;
581
582 case PDO_PARAM_BOOL:
583 if (value && value_len == sizeof(zend_bool)) {
584 ZVAL_BOOL(dest, *(zend_bool*)value);
585 break;
586 }
587 ZVAL_NULL(dest);
588 break;
589
590 case PDO_PARAM_LOB:
591 if (value == NULL) {
592 ZVAL_NULL(dest);
593 } else if (value_len == 0) {
594
595 if (stmt->dbh->stringify || new_type == PDO_PARAM_STR) {
596 zend_string *buf;
597 buf = php_stream_copy_to_mem((php_stream*)value, PHP_STREAM_COPY_ALL, 0);
598 if (buf == NULL) {
599 ZVAL_EMPTY_STRING(dest);
600 } else {
601 ZVAL_STR(dest, buf);
602 }
603 php_stream_close((php_stream*)value);
604 } else {
605 php_stream_to_zval((php_stream*)value, dest);
606 }
607 } else if (!stmt->dbh->stringify && new_type != PDO_PARAM_STR) {
608
609 php_stream *stm;
610 #ifdef TEMP_STREAM_TAKE_BUFFER
611 if (caller_frees) {
612 stm = php_stream_memory_open(TEMP_STREAM_TAKE_BUFFER, value, value_len);
613 if (stm) {
614 caller_frees = 0;
615 }
616 } else
617 #endif
618 {
619 stm = php_stream_memory_open(TEMP_STREAM_READONLY, value, value_len);
620 }
621 if (stm) {
622 php_stream_to_zval(stm, dest);
623 } else {
624 ZVAL_NULL(dest);
625 }
626 } else {
627 ZVAL_STRINGL(dest, value, value_len);
628 }
629 break;
630
631 case PDO_PARAM_STR:
632 if (value && !(value_len == 0 && stmt->dbh->oracle_nulls == PDO_NULL_EMPTY_STRING)) {
633 ZVAL_STRINGL(dest, value, value_len);
634 break;
635 }
636 default:
637 ZVAL_NULL(dest);
638 }
639
640 if (type != new_type) {
641 switch (new_type) {
642 case PDO_PARAM_INT:
643 convert_to_long_ex(dest);
644 break;
645 case PDO_PARAM_BOOL:
646 convert_to_boolean_ex(dest);
647 break;
648 case PDO_PARAM_STR:
649 convert_to_string_ex(dest);
650 break;
651 case PDO_PARAM_NULL:
652 convert_to_null_ex(dest);
653 break;
654 default:
655 ;
656 }
657 }
658
659 if (caller_frees && value) {
660 efree(value);
661 }
662
663 if (stmt->dbh->stringify) {
664 switch (Z_TYPE_P(dest)) {
665 case IS_LONG:
666 case IS_DOUBLE:
667 convert_to_string(dest);
668 break;
669 }
670 }
671
672 if (Z_TYPE_P(dest) == IS_NULL && stmt->dbh->oracle_nulls == PDO_NULL_TO_STRING) {
673 ZVAL_EMPTY_STRING(dest);
674 }
675 }
676
677
678 static int do_fetch_common(pdo_stmt_t *stmt, enum pdo_fetch_orientation ori, zend_long offset, int do_bind)
679 {
680 if (!stmt->executed) {
681 return 0;
682 }
683
684 if (!dispatch_param_event(stmt, PDO_PARAM_EVT_FETCH_PRE)) {
685 return 0;
686 }
687
688 if (!stmt->methods->fetcher(stmt, ori, offset)) {
689 return 0;
690 }
691
692
693 if (!stmt->columns && !pdo_stmt_describe_columns(stmt)) {
694 return 0;
695 }
696
697 if (!dispatch_param_event(stmt, PDO_PARAM_EVT_FETCH_POST)) {
698 return 0;
699 }
700
701 if (do_bind && stmt->bound_columns) {
702
703 struct pdo_bound_param_data *param;
704
705 ZEND_HASH_FOREACH_PTR(stmt->bound_columns, param) {
706 if (param->paramno >= 0) {
707 if (!Z_ISREF(param->parameter)) {
708 continue;
709 }
710
711
712 zval_ptr_dtor(Z_REFVAL(param->parameter));
713
714
715 fetch_value(stmt, Z_REFVAL(param->parameter), param->paramno, (int *)¶m->param_type);
716
717
718
719
720
721 }
722 } ZEND_HASH_FOREACH_END();
723 }
724
725 return 1;
726 }
727
728
729 static int do_fetch_class_prepare(pdo_stmt_t *stmt)
730 {
731 zend_class_entry *ce = stmt->fetch.cls.ce;
732 zend_fcall_info *fci = &stmt->fetch.cls.fci;
733 zend_fcall_info_cache *fcc = &stmt->fetch.cls.fcc;
734
735 fci->size = sizeof(zend_fcall_info);
736
737 if (!ce) {
738 stmt->fetch.cls.ce = ZEND_STANDARD_CLASS_DEF_PTR;
739 ce = ZEND_STANDARD_CLASS_DEF_PTR;
740 }
741
742 if (ce->constructor) {
743 fci->function_table = &ce->function_table;
744 ZVAL_UNDEF(&fci->function_name);
745 fci->symbol_table = NULL;
746 fci->retval = &stmt->fetch.cls.retval;
747 fci->param_count = 0;
748 fci->params = NULL;
749 fci->no_separation = 1;
750
751 zend_fcall_info_args_ex(fci, ce->constructor, &stmt->fetch.cls.ctor_args);
752
753 fcc->initialized = 1;
754 fcc->function_handler = ce->constructor;
755 fcc->calling_scope = EG(scope);
756 fcc->called_scope = ce;
757 return 1;
758 } else if (!Z_ISUNDEF(stmt->fetch.cls.ctor_args)) {
759 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "user-supplied class does not have a constructor, use NULL for the ctor_params parameter, or simply omit it");
760 return 0;
761 } else {
762 return 1;
763 }
764 }
765
766
767 static int make_callable_ex(pdo_stmt_t *stmt, zval *callable, zend_fcall_info * fci, zend_fcall_info_cache * fcc, int num_args)
768 {
769 char *is_callable_error = NULL;
770
771 if (zend_fcall_info_init(callable, 0, fci, fcc, NULL, &is_callable_error) == FAILURE) {
772 if (is_callable_error) {
773 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", is_callable_error);
774 efree(is_callable_error);
775 } else {
776 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "user-supplied function must be a valid callback");
777 }
778 return 0;
779 }
780 if (is_callable_error) {
781
782 efree(is_callable_error);
783 }
784
785 fci->param_count = num_args;
786 fci->params = safe_emalloc(sizeof(zval), num_args, 0);
787
788 return 1;
789 }
790
791
792 static int do_fetch_func_prepare(pdo_stmt_t *stmt)
793 {
794 zend_fcall_info *fci = &stmt->fetch.cls.fci;
795 zend_fcall_info_cache *fcc = &stmt->fetch.cls.fcc;
796
797 if (!make_callable_ex(stmt, &stmt->fetch.func.function, fci, fcc, stmt->column_count)) {
798 return 0;
799 } else {
800 stmt->fetch.func.values = safe_emalloc(sizeof(zval), stmt->column_count, 0);
801 return 1;
802 }
803 }
804
805
806 static void do_fetch_opt_finish(pdo_stmt_t *stmt, int free_ctor_agrs)
807 {
808
809 if (stmt->fetch.cls.fci.size && stmt->fetch.cls.fci.params) {
810 if (!Z_ISUNDEF(stmt->fetch.cls.ctor_args)) {
811
812 zend_fcall_info_args_clear(&stmt->fetch.cls.fci, 1);
813 } else {
814 efree(stmt->fetch.cls.fci.params);
815 }
816 stmt->fetch.cls.fci.params = NULL;
817 }
818
819 stmt->fetch.cls.fci.size = 0;
820 if (!Z_ISUNDEF(stmt->fetch.cls.ctor_args) && free_ctor_agrs) {
821 zval_ptr_dtor(&stmt->fetch.cls.ctor_args);
822 ZVAL_UNDEF(&stmt->fetch.cls.ctor_args);
823 stmt->fetch.cls.fci.param_count = 0;
824 }
825 if (stmt->fetch.func.values) {
826 efree(stmt->fetch.func.values);
827 stmt->fetch.func.values = NULL;
828 }
829 }
830
831
832
833
834 static int do_fetch(pdo_stmt_t *stmt, int do_bind, zval *return_value, enum pdo_fetch_type how, enum pdo_fetch_orientation ori, zend_long offset, zval *return_all)
835 {
836 int flags, idx, old_arg_count = 0;
837 zend_class_entry *ce = NULL, *old_ce = NULL;
838 zval grp_val, *pgrp, retval, old_ctor_args;
839 int colno;
840
841 if (how == PDO_FETCH_USE_DEFAULT) {
842 how = stmt->default_fetch_type;
843 }
844 flags = how & PDO_FETCH_FLAGS;
845 how = how & ~PDO_FETCH_FLAGS;
846
847 if (!do_fetch_common(stmt, ori, offset, do_bind)) {
848 return 0;
849 }
850
851 if (how == PDO_FETCH_BOUND) {
852 RETVAL_TRUE;
853 return 1;
854 }
855
856 if (flags & PDO_FETCH_GROUP && stmt->fetch.column == -1) {
857 colno = 1;
858 } else {
859 colno = stmt->fetch.column;
860 }
861
862 if (return_value) {
863 int i = 0;
864
865 if (how == PDO_FETCH_LAZY) {
866 get_lazy_object(stmt, return_value);
867 return 1;
868 }
869
870 RETVAL_FALSE;
871
872 switch (how) {
873 case PDO_FETCH_USE_DEFAULT:
874 case PDO_FETCH_ASSOC:
875 case PDO_FETCH_BOTH:
876 case PDO_FETCH_NUM:
877 case PDO_FETCH_NAMED:
878 if (!return_all) {
879 ZVAL_NEW_ARR(return_value);
880 zend_hash_init(Z_ARRVAL_P(return_value), stmt->column_count, NULL, ZVAL_PTR_DTOR, 0);;
881 } else {
882 array_init(return_value);
883 }
884 break;
885
886 case PDO_FETCH_KEY_PAIR:
887 if (stmt->column_count != 2) {
888 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "PDO::FETCH_KEY_PAIR fetch mode requires the result set to contain extactly 2 columns.");
889 return 0;
890 }
891 if (!return_all) {
892 array_init(return_value);
893 }
894 break;
895
896 case PDO_FETCH_COLUMN:
897 if (colno >= 0 && colno < stmt->column_count) {
898 if (flags == PDO_FETCH_GROUP && stmt->fetch.column == -1) {
899 fetch_value(stmt, return_value, 1, NULL);
900 } else if (flags == PDO_FETCH_GROUP && colno) {
901 fetch_value(stmt, return_value, 0, NULL);
902 } else {
903 fetch_value(stmt, return_value, colno, NULL);
904 }
905 if (!return_all) {
906 return 1;
907 } else {
908 break;
909 }
910 } else {
911 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "Invalid column index");
912 }
913 return 0;
914
915 case PDO_FETCH_OBJ:
916 object_init_ex(return_value, ZEND_STANDARD_CLASS_DEF_PTR);
917 break;
918
919 case PDO_FETCH_CLASS:
920 if (flags & PDO_FETCH_CLASSTYPE) {
921 zval val;
922 zend_class_entry *cep;
923
924 old_ce = stmt->fetch.cls.ce;
925 ZVAL_COPY_VALUE(&old_ctor_args, &stmt->fetch.cls.ctor_args);
926 old_arg_count = stmt->fetch.cls.fci.param_count;
927 do_fetch_opt_finish(stmt, 0);
928
929 fetch_value(stmt, &val, i++, NULL);
930 if (Z_TYPE(val) != IS_NULL) {
931 convert_to_string(&val);
932 if ((cep = zend_lookup_class(Z_STR(val))) == NULL) {
933 stmt->fetch.cls.ce = ZEND_STANDARD_CLASS_DEF_PTR;
934 } else {
935 stmt->fetch.cls.ce = cep;
936 }
937 }
938
939 do_fetch_class_prepare(stmt);
940 zval_dtor(&val);
941 }
942 ce = stmt->fetch.cls.ce;
943 if (!ce) {
944 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "No fetch class specified");
945 return 0;
946 }
947 if ((flags & PDO_FETCH_SERIALIZE) == 0) {
948 if (UNEXPECTED(object_init_ex(return_value, ce) != SUCCESS)) {
949 return 0;
950 }
951 if (!stmt->fetch.cls.fci.size) {
952 if (!do_fetch_class_prepare(stmt))
953 {
954 return 0;
955 }
956 }
957 if (ce->constructor && (flags & PDO_FETCH_PROPS_LATE)) {
958 stmt->fetch.cls.fci.object = Z_OBJ_P(return_value);
959 stmt->fetch.cls.fcc.object = Z_OBJ_P(return_value);
960 if (zend_call_function(&stmt->fetch.cls.fci, &stmt->fetch.cls.fcc) == FAILURE) {
961 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "could not call class constructor");
962 return 0;
963 } else {
964 if (!Z_ISUNDEF(stmt->fetch.cls.retval)) {
965 zval_ptr_dtor(&stmt->fetch.cls.retval);
966 ZVAL_UNDEF(&stmt->fetch.cls.retval);
967 }
968 }
969 }
970 }
971 break;
972
973 case PDO_FETCH_INTO:
974 if (Z_ISUNDEF(stmt->fetch.into)) {
975 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "No fetch-into object specified.");
976 return 0;
977 break;
978 }
979
980 ZVAL_COPY(return_value, &stmt->fetch.into);
981
982 if (Z_OBJ_P(return_value)->ce == ZEND_STANDARD_CLASS_DEF_PTR) {
983 how = PDO_FETCH_OBJ;
984 }
985 break;
986
987 case PDO_FETCH_FUNC:
988 if (Z_ISUNDEF(stmt->fetch.func.function)) {
989 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "No fetch function specified");
990 return 0;
991 }
992 if (!stmt->fetch.func.fci.size) {
993 if (!do_fetch_func_prepare(stmt))
994 {
995 return 0;
996 }
997 }
998 break;
999
1000
1001 default:
1002
1003 return 0;
1004 }
1005
1006 if (return_all && how != PDO_FETCH_KEY_PAIR) {
1007 if (flags == PDO_FETCH_GROUP && how == PDO_FETCH_COLUMN && stmt->fetch.column > 0) {
1008 fetch_value(stmt, &grp_val, colno, NULL);
1009 } else {
1010 fetch_value(stmt, &grp_val, i, NULL);
1011 }
1012 convert_to_string(&grp_val);
1013 if (how == PDO_FETCH_COLUMN) {
1014 i = stmt->column_count;
1015 } else {
1016 i++;
1017 }
1018 }
1019
1020 for (idx = 0; i < stmt->column_count; i++, idx++) {
1021 zval val;
1022 fetch_value(stmt, &val, i, NULL);
1023
1024 switch (how) {
1025 case PDO_FETCH_ASSOC:
1026 zend_symtable_update(Z_ARRVAL_P(return_value), stmt->columns[i].name, &val);
1027 break;
1028
1029 case PDO_FETCH_KEY_PAIR:
1030 {
1031 zval tmp;
1032 fetch_value(stmt, &tmp, ++i, NULL);
1033
1034 if (Z_TYPE(val) == IS_LONG) {
1035 zend_hash_index_update((return_all ? Z_ARRVAL_P(return_all) : Z_ARRVAL_P(return_value)), Z_LVAL(val), &tmp);
1036 } else {
1037 convert_to_string(&val);
1038 zend_symtable_update((return_all ? Z_ARRVAL_P(return_all) : Z_ARRVAL_P(return_value)), Z_STR(val), &tmp);
1039 }
1040 zval_ptr_dtor(&val);
1041 return 1;
1042 }
1043 break;
1044
1045 case PDO_FETCH_USE_DEFAULT:
1046 case PDO_FETCH_BOTH:
1047 zend_symtable_update(Z_ARRVAL_P(return_value), stmt->columns[i].name, &val);
1048 if (Z_REFCOUNTED(val)) {
1049 Z_ADDREF(val);
1050 }
1051 zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &val);
1052 break;
1053
1054 case PDO_FETCH_NAMED:
1055
1056 {
1057 zval *curr_val;
1058 if ((curr_val = zend_hash_find(Z_ARRVAL_P(return_value), stmt->columns[i].name))) {
1059 zval arr;
1060 if (Z_TYPE_P(curr_val) != IS_ARRAY) {
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070 zval cur;
1071
1072 array_init(&arr);
1073
1074 ZVAL_COPY_VALUE(&cur, curr_val);
1075 ZVAL_COPY_VALUE(curr_val, &arr);
1076
1077 zend_hash_next_index_insert_new(Z_ARRVAL(arr), &cur);
1078 } else {
1079 ZVAL_COPY_VALUE(&arr, curr_val);
1080 }
1081 zend_hash_next_index_insert_new(Z_ARRVAL(arr), &val);
1082 } else {
1083 zend_hash_update(Z_ARRVAL_P(return_value), stmt->columns[i].name, &val);
1084 }
1085 }
1086 break;
1087
1088 case PDO_FETCH_NUM:
1089 zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &val);
1090 break;
1091
1092 case PDO_FETCH_OBJ:
1093 case PDO_FETCH_INTO:
1094 zend_update_property_ex(NULL, return_value,
1095 stmt->columns[i].name,
1096 &val);
1097 zval_ptr_dtor(&val);
1098 break;
1099
1100 case PDO_FETCH_CLASS:
1101 if ((flags & PDO_FETCH_SERIALIZE) == 0 || idx) {
1102 zend_update_property_ex(ce, return_value,
1103 stmt->columns[i].name,
1104 &val);
1105 zval_ptr_dtor(&val);
1106 } else {
1107 #ifdef MBO_0
1108 php_unserialize_data_t var_hash;
1109
1110 PHP_VAR_UNSERIALIZE_INIT(var_hash);
1111 if (php_var_unserialize(return_value, (const unsigned char**)&Z_STRVAL(val), Z_STRVAL(val)+Z_STRLEN(val), NULL) == FAILURE) {
1112 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "cannot unserialize data");
1113 PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
1114 return 0;
1115 }
1116 PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
1117 #endif
1118 if (!ce->unserialize) {
1119 zval_ptr_dtor(&val);
1120 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "cannot unserialize class");
1121 return 0;
1122 } else if (ce->unserialize(return_value, ce, (unsigned char *)(Z_TYPE(val) == IS_STRING ? Z_STRVAL(val) : ""), Z_TYPE(val) == IS_STRING ? Z_STRLEN(val) : 0, NULL) == FAILURE) {
1123 zval_ptr_dtor(&val);
1124 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "cannot unserialize class");
1125 zval_dtor(return_value);
1126 ZVAL_NULL(return_value);
1127 return 0;
1128 } else {
1129 zval_ptr_dtor(&val);
1130 }
1131 }
1132 break;
1133
1134 case PDO_FETCH_FUNC:
1135 ZVAL_COPY_VALUE(&stmt->fetch.func.values[idx], &val);
1136 ZVAL_COPY_VALUE(&stmt->fetch.cls.fci.params[idx], &stmt->fetch.func.values[idx]);
1137 break;
1138
1139 default:
1140 zval_ptr_dtor(&val);
1141 pdo_raise_impl_error(stmt->dbh, stmt, "22003", "mode is out of range");
1142 return 0;
1143 break;
1144 }
1145 }
1146
1147 switch (how) {
1148 case PDO_FETCH_CLASS:
1149 if (ce->constructor && !(flags & (PDO_FETCH_PROPS_LATE | PDO_FETCH_SERIALIZE))) {
1150 stmt->fetch.cls.fci.object = Z_OBJ_P(return_value);
1151 stmt->fetch.cls.fcc.object = Z_OBJ_P(return_value);
1152 if (zend_call_function(&stmt->fetch.cls.fci, &stmt->fetch.cls.fcc) == FAILURE) {
1153 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "could not call class constructor");
1154 return 0;
1155 } else {
1156 if (!Z_ISUNDEF(stmt->fetch.cls.retval)) {
1157 zval_ptr_dtor(&stmt->fetch.cls.retval);
1158 }
1159 }
1160 }
1161 if (flags & PDO_FETCH_CLASSTYPE) {
1162 do_fetch_opt_finish(stmt, 0);
1163 stmt->fetch.cls.ce = old_ce;
1164 ZVAL_COPY_VALUE(&stmt->fetch.cls.ctor_args, &old_ctor_args);
1165 stmt->fetch.cls.fci.param_count = old_arg_count;
1166 }
1167 break;
1168
1169 case PDO_FETCH_FUNC:
1170 stmt->fetch.func.fci.param_count = idx;
1171 stmt->fetch.func.fci.retval = &retval;
1172 if (zend_call_function(&stmt->fetch.func.fci, &stmt->fetch.func.fcc) == FAILURE) {
1173 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "could not call user-supplied function");
1174 return 0;
1175 } else {
1176 if (return_all) {
1177 zval_ptr_dtor(return_value);
1178 ZVAL_COPY_VALUE(return_value, &retval);
1179 } else if (!Z_ISUNDEF(retval)) {
1180 ZVAL_COPY_VALUE(return_value, &retval);
1181 }
1182 }
1183 while (idx--) {
1184 zval_ptr_dtor(&stmt->fetch.func.values[idx]);
1185 }
1186 break;
1187
1188 default:
1189 break;
1190 }
1191
1192 if (return_all) {
1193 if ((flags & PDO_FETCH_UNIQUE) == PDO_FETCH_UNIQUE) {
1194 zend_symtable_update(Z_ARRVAL_P(return_all), Z_STR(grp_val), return_value);
1195 } else {
1196 zval grp;
1197 if ((pgrp = zend_symtable_find(Z_ARRVAL_P(return_all), Z_STR(grp_val))) == NULL) {
1198 array_init(&grp);
1199 zend_symtable_update(Z_ARRVAL_P(return_all), Z_STR(grp_val), &grp);
1200 } else {
1201 ZVAL_COPY_VALUE(&grp, pgrp);
1202 }
1203 zend_hash_next_index_insert(Z_ARRVAL(grp), return_value);
1204 }
1205 zval_dtor(&grp_val);
1206 }
1207
1208 }
1209
1210 return 1;
1211 }
1212
1213
1214 static int pdo_stmt_verify_mode(pdo_stmt_t *stmt, zend_long mode, int fetch_all)
1215 {
1216 int flags = mode & PDO_FETCH_FLAGS;
1217
1218 mode = mode & ~PDO_FETCH_FLAGS;
1219
1220 if (mode < 0 || mode > PDO_FETCH__MAX) {
1221 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "invalid fetch mode");
1222 return 0;
1223 }
1224
1225 if (mode == PDO_FETCH_USE_DEFAULT) {
1226 flags = stmt->default_fetch_type & PDO_FETCH_FLAGS;
1227 mode = stmt->default_fetch_type & ~PDO_FETCH_FLAGS;
1228 }
1229
1230 switch(mode) {
1231 case PDO_FETCH_FUNC:
1232 if (!fetch_all) {
1233 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "PDO::FETCH_FUNC is only allowed in PDOStatement::fetchAll()");
1234 return 0;
1235 }
1236 return 1;
1237
1238 case PDO_FETCH_LAZY:
1239 if (fetch_all) {
1240 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "PDO::FETCH_LAZY can't be used with PDOStatement::fetchAll()");
1241 return 0;
1242 }
1243
1244
1245 default:
1246 if ((flags & PDO_FETCH_SERIALIZE) == PDO_FETCH_SERIALIZE) {
1247 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "PDO::FETCH_SERIALIZE can only be used together with PDO::FETCH_CLASS");
1248 return 0;
1249 }
1250 if ((flags & PDO_FETCH_CLASSTYPE) == PDO_FETCH_CLASSTYPE) {
1251 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "PDO::FETCH_CLASSTYPE can only be used together with PDO::FETCH_CLASS");
1252 return 0;
1253 }
1254 if (mode >= PDO_FETCH__MAX) {
1255 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "invalid fetch mode");
1256 return 0;
1257 }
1258
1259
1260 case PDO_FETCH_CLASS:
1261 return 1;
1262 }
1263 }
1264
1265
1266
1267
1268 static PHP_METHOD(PDOStatement, fetch)
1269 {
1270 zend_long how = PDO_FETCH_USE_DEFAULT;
1271 zend_long ori = PDO_FETCH_ORI_NEXT;
1272 zend_long off = 0;
1273 PHP_STMT_GET_OBJ;
1274
1275 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "|lll", &how,
1276 &ori, &off)) {
1277 RETURN_FALSE;
1278 }
1279
1280 PDO_STMT_CLEAR_ERR();
1281
1282 if (!pdo_stmt_verify_mode(stmt, how, 0)) {
1283 RETURN_FALSE;
1284 }
1285
1286 if (!do_fetch(stmt, TRUE, return_value, how, ori, off, 0)) {
1287 PDO_HANDLE_STMT_ERR();
1288 RETURN_FALSE;
1289 }
1290 }
1291
1292
1293
1294
1295 static PHP_METHOD(PDOStatement, fetchObject)
1296 {
1297 zend_long how = PDO_FETCH_CLASS;
1298 zend_long ori = PDO_FETCH_ORI_NEXT;
1299 zend_long off = 0;
1300 zend_string *class_name = NULL;
1301 zend_class_entry *old_ce;
1302 zval old_ctor_args, *ctor_args = NULL;
1303 int error = 0, old_arg_count;
1304
1305 PHP_STMT_GET_OBJ;
1306
1307 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "|S!a", &class_name, &ctor_args)) {
1308 RETURN_FALSE;
1309 }
1310
1311 PDO_STMT_CLEAR_ERR();
1312
1313 if (!pdo_stmt_verify_mode(stmt, how, 0)) {
1314 RETURN_FALSE;
1315 }
1316
1317 old_ce = stmt->fetch.cls.ce;
1318 ZVAL_COPY_VALUE(&old_ctor_args, &stmt->fetch.cls.ctor_args);
1319 old_arg_count = stmt->fetch.cls.fci.param_count;
1320
1321 do_fetch_opt_finish(stmt, 0);
1322
1323 if (ctor_args) {
1324 if (Z_TYPE_P(ctor_args) == IS_ARRAY && zend_hash_num_elements(Z_ARRVAL_P(ctor_args))) {
1325 ZVAL_DUP(&stmt->fetch.cls.ctor_args, ctor_args);
1326 } else {
1327 ZVAL_UNDEF(&stmt->fetch.cls.ctor_args);
1328 }
1329 }
1330 if (class_name && !error) {
1331 stmt->fetch.cls.ce = zend_fetch_class(class_name, ZEND_FETCH_CLASS_AUTO);
1332
1333 if (!stmt->fetch.cls.ce) {
1334 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "Could not find user-supplied class");
1335 error = 1;
1336 }
1337 } else if (!error) {
1338 stmt->fetch.cls.ce = zend_standard_class_def;
1339 }
1340
1341 if (!error && !do_fetch(stmt, TRUE, return_value, how, ori, off, 0)) {
1342 error = 1;
1343 }
1344 if (error) {
1345 PDO_HANDLE_STMT_ERR();
1346 }
1347 do_fetch_opt_finish(stmt, 1);
1348
1349 stmt->fetch.cls.ce = old_ce;
1350 ZVAL_COPY_VALUE(&stmt->fetch.cls.ctor_args, &old_ctor_args);
1351 stmt->fetch.cls.fci.param_count = old_arg_count;
1352 if (error) {
1353 RETURN_FALSE;
1354 }
1355 }
1356
1357
1358
1359
1360 static PHP_METHOD(PDOStatement, fetchColumn)
1361 {
1362 zend_long col_n = 0;
1363 PHP_STMT_GET_OBJ;
1364
1365 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &col_n)) {
1366 RETURN_FALSE;
1367 }
1368
1369 PDO_STMT_CLEAR_ERR();
1370
1371 if (!do_fetch_common(stmt, PDO_FETCH_ORI_NEXT, 0, TRUE)) {
1372 PDO_HANDLE_STMT_ERR();
1373 RETURN_FALSE;
1374 }
1375
1376 fetch_value(stmt, return_value, col_n, NULL);
1377 }
1378
1379
1380
1381
1382 static PHP_METHOD(PDOStatement, fetchAll)
1383 {
1384 zend_long how = PDO_FETCH_USE_DEFAULT;
1385 zval data, *return_all;
1386 zval *arg2;
1387 zend_class_entry *old_ce;
1388 zval old_ctor_args, *ctor_args = NULL;
1389 int error = 0, flags, old_arg_count;
1390 PHP_STMT_GET_OBJ;
1391
1392 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "|lzz", &how, &arg2, &ctor_args)) {
1393 RETURN_FALSE;
1394 }
1395
1396 if (!pdo_stmt_verify_mode(stmt, how, 1)) {
1397 RETURN_FALSE;
1398 }
1399
1400 old_ce = stmt->fetch.cls.ce;
1401 ZVAL_COPY_VALUE(&old_ctor_args, &stmt->fetch.cls.ctor_args);
1402 old_arg_count = stmt->fetch.cls.fci.param_count;
1403
1404 do_fetch_opt_finish(stmt, 0);
1405
1406 switch(how & ~PDO_FETCH_FLAGS) {
1407 case PDO_FETCH_CLASS:
1408 switch(ZEND_NUM_ARGS()) {
1409 case 0:
1410 case 1:
1411 stmt->fetch.cls.ce = zend_standard_class_def;
1412 break;
1413 case 3:
1414 if (Z_TYPE_P(ctor_args) != IS_NULL && Z_TYPE_P(ctor_args) != IS_ARRAY) {
1415 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "ctor_args must be either NULL or an array");
1416 error = 1;
1417 break;
1418 }
1419 if (Z_TYPE_P(ctor_args) != IS_ARRAY || !zend_hash_num_elements(Z_ARRVAL_P(ctor_args))) {
1420 ctor_args = NULL;
1421 }
1422
1423 case 2:
1424 if (ctor_args) {
1425 ZVAL_COPY_VALUE(&stmt->fetch.cls.ctor_args, ctor_args);
1426 } else {
1427 ZVAL_UNDEF(&stmt->fetch.cls.ctor_args);
1428 }
1429 if (Z_TYPE_P(arg2) != IS_STRING) {
1430 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "Invalid class name (should be a string)");
1431 error = 1;
1432 break;
1433 } else {
1434 stmt->fetch.cls.ce = zend_fetch_class(Z_STR_P(arg2), ZEND_FETCH_CLASS_AUTO);
1435 if (!stmt->fetch.cls.ce) {
1436 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "could not find user-specified class");
1437 error = 1;
1438 break;
1439 }
1440 }
1441 }
1442 if (!error) {
1443 do_fetch_class_prepare(stmt);
1444 }
1445 break;
1446
1447 case PDO_FETCH_FUNC:
1448 switch (ZEND_NUM_ARGS()) {
1449 case 0:
1450 case 1:
1451 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "no fetch function specified");
1452 error = 1;
1453 break;
1454 case 3:
1455 case 2:
1456 ZVAL_COPY_VALUE(&stmt->fetch.func.function, arg2);
1457 if (do_fetch_func_prepare(stmt) == 0) {
1458 error = 1;
1459 }
1460 break;
1461 }
1462 break;
1463
1464 case PDO_FETCH_COLUMN:
1465 switch(ZEND_NUM_ARGS()) {
1466 case 0:
1467 case 1:
1468 stmt->fetch.column = how & PDO_FETCH_GROUP ? -1 : 0;
1469 break;
1470 case 2:
1471 convert_to_long(arg2);
1472 stmt->fetch.column = Z_LVAL_P(arg2);
1473 break;
1474 case 3:
1475 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "Third parameter not allowed for PDO::FETCH_COLUMN");
1476 error = 1;
1477 }
1478 break;
1479
1480 default:
1481 if (ZEND_NUM_ARGS() > 1) {
1482 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "Extraneous additional parameters");
1483 error = 1;
1484 }
1485 }
1486
1487 flags = how & PDO_FETCH_FLAGS;
1488
1489 if ((how & ~PDO_FETCH_FLAGS) == PDO_FETCH_USE_DEFAULT) {
1490 flags |= stmt->default_fetch_type & PDO_FETCH_FLAGS;
1491 how |= stmt->default_fetch_type & ~PDO_FETCH_FLAGS;
1492 }
1493
1494 if (!error) {
1495 PDO_STMT_CLEAR_ERR();
1496 if ((how & PDO_FETCH_GROUP) || how == PDO_FETCH_KEY_PAIR ||
1497 (how == PDO_FETCH_USE_DEFAULT && stmt->default_fetch_type == PDO_FETCH_KEY_PAIR)
1498 ) {
1499 array_init(return_value);
1500 return_all = return_value;
1501 } else {
1502 return_all = 0;
1503 }
1504 if (!do_fetch(stmt, 1, &data, how | flags, PDO_FETCH_ORI_NEXT, 0, return_all)) {
1505 error = 2;
1506 }
1507 }
1508 if (!error) {
1509 if ((how & PDO_FETCH_GROUP)) {
1510 while (do_fetch(stmt, 1, &data, how | flags, PDO_FETCH_ORI_NEXT, 0, return_all));
1511 } else if (how == PDO_FETCH_KEY_PAIR || (how == PDO_FETCH_USE_DEFAULT && stmt->default_fetch_type == PDO_FETCH_KEY_PAIR)) {
1512 while (do_fetch(stmt, 1, &data, how | flags, PDO_FETCH_ORI_NEXT, 0, return_all));
1513 } else {
1514 array_init(return_value);
1515 do {
1516 zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &data);
1517 } while (do_fetch(stmt, 1, &data, how | flags, PDO_FETCH_ORI_NEXT, 0, 0));
1518 }
1519 }
1520
1521 do_fetch_opt_finish(stmt, 0);
1522
1523 stmt->fetch.cls.ce = old_ce;
1524 ZVAL_COPY_VALUE(&stmt->fetch.cls.ctor_args, &old_ctor_args);
1525 stmt->fetch.cls.fci.param_count = old_arg_count;
1526
1527 if (error) {
1528 PDO_HANDLE_STMT_ERR();
1529 if (error != 2) {
1530 RETURN_FALSE;
1531 } else {
1532 if (Z_TYPE_P(return_value) != IS_ARRAY) {
1533 array_init(return_value);
1534 }
1535 return;
1536 }
1537 }
1538 }
1539
1540
1541 static int register_bound_param(INTERNAL_FUNCTION_PARAMETERS, pdo_stmt_t *stmt, int is_param)
1542 {
1543 struct pdo_bound_param_data param = {{{0}}};
1544 zend_long param_type = PDO_PARAM_STR;
1545 zval *parameter;
1546
1547 param.paramno = -1;
1548
1549 if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(),
1550 "lz|llz!", ¶m.paramno, ¶meter, ¶m_type, ¶m.max_value_len,
1551 ¶m.driver_params)) {
1552 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "Sz|llz!", ¶m.name,
1553 ¶meter, ¶m_type, ¶m.max_value_len,
1554 ¶m.driver_params)) {
1555 return 0;
1556 }
1557 }
1558
1559 param.param_type = (int) param_type;
1560
1561 if (param.paramno > 0) {
1562 --param.paramno;
1563 } else if (!param.name) {
1564 pdo_raise_impl_error(stmt->dbh, stmt, "HY093", "Columns/Parameters are 1-based");
1565 return 0;
1566 }
1567
1568 ZVAL_COPY(¶m.parameter, parameter);
1569 if (!really_register_bound_param(¶m, stmt, is_param)) {
1570 if (!Z_ISUNDEF(param.parameter)) {
1571 zval_ptr_dtor(&(param.parameter));
1572 }
1573 return 0;
1574 }
1575 return 1;
1576 }
1577
1578
1579
1580 static PHP_METHOD(PDOStatement, bindValue)
1581 {
1582 struct pdo_bound_param_data param = {{{0}}};
1583 zend_long param_type = PDO_PARAM_STR;
1584 zval *parameter;
1585 PHP_STMT_GET_OBJ;
1586
1587 param.paramno = -1;
1588
1589 if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(),
1590 "lz/|l", ¶m.paramno, ¶meter, ¶m_type)) {
1591 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "Sz/|l", ¶m.name,
1592 ¶meter, ¶m_type)) {
1593 RETURN_FALSE;
1594 }
1595 }
1596
1597 param.param_type = (int) param_type;
1598
1599 if (param.paramno > 0) {
1600 --param.paramno;
1601 } else if (!param.name) {
1602 pdo_raise_impl_error(stmt->dbh, stmt, "HY093", "Columns/Parameters are 1-based");
1603 RETURN_FALSE;
1604 }
1605
1606 ZVAL_COPY(¶m.parameter, parameter);
1607 if (!really_register_bound_param(¶m, stmt, TRUE)) {
1608 if (!Z_ISUNDEF(param.parameter)) {
1609 zval_ptr_dtor(&(param.parameter));
1610 ZVAL_UNDEF(¶m.parameter);
1611 }
1612 RETURN_FALSE;
1613 }
1614 RETURN_TRUE;
1615 }
1616
1617
1618
1619
1620 static PHP_METHOD(PDOStatement, bindParam)
1621 {
1622 PHP_STMT_GET_OBJ;
1623 RETURN_BOOL(register_bound_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, stmt, TRUE));
1624 }
1625
1626
1627
1628
1629 static PHP_METHOD(PDOStatement, bindColumn)
1630 {
1631 PHP_STMT_GET_OBJ;
1632 RETURN_BOOL(register_bound_param(INTERNAL_FUNCTION_PARAM_PASSTHRU, stmt, 0));
1633 }
1634
1635
1636
1637
1638 static PHP_METHOD(PDOStatement, rowCount)
1639 {
1640 PHP_STMT_GET_OBJ;
1641
1642 RETURN_LONG(stmt->row_count);
1643 }
1644
1645
1646
1647
1648 static PHP_METHOD(PDOStatement, errorCode)
1649 {
1650 PHP_STMT_GET_OBJ;
1651
1652 if (zend_parse_parameters_none() == FAILURE) {
1653 return;
1654 }
1655
1656 if (stmt->error_code[0] == '\0') {
1657 RETURN_NULL();
1658 }
1659
1660 RETURN_STRING(stmt->error_code);
1661 }
1662
1663
1664
1665
1666 static PHP_METHOD(PDOStatement, errorInfo)
1667 {
1668 int error_count;
1669 int error_count_diff = 0;
1670 int error_expected_count = 3;
1671
1672 PHP_STMT_GET_OBJ;
1673
1674 if (zend_parse_parameters_none() == FAILURE) {
1675 return;
1676 }
1677
1678 array_init(return_value);
1679 add_next_index_string(return_value, stmt->error_code);
1680
1681 if (stmt->dbh->methods->fetch_err) {
1682 stmt->dbh->methods->fetch_err(stmt->dbh, stmt, return_value);
1683 }
1684
1685 error_count = zend_hash_num_elements(Z_ARRVAL_P(return_value));
1686
1687 if (error_expected_count > error_count) {
1688 int current_index;
1689
1690 error_count_diff = error_expected_count - error_count;
1691 for (current_index = 0; current_index < error_count_diff; current_index++) {
1692 add_next_index_null(return_value);
1693 }
1694 }
1695 }
1696
1697
1698
1699
1700 static PHP_METHOD(PDOStatement, setAttribute)
1701 {
1702 zend_long attr;
1703 zval *value = NULL;
1704 PHP_STMT_GET_OBJ;
1705
1706 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "lz!", &attr, &value)) {
1707 RETURN_FALSE;
1708 }
1709
1710 if (!stmt->methods->set_attribute) {
1711 goto fail;
1712 }
1713
1714 PDO_STMT_CLEAR_ERR();
1715 if (stmt->methods->set_attribute(stmt, attr, value)) {
1716 RETURN_TRUE;
1717 }
1718
1719 fail:
1720 if (!stmt->methods->set_attribute) {
1721 pdo_raise_impl_error(stmt->dbh, stmt, "IM001", "This driver doesn't support setting attributes");
1722 } else {
1723 PDO_HANDLE_STMT_ERR();
1724 }
1725 RETURN_FALSE;
1726 }
1727
1728
1729
1730
1731
1732 static int generic_stmt_attr_get(pdo_stmt_t *stmt, zval *return_value, zend_long attr)
1733 {
1734 switch (attr) {
1735 case PDO_ATTR_EMULATE_PREPARES:
1736 RETVAL_BOOL(stmt->supports_placeholders == PDO_PLACEHOLDER_NONE);
1737 return 1;
1738 }
1739 return 0;
1740 }
1741
1742 static PHP_METHOD(PDOStatement, getAttribute)
1743 {
1744 zend_long attr;
1745 PHP_STMT_GET_OBJ;
1746
1747 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "l", &attr)) {
1748 RETURN_FALSE;
1749 }
1750
1751 if (!stmt->methods->get_attribute) {
1752 if (!generic_stmt_attr_get(stmt, return_value, attr)) {
1753 pdo_raise_impl_error(stmt->dbh, stmt, "IM001",
1754 "This driver doesn't support getting attributes");
1755 RETURN_FALSE;
1756 }
1757 return;
1758 }
1759
1760 PDO_STMT_CLEAR_ERR();
1761 switch (stmt->methods->get_attribute(stmt, attr, return_value)) {
1762 case -1:
1763 PDO_HANDLE_STMT_ERR();
1764 RETURN_FALSE;
1765
1766 case 0:
1767 if (!generic_stmt_attr_get(stmt, return_value, attr)) {
1768
1769 pdo_raise_impl_error(stmt->dbh, stmt, "IM001",
1770 "driver doesn't support getting that attribute");
1771 RETURN_FALSE;
1772 }
1773 return;
1774
1775 default:
1776 return;
1777 }
1778 }
1779
1780
1781
1782
1783 static PHP_METHOD(PDOStatement, columnCount)
1784 {
1785 PHP_STMT_GET_OBJ;
1786 if (zend_parse_parameters_none() == FAILURE) {
1787 return;
1788 }
1789 RETURN_LONG(stmt->column_count);
1790 }
1791
1792
1793
1794
1795 static PHP_METHOD(PDOStatement, getColumnMeta)
1796 {
1797 zend_long colno;
1798 struct pdo_column_data *col;
1799 PHP_STMT_GET_OBJ;
1800
1801 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "l", &colno)) {
1802 RETURN_FALSE;
1803 }
1804 if(colno < 0) {
1805 pdo_raise_impl_error(stmt->dbh, stmt, "42P10", "column number must be non-negative");
1806 RETURN_FALSE;
1807 }
1808
1809 if (!stmt->methods->get_column_meta) {
1810 pdo_raise_impl_error(stmt->dbh, stmt, "IM001", "driver doesn't support meta data");
1811 RETURN_FALSE;
1812 }
1813
1814 PDO_STMT_CLEAR_ERR();
1815 if (FAILURE == stmt->methods->get_column_meta(stmt, colno, return_value)) {
1816 PDO_HANDLE_STMT_ERR();
1817 RETURN_FALSE;
1818 }
1819
1820
1821 col = &stmt->columns[colno];
1822 add_assoc_str(return_value, "name", zend_string_copy(col->name));
1823 add_assoc_long(return_value, "len", col->maxlen);
1824 add_assoc_long(return_value, "precision", col->precision);
1825 if (col->param_type != PDO_PARAM_ZVAL) {
1826
1827 add_assoc_long(return_value, "pdo_type", col->param_type);
1828 }
1829 }
1830
1831
1832
1833
1834
1835 int pdo_stmt_setup_fetch_mode(INTERNAL_FUNCTION_PARAMETERS, pdo_stmt_t *stmt, int skip)
1836 {
1837 zend_long mode = PDO_FETCH_BOTH;
1838 int flags = 0, argc = ZEND_NUM_ARGS() - skip;
1839 zval *args;
1840 zend_class_entry *cep;
1841 int retval;
1842
1843 do_fetch_opt_finish(stmt, 1);
1844
1845 switch (stmt->default_fetch_type) {
1846 case PDO_FETCH_INTO:
1847 if (!Z_ISUNDEF(stmt->fetch.into)) {
1848 zval_ptr_dtor(&stmt->fetch.into);
1849 ZVAL_UNDEF(&stmt->fetch.into);
1850 }
1851 break;
1852 default:
1853 ;
1854 }
1855
1856 stmt->default_fetch_type = PDO_FETCH_BOTH;
1857
1858 if (argc == 0) {
1859 return SUCCESS;
1860 }
1861
1862 args = safe_emalloc(ZEND_NUM_ARGS(), sizeof(zval), 0);
1863
1864 retval = zend_get_parameters_array_ex(ZEND_NUM_ARGS(), args);
1865
1866 if (SUCCESS == retval) {
1867 if (Z_TYPE(args[skip]) != IS_LONG) {
1868 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "mode must be an integer");
1869 retval = FAILURE;
1870 } else {
1871 mode = Z_LVAL(args[skip]);
1872 flags = mode & PDO_FETCH_FLAGS;
1873
1874 retval = pdo_stmt_verify_mode(stmt, mode, 0);
1875 }
1876 }
1877
1878 if (FAILURE == retval) {
1879 PDO_STMT_CLEAR_ERR();
1880 efree(args);
1881 return FAILURE;
1882 }
1883
1884 retval = FAILURE;
1885 switch (mode & ~PDO_FETCH_FLAGS) {
1886 case PDO_FETCH_USE_DEFAULT:
1887 case PDO_FETCH_LAZY:
1888 case PDO_FETCH_ASSOC:
1889 case PDO_FETCH_NUM:
1890 case PDO_FETCH_BOTH:
1891 case PDO_FETCH_OBJ:
1892 case PDO_FETCH_BOUND:
1893 case PDO_FETCH_NAMED:
1894 case PDO_FETCH_KEY_PAIR:
1895 if (argc != 1) {
1896 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "fetch mode doesn't allow any extra arguments");
1897 } else {
1898 retval = SUCCESS;
1899 }
1900 break;
1901
1902 case PDO_FETCH_COLUMN:
1903 if (argc != 2) {
1904 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "fetch mode requires the colno argument");
1905 } else if (Z_TYPE(args[skip+1]) != IS_LONG) {
1906 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "colno must be an integer");
1907 } else {
1908 stmt->fetch.column = Z_LVAL(args[skip+1]);
1909 retval = SUCCESS;
1910 }
1911 break;
1912
1913 case PDO_FETCH_CLASS:
1914
1915 if ((flags & PDO_FETCH_CLASSTYPE) == PDO_FETCH_CLASSTYPE) {
1916 if (argc != 1) {
1917 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "fetch mode doesn't allow any extra arguments");
1918 } else {
1919 stmt->fetch.cls.ce = NULL;
1920 retval = SUCCESS;
1921 }
1922 } else {
1923 if (argc < 2) {
1924 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "fetch mode requires the classname argument");
1925 } else if (argc > 3) {
1926 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "too many arguments");
1927 } else if (Z_TYPE(args[skip+1]) != IS_STRING) {
1928 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "classname must be a string");
1929 } else {
1930 cep = zend_lookup_class(Z_STR(args[skip+1]));
1931 if (cep) {
1932 retval = SUCCESS;
1933 stmt->fetch.cls.ce = cep;
1934 }
1935 }
1936 }
1937
1938 if (SUCCESS == retval) {
1939 ZVAL_UNDEF(&stmt->fetch.cls.ctor_args);
1940 #ifdef ilia_0
1941 if (stmt->dbh->is_persistent) {
1942 php_error_docref(NULL, E_WARNING, "PHP might crash if you don't call $stmt->setFetchMode() to reset to defaults on this persistent statement. This will be fixed in a later release");
1943 }
1944 #endif
1945 if (argc == 3) {
1946 if (Z_TYPE(args[skip+2]) != IS_NULL && Z_TYPE(args[skip+2]) != IS_ARRAY) {
1947 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "ctor_args must be either NULL or an array");
1948 retval = FAILURE;
1949 } else if (Z_TYPE(args[skip+2]) == IS_ARRAY && zend_hash_num_elements(Z_ARRVAL(args[skip+2]))) {
1950 ZVAL_DUP(&stmt->fetch.cls.ctor_args, &args[skip+2]);
1951 }
1952 }
1953
1954 if (SUCCESS == retval) {
1955 do_fetch_class_prepare(stmt);
1956 }
1957 }
1958
1959 break;
1960
1961 case PDO_FETCH_INTO:
1962 if (argc != 2) {
1963 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "fetch mode requires the object parameter");
1964 } else if (Z_TYPE(args[skip+1]) != IS_OBJECT) {
1965 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "object must be an object");
1966 } else {
1967 retval = SUCCESS;
1968 }
1969
1970 if (SUCCESS == retval) {
1971 #ifdef ilia_0
1972 if (stmt->dbh->is_persistent) {
1973 php_error_docref(NULL, E_WARNING, "PHP might crash if you don't call $stmt->setFetchMode() to reset to defaults on this persistent statement. This will be fixed in a later release");
1974 }
1975 #endif
1976 ZVAL_COPY(&stmt->fetch.into, &args[skip+1]);
1977 }
1978
1979 break;
1980
1981 default:
1982 pdo_raise_impl_error(stmt->dbh, stmt, "22003", "Invalid fetch mode specified");
1983 }
1984
1985 if (SUCCESS == retval) {
1986 stmt->default_fetch_type = mode;
1987 }
1988
1989
1990
1991
1992
1993
1994
1995
1996 PDO_STMT_CLEAR_ERR();
1997
1998 efree(args);
1999
2000 return retval;
2001 }
2002
2003 static PHP_METHOD(PDOStatement, setFetchMode)
2004 {
2005 PHP_STMT_GET_OBJ;
2006
2007 RETVAL_BOOL(
2008 pdo_stmt_setup_fetch_mode(INTERNAL_FUNCTION_PARAM_PASSTHRU,
2009 stmt, 0) == SUCCESS ? 1 : 0
2010 );
2011 }
2012
2013
2014
2015
2016
2017 static int pdo_stmt_do_next_rowset(pdo_stmt_t *stmt)
2018 {
2019
2020 if (stmt->columns) {
2021 int i;
2022 struct pdo_column_data *cols = stmt->columns;
2023
2024 for (i = 0; i < stmt->column_count; i++) {
2025 zend_string_release(cols[i].name);
2026 }
2027 efree(stmt->columns);
2028 stmt->columns = NULL;
2029 stmt->column_count = 0;
2030 }
2031
2032 if (!stmt->methods->next_rowset(stmt)) {
2033
2034 stmt->executed = 0;
2035 return 0;
2036 }
2037
2038 pdo_stmt_describe_columns(stmt);
2039
2040 return 1;
2041 }
2042
2043 static PHP_METHOD(PDOStatement, nextRowset)
2044 {
2045 PHP_STMT_GET_OBJ;
2046
2047 if (!stmt->methods->next_rowset) {
2048 pdo_raise_impl_error(stmt->dbh, stmt, "IM001", "driver does not support multiple rowsets");
2049 RETURN_FALSE;
2050 }
2051
2052 PDO_STMT_CLEAR_ERR();
2053
2054 if (!pdo_stmt_do_next_rowset(stmt)) {
2055 PDO_HANDLE_STMT_ERR();
2056 RETURN_FALSE;
2057 }
2058
2059 RETURN_TRUE;
2060 }
2061
2062
2063
2064
2065 static PHP_METHOD(PDOStatement, closeCursor)
2066 {
2067 PHP_STMT_GET_OBJ;
2068
2069 if (!stmt->methods->cursor_closer) {
2070
2071 do {
2072 while (stmt->methods->fetcher(stmt, PDO_FETCH_ORI_NEXT, 0))
2073 ;
2074 if (!stmt->methods->next_rowset) {
2075 break;
2076 }
2077
2078 if (!pdo_stmt_do_next_rowset(stmt)) {
2079 break;
2080 }
2081
2082 } while (1);
2083 stmt->executed = 0;
2084 RETURN_TRUE;
2085 }
2086
2087 PDO_STMT_CLEAR_ERR();
2088
2089 if (!stmt->methods->cursor_closer(stmt)) {
2090 PDO_HANDLE_STMT_ERR();
2091 RETURN_FALSE;
2092 }
2093 stmt->executed = 0;
2094 RETURN_TRUE;
2095 }
2096
2097
2098
2099
2100 static PHP_METHOD(PDOStatement, debugDumpParams)
2101 {
2102 php_stream *out = php_stream_open_wrapper("php://output", "w", 0, NULL);
2103 struct pdo_bound_param_data *param;
2104 PHP_STMT_GET_OBJ;
2105
2106 if (out == NULL) {
2107 RETURN_FALSE;
2108 }
2109
2110 php_stream_printf(out, "SQL: [%zd] %.*s\n",
2111 stmt->query_stringlen,
2112 (int) stmt->query_stringlen, stmt->query_string);
2113
2114 php_stream_printf(out, "Params: %d\n",
2115 stmt->bound_params ? zend_hash_num_elements(stmt->bound_params) : 0);
2116
2117 if (stmt->bound_params) {
2118 zend_ulong num;
2119 zend_string *key = NULL;
2120 ZEND_HASH_FOREACH_KEY_PTR(stmt->bound_params, num, key, param) {
2121 if (key) {
2122 php_stream_printf(out, "Key: Name: [%zd] %.*s\n",
2123 ZSTR_LEN(key), (int) ZSTR_LEN(key), ZSTR_VAL(key));
2124 } else {
2125 php_stream_printf(out, "Key: Position #%pd:\n", num);
2126 }
2127
2128 php_stream_printf(out, "paramno=%pd\nname=[%zd] \"%.*s\"\nis_param=%d\nparam_type=%d\n",
2129 param->paramno, param->name ? ZSTR_LEN(param->name) : 0, param->name ? (int) ZSTR_LEN(param->name) : 0,
2130 param->name ? ZSTR_VAL(param->name) : "",
2131 param->is_param,
2132 param->param_type);
2133
2134 } ZEND_HASH_FOREACH_END();
2135 }
2136
2137 php_stream_close(out);
2138 }
2139
2140
2141
2142
2143 static PHP_METHOD(PDOStatement, __wakeup)
2144 {
2145 zend_throw_exception_ex(php_pdo_get_exception(), 0, "You cannot serialize or unserialize PDOStatement instances");
2146 }
2147
2148
2149
2150
2151 static PHP_METHOD(PDOStatement, __sleep)
2152 {
2153 zend_throw_exception_ex(php_pdo_get_exception(), 0, "You cannot serialize or unserialize PDOStatement instances");
2154 }
2155
2156
2157 const zend_function_entry pdo_dbstmt_functions[] = {
2158 PHP_ME(PDOStatement, execute, arginfo_pdostatement_execute, ZEND_ACC_PUBLIC)
2159 PHP_ME(PDOStatement, fetch, arginfo_pdostatement_fetch, ZEND_ACC_PUBLIC)
2160 PHP_ME(PDOStatement, bindParam, arginfo_pdostatement_bindparam, ZEND_ACC_PUBLIC)
2161 PHP_ME(PDOStatement, bindColumn, arginfo_pdostatement_bindcolumn, ZEND_ACC_PUBLIC)
2162 PHP_ME(PDOStatement, bindValue, arginfo_pdostatement_bindvalue, ZEND_ACC_PUBLIC)
2163 PHP_ME(PDOStatement, rowCount, arginfo_pdostatement__void, ZEND_ACC_PUBLIC)
2164 PHP_ME(PDOStatement, fetchColumn, arginfo_pdostatement_fetchcolumn, ZEND_ACC_PUBLIC)
2165 PHP_ME(PDOStatement, fetchAll, arginfo_pdostatement_fetchall, ZEND_ACC_PUBLIC)
2166 PHP_ME(PDOStatement, fetchObject, arginfo_pdostatement_fetchobject, ZEND_ACC_PUBLIC)
2167 PHP_ME(PDOStatement, errorCode, arginfo_pdostatement__void, ZEND_ACC_PUBLIC)
2168 PHP_ME(PDOStatement, errorInfo, arginfo_pdostatement__void, ZEND_ACC_PUBLIC)
2169 PHP_ME(PDOStatement, setAttribute, arginfo_pdostatement_setattribute, ZEND_ACC_PUBLIC)
2170 PHP_ME(PDOStatement, getAttribute, arginfo_pdostatement_getattribute, ZEND_ACC_PUBLIC)
2171 PHP_ME(PDOStatement, columnCount, arginfo_pdostatement__void, ZEND_ACC_PUBLIC)
2172 PHP_ME(PDOStatement, getColumnMeta, arginfo_pdostatement_getcolumnmeta, ZEND_ACC_PUBLIC)
2173 PHP_ME(PDOStatement, setFetchMode, arginfo_pdostatement_setfetchmode, ZEND_ACC_PUBLIC)
2174 PHP_ME(PDOStatement, nextRowset, arginfo_pdostatement__void, ZEND_ACC_PUBLIC)
2175 PHP_ME(PDOStatement, closeCursor, arginfo_pdostatement__void, ZEND_ACC_PUBLIC)
2176 PHP_ME(PDOStatement, debugDumpParams, arginfo_pdostatement__void, ZEND_ACC_PUBLIC)
2177 PHP_ME(PDOStatement, __wakeup, arginfo_pdostatement__void, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
2178 PHP_ME(PDOStatement, __sleep, arginfo_pdostatement__void, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
2179 {NULL, NULL, NULL}
2180 };
2181
2182
2183 static void dbstmt_prop_write(zval *object, zval *member, zval *value, void **cache_slot)
2184 {
2185 pdo_stmt_t *stmt = Z_PDO_STMT_P(object);
2186
2187 convert_to_string(member);
2188
2189 if (strcmp(Z_STRVAL_P(member), "queryString") == 0) {
2190 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "property queryString is read only");
2191 } else {
2192 std_object_handlers.write_property(object, member, value, cache_slot);
2193 }
2194 }
2195
2196 static void dbstmt_prop_delete(zval *object, zval *member, void **cache_slot)
2197 {
2198 pdo_stmt_t *stmt = Z_PDO_STMT_P(object);
2199
2200 convert_to_string(member);
2201
2202 if (strcmp(Z_STRVAL_P(member), "queryString") == 0) {
2203 pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "property queryString is read only");
2204 } else {
2205 std_object_handlers.unset_property(object, member, cache_slot);
2206 }
2207 }
2208
2209 static union _zend_function *dbstmt_method_get(zend_object **object_pp, zend_string *method_name, const zval *key)
2210 {
2211 zend_function *fbc = NULL;
2212 zend_string *lc_method_name;
2213 zend_object *object = *object_pp;
2214
2215 lc_method_name = zend_string_alloc(ZSTR_LEN(method_name), 0);
2216 zend_str_tolower_copy(ZSTR_VAL(lc_method_name), ZSTR_VAL(method_name), ZSTR_LEN(method_name));
2217
2218 if ((fbc = zend_hash_find_ptr(&object->ce->function_table, lc_method_name)) == NULL) {
2219 pdo_stmt_t *stmt = php_pdo_stmt_fetch_object(object);
2220
2221 if (!stmt->dbh) {
2222 goto out;
2223 }
2224
2225
2226 if (!stmt->dbh->cls_methods[PDO_DBH_DRIVER_METHOD_KIND_STMT]) {
2227 if (!pdo_hash_methods(Z_PDO_OBJECT_P(&stmt->database_object_handle),
2228 PDO_DBH_DRIVER_METHOD_KIND_STMT)
2229 || !stmt->dbh->cls_methods[PDO_DBH_DRIVER_METHOD_KIND_STMT]) {
2230 goto out;
2231 }
2232 }
2233
2234 if ((fbc = zend_hash_find_ptr(stmt->dbh->cls_methods[PDO_DBH_DRIVER_METHOD_KIND_STMT], lc_method_name)) == NULL) {
2235 goto out;
2236 }
2237
2238 }
2239
2240 out:
2241 zend_string_release(lc_method_name);
2242 return fbc;
2243 }
2244
2245 static int dbstmt_compare(zval *object1, zval *object2)
2246 {
2247 return -1;
2248 }
2249
2250 static zend_object *dbstmt_clone_obj(zval *zobject)
2251 {
2252 pdo_stmt_t *stmt;
2253 pdo_stmt_t *old_stmt;
2254
2255 stmt = ecalloc(1, sizeof(pdo_stmt_t) + zend_object_properties_size(Z_OBJCE_P(zobject)));
2256 zend_object_std_init(&stmt->std, Z_OBJCE_P(zobject));
2257 object_properties_init(&stmt->std, Z_OBJCE_P(zobject));
2258
2259 old_stmt = Z_PDO_STMT_P(zobject);
2260
2261 zend_objects_clone_members(&stmt->std, &old_stmt->std);
2262
2263 return &stmt->std;
2264 }
2265
2266 zend_object_handlers pdo_dbstmt_object_handlers;
2267 static int pdo_row_serialize(zval *object, unsigned char **buffer, size_t *buf_len, zend_serialize_data *data);
2268
2269 void pdo_stmt_init(void)
2270 {
2271 zend_class_entry ce;
2272
2273 INIT_CLASS_ENTRY(ce, "PDOStatement", pdo_dbstmt_functions);
2274 pdo_dbstmt_ce = zend_register_internal_class(&ce);
2275 pdo_dbstmt_ce->get_iterator = pdo_stmt_iter_get;
2276 pdo_dbstmt_ce->create_object = pdo_dbstmt_new;
2277 zend_class_implements(pdo_dbstmt_ce, 1, zend_ce_traversable);
2278 zend_declare_property_null(pdo_dbstmt_ce, "queryString", sizeof("queryString")-1, ZEND_ACC_PUBLIC);
2279
2280 memcpy(&pdo_dbstmt_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
2281 pdo_dbstmt_object_handlers.offset = XtOffsetOf(pdo_stmt_t, std);
2282 pdo_dbstmt_object_handlers.dtor_obj = zend_objects_destroy_object;
2283 pdo_dbstmt_object_handlers.free_obj = pdo_dbstmt_free_storage;
2284 pdo_dbstmt_object_handlers.write_property = dbstmt_prop_write;
2285 pdo_dbstmt_object_handlers.unset_property = dbstmt_prop_delete;
2286 pdo_dbstmt_object_handlers.get_method = dbstmt_method_get;
2287 pdo_dbstmt_object_handlers.compare_objects = dbstmt_compare;
2288 pdo_dbstmt_object_handlers.clone_obj = dbstmt_clone_obj;
2289
2290 INIT_CLASS_ENTRY(ce, "PDORow", pdo_row_functions);
2291 pdo_row_ce = zend_register_internal_class(&ce);
2292 pdo_row_ce->ce_flags |= ZEND_ACC_FINAL;
2293 pdo_row_ce->create_object = pdo_row_new;
2294 pdo_row_ce->serialize = pdo_row_serialize;
2295 }
2296
2297 PDO_API void php_pdo_free_statement(pdo_stmt_t *stmt)
2298 {
2299 if (stmt->bound_params) {
2300 zend_hash_destroy(stmt->bound_params);
2301 FREE_HASHTABLE(stmt->bound_params);
2302 stmt->bound_params = NULL;
2303 }
2304 if (stmt->bound_param_map) {
2305 zend_hash_destroy(stmt->bound_param_map);
2306 FREE_HASHTABLE(stmt->bound_param_map);
2307 stmt->bound_param_map = NULL;
2308 }
2309 if (stmt->bound_columns) {
2310 zend_hash_destroy(stmt->bound_columns);
2311 FREE_HASHTABLE(stmt->bound_columns);
2312 stmt->bound_columns = NULL;
2313 }
2314
2315 if (stmt->methods && stmt->methods->dtor) {
2316 stmt->methods->dtor(stmt);
2317 }
2318 if (stmt->query_string) {
2319 efree(stmt->query_string);
2320 }
2321
2322 if (stmt->columns) {
2323 int i;
2324 struct pdo_column_data *cols = stmt->columns;
2325
2326 for (i = 0; i < stmt->column_count; i++) {
2327 if (cols[i].name) {
2328 zend_string_release(cols[i].name);
2329 cols[i].name = NULL;
2330 }
2331 }
2332 efree(stmt->columns);
2333 stmt->columns = NULL;
2334 }
2335
2336 if (!Z_ISUNDEF(stmt->fetch.into) && stmt->default_fetch_type == PDO_FETCH_INTO) {
2337 zval_ptr_dtor(&stmt->fetch.into);
2338 ZVAL_UNDEF(&stmt->fetch.into);
2339 }
2340
2341 do_fetch_opt_finish(stmt, 1);
2342
2343 if (!Z_ISUNDEF(stmt->database_object_handle)) {
2344 zval_ptr_dtor(&stmt->database_object_handle);
2345 }
2346 zend_object_std_dtor(&stmt->std);
2347 }
2348
2349 void pdo_dbstmt_free_storage(zend_object *std)
2350 {
2351 pdo_stmt_t *stmt = php_pdo_stmt_fetch_object(std);
2352 php_pdo_free_statement(stmt);
2353 }
2354
2355 zend_object *pdo_dbstmt_new(zend_class_entry *ce)
2356 {
2357 pdo_stmt_t *stmt;
2358
2359 stmt = ecalloc(1, sizeof(pdo_stmt_t) + zend_object_properties_size(ce));
2360 zend_object_std_init(&stmt->std, ce);
2361 object_properties_init(&stmt->std, ce);
2362
2363 stmt->std.handlers = &pdo_dbstmt_object_handlers;
2364
2365 return &stmt->std;
2366 }
2367
2368
2369
2370
2371 struct php_pdo_iterator {
2372 zend_object_iterator iter;
2373 zend_ulong key;
2374 zval fetch_ahead;
2375 };
2376
2377 static void pdo_stmt_iter_dtor(zend_object_iterator *iter)
2378 {
2379 struct php_pdo_iterator *I = (struct php_pdo_iterator*)iter;
2380
2381 zval_ptr_dtor(&I->iter.data);
2382
2383 if (!Z_ISUNDEF(I->fetch_ahead)) {
2384 zval_ptr_dtor(&I->fetch_ahead);
2385 }
2386 }
2387
2388 static int pdo_stmt_iter_valid(zend_object_iterator *iter)
2389 {
2390 struct php_pdo_iterator *I = (struct php_pdo_iterator*)iter;
2391
2392 return Z_ISUNDEF(I->fetch_ahead) ? FAILURE : SUCCESS;
2393 }
2394
2395 static zval *pdo_stmt_iter_get_data(zend_object_iterator *iter)
2396 {
2397 struct php_pdo_iterator *I = (struct php_pdo_iterator*)iter;
2398
2399
2400 if (Z_ISUNDEF(I->fetch_ahead)) {
2401 return NULL;
2402 }
2403
2404 return &I->fetch_ahead;
2405 }
2406
2407 static void pdo_stmt_iter_get_key(zend_object_iterator *iter, zval *key)
2408 {
2409 struct php_pdo_iterator *I = (struct php_pdo_iterator*)iter;
2410
2411 if (I->key == (ulong)-1) {
2412 ZVAL_NULL(key);
2413 } else {
2414 ZVAL_LONG(key, I->key);
2415 }
2416 }
2417
2418 static void pdo_stmt_iter_move_forwards(zend_object_iterator *iter)
2419 {
2420 struct php_pdo_iterator *I = (struct php_pdo_iterator*)iter;
2421 pdo_stmt_t *stmt = Z_PDO_STMT_P(&I->iter.data);
2422
2423 if (!Z_ISUNDEF(I->fetch_ahead)) {
2424 zval_ptr_dtor(&I->fetch_ahead);
2425 }
2426
2427 if (!do_fetch(stmt, TRUE, &I->fetch_ahead, PDO_FETCH_USE_DEFAULT,
2428 PDO_FETCH_ORI_NEXT, 0, 0)) {
2429
2430 PDO_HANDLE_STMT_ERR();
2431 I->key = (ulong)-1;
2432 ZVAL_UNDEF(&I->fetch_ahead);
2433
2434 return;
2435 }
2436
2437 I->key++;
2438 }
2439
2440 static zend_object_iterator_funcs pdo_stmt_iter_funcs = {
2441 pdo_stmt_iter_dtor,
2442 pdo_stmt_iter_valid,
2443 pdo_stmt_iter_get_data,
2444 pdo_stmt_iter_get_key,
2445 pdo_stmt_iter_move_forwards,
2446 NULL
2447 };
2448
2449 zend_object_iterator *pdo_stmt_iter_get(zend_class_entry *ce, zval *object, int by_ref)
2450 {
2451 pdo_stmt_t *stmt = Z_PDO_STMT_P(object);
2452 struct php_pdo_iterator *I;
2453
2454 if (by_ref) {
2455 zend_error(E_ERROR, "An iterator cannot be used with foreach by reference");
2456 }
2457
2458 I = ecalloc(1, sizeof(struct php_pdo_iterator));
2459 zend_iterator_init(&I->iter);
2460 I->iter.funcs = &pdo_stmt_iter_funcs;
2461 ZVAL_COPY(&I->iter.data, object);
2462
2463 if (!do_fetch(stmt, 1, &I->fetch_ahead, PDO_FETCH_USE_DEFAULT,
2464 PDO_FETCH_ORI_NEXT, 0, 0)) {
2465 PDO_HANDLE_STMT_ERR();
2466 I->key = (ulong)-1;
2467 ZVAL_UNDEF(&I->fetch_ahead);
2468 }
2469
2470 return &I->iter;
2471 }
2472
2473
2474
2475
2476
2477 const zend_function_entry pdo_row_functions[] = {
2478 {NULL, NULL, NULL}
2479 };
2480
2481 static zval *row_prop_read(zval *object, zval *member, int type, void **cache_slot, zval *rv)
2482 {
2483 pdo_row_t *row = (pdo_row_t *)Z_OBJ_P(object);
2484 pdo_stmt_t *stmt = row->stmt;
2485 int colno = -1;
2486 zval zobj;
2487 zend_long lval;
2488
2489 ZVAL_NULL(rv);
2490 if (stmt) {
2491 if (Z_TYPE_P(member) == IS_LONG) {
2492 if (Z_LVAL_P(member) >= 0 && Z_LVAL_P(member) < stmt->column_count) {
2493 fetch_value(stmt, rv, Z_LVAL_P(member), NULL);
2494 }
2495 } else if (Z_TYPE_P(member) == IS_STRING
2496 && is_numeric_string_ex(Z_STRVAL_P(member), Z_STRLEN_P(member), &lval, NULL, 0, NULL) == IS_LONG) {
2497 if (lval >= 0 && lval < stmt->column_count) {
2498 fetch_value(stmt, rv, lval, NULL);
2499 }
2500 } else {
2501 convert_to_string(member);
2502
2503
2504 for (colno = 0; colno < stmt->column_count; colno++) {
2505 if (ZSTR_LEN(stmt->columns[colno].name) == Z_STRLEN_P(member) &&
2506 strncmp(ZSTR_VAL(stmt->columns[colno].name), Z_STRVAL_P(member), Z_STRLEN_P(member)) == 0) {
2507 fetch_value(stmt, rv, colno, NULL);
2508 return rv;
2509 }
2510 }
2511 if (strcmp(Z_STRVAL_P(member), "queryString") == 0) {
2512 ZVAL_OBJ(&zobj, &stmt->std);
2513
2514 return std_object_handlers.read_property(&zobj, member, type, cache_slot, rv);
2515 }
2516 }
2517 }
2518
2519 return rv;
2520 }
2521
2522 static zval *row_dim_read(zval *object, zval *member, int type, zval *rv)
2523 {
2524 return row_prop_read(object, member, type, NULL, rv);
2525 }
2526
2527 static void row_prop_write(zval *object, zval *member, zval *value, void **cache_slot)
2528 {
2529 php_error_docref(NULL, E_WARNING, "This PDORow is not from a writable result set");
2530 }
2531
2532 static void row_dim_write(zval *object, zval *member, zval *value)
2533 {
2534 php_error_docref(NULL, E_WARNING, "This PDORow is not from a writable result set");
2535 }
2536
2537 static int row_prop_exists(zval *object, zval *member, int check_empty, void **cache_slot)
2538 {
2539 pdo_row_t *row = (pdo_row_t *)Z_OBJ_P(object);
2540 pdo_stmt_t *stmt = row->stmt;
2541 int colno = -1;
2542 zend_long lval;
2543
2544 if (stmt) {
2545 if (Z_TYPE_P(member) == IS_LONG) {
2546 return Z_LVAL_P(member) >= 0 && Z_LVAL_P(member) < stmt->column_count;
2547 } else if (Z_TYPE_P(member) == IS_STRING) {
2548 if (is_numeric_string_ex(Z_STRVAL_P(member), Z_STRLEN_P(member), &lval, NULL, 0, NULL) == IS_LONG) {
2549 return lval >=0 && lval < stmt->column_count;
2550 }
2551 } else {
2552 convert_to_string(member);
2553 }
2554
2555
2556
2557 for (colno = 0; colno < stmt->column_count; colno++) {
2558 if (ZSTR_LEN(stmt->columns[colno].name) == Z_STRLEN_P(member) &&
2559 strncmp(ZSTR_VAL(stmt->columns[colno].name), Z_STRVAL_P(member), Z_STRLEN_P(member)) == 0) {
2560 return 1;
2561 }
2562 }
2563 }
2564
2565 return 0;
2566 }
2567
2568 static int row_dim_exists(zval *object, zval *member, int check_empty)
2569 {
2570 return row_prop_exists(object, member, check_empty, NULL);
2571 }
2572
2573 static void row_prop_delete(zval *object, zval *offset, void **cache_slot)
2574 {
2575 php_error_docref(NULL, E_WARNING, "Cannot delete properties from a PDORow");
2576 }
2577
2578 static void row_dim_delete(zval *object, zval *offset)
2579 {
2580 php_error_docref(NULL, E_WARNING, "Cannot delete properties from a PDORow");
2581 }
2582
2583 static HashTable *row_get_properties(zval *object)
2584 {
2585 pdo_row_t *row = (pdo_row_t *)Z_OBJ_P(object);
2586 pdo_stmt_t *stmt = row->stmt;
2587 int i;
2588
2589 if (stmt == NULL) {
2590 return NULL;
2591 }
2592
2593 if (!stmt->std.properties) {
2594 rebuild_object_properties(&stmt->std);
2595 }
2596 for (i = 0; i < stmt->column_count; i++) {
2597 zval val;
2598 fetch_value(stmt, &val, i, NULL);
2599
2600 zend_hash_update(stmt->std.properties, stmt->columns[i].name, &val);
2601 }
2602
2603 return stmt->std.properties;
2604 }
2605
2606 static union _zend_function *row_method_get(
2607 zend_object **object_pp,
2608 zend_string *method_name, const zval *key)
2609 {
2610 zend_function *fbc;
2611 zend_string *lc_method_name;
2612
2613 lc_method_name = zend_string_alloc(ZSTR_LEN(method_name), 0);
2614 zend_str_tolower_copy(ZSTR_VAL(lc_method_name), ZSTR_VAL(method_name), ZSTR_LEN(method_name));
2615
2616 if ((fbc = zend_hash_find_ptr(&pdo_row_ce->function_table, lc_method_name)) == NULL) {
2617 zend_string_release(lc_method_name);
2618 return NULL;
2619 }
2620
2621 zend_string_release(lc_method_name);
2622 return fbc;
2623 }
2624
2625 static int row_call_method(zend_string *method, zend_object *object, INTERNAL_FUNCTION_PARAMETERS)
2626 {
2627 return FAILURE;
2628 }
2629
2630 static union _zend_function *row_get_ctor(zend_object *object)
2631 {
2632 static zend_internal_function ctor = {0};
2633
2634 ctor.type = ZEND_INTERNAL_FUNCTION;
2635 ctor.function_name = zend_string_init("__construct", sizeof("__construct") - 1, 0);
2636 ctor.scope = pdo_row_ce;
2637 ctor.handler = ZEND_FN(dbrow_constructor);
2638 ctor.fn_flags = ZEND_ACC_PUBLIC;
2639
2640 return (union _zend_function*)&ctor;
2641 }
2642
2643 static zend_string *row_get_classname(const zend_object *object)
2644 {
2645 return zend_string_init("PDORow", sizeof("PDORow") - 1, 0);
2646 }
2647
2648 static int row_compare(zval *object1, zval *object2)
2649 {
2650 return -1;
2651 }
2652
2653 zend_object_handlers pdo_row_object_handlers = {
2654 0,
2655 zend_objects_destroy_object,
2656 pdo_row_free_storage,
2657 NULL,
2658 row_prop_read,
2659 row_prop_write,
2660 row_dim_read,
2661 row_dim_write,
2662 NULL,
2663 NULL,
2664 NULL,
2665 row_prop_exists,
2666 row_prop_delete,
2667 row_dim_exists,
2668 row_dim_delete,
2669 row_get_properties,
2670 row_method_get,
2671 row_call_method,
2672 row_get_ctor,
2673 row_get_classname,
2674 row_compare,
2675 NULL,
2676 NULL
2677 };
2678
2679 void pdo_row_free_storage(zend_object *std)
2680 {
2681 pdo_row_t *row = (pdo_row_t *)std;
2682 if (row->stmt) {
2683 ZVAL_UNDEF(&row->stmt->lazy_object_ref);
2684 OBJ_RELEASE(&row->stmt->std);
2685 }
2686 }
2687
2688 zend_object *pdo_row_new(zend_class_entry *ce)
2689 {
2690 pdo_row_t *row = ecalloc(1, sizeof(pdo_row_t));
2691 zend_object_std_init(&row->std, ce);
2692 row->std.handlers = &pdo_row_object_handlers;
2693
2694 return &row->std;
2695 }
2696
2697 static int pdo_row_serialize(zval *object, unsigned char **buffer, size_t *buf_len, zend_serialize_data *data)
2698 {
2699 php_error_docref(NULL, E_WARNING, "PDORow instances may not be serialized");
2700 return FAILURE;
2701 }
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711