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