php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
pdo_dbh.c
Go to the documentation of this file.
1/*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | https://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Author: Wez Furlong <wez@php.net> |
14 | Marcus Boerger <helly@php.net> |
15 | Sterling Hughes <sterling@php.net> |
16 +----------------------------------------------------------------------+
17*/
18
19/* The PDO Database Handle Class */
20
21#ifdef HAVE_CONFIG_H
22#include <config.h>
23#endif
24
25#include "php.h"
26#include "php_ini.h"
27#include "ext/standard/info.h"
28#include "php_pdo.h"
29#include "php_pdo_driver.h"
30#include "php_pdo_int.h"
31#include "zend_attributes.h"
32#include "zend_exceptions.h"
34#include "zend_hash.h"
35#include "pdo_dbh_arginfo.h"
36#include "zend_observer.h"
37#include "zend_extensions.h"
38
39static bool pdo_dbh_attribute_set(pdo_dbh_t *dbh, zend_long attr, zval *value);
40
41void pdo_throw_exception(unsigned int driver_errcode, char *driver_errmsg, pdo_error_type *pdo_error)
42{
43 zval error_info,pdo_exception;
44 char *pdo_exception_message;
45
46 object_init_ex(&pdo_exception, php_pdo_get_exception());
47 array_init(&error_info);
48
49 add_next_index_string(&error_info, *pdo_error);
50 add_next_index_long(&error_info, driver_errcode);
51 add_next_index_string(&error_info, driver_errmsg);
52
53 spprintf(&pdo_exception_message, 0,"SQLSTATE[%s] [%d] %s",*pdo_error, driver_errcode, driver_errmsg);
54 zend_update_property(php_pdo_get_exception(), Z_OBJ(pdo_exception), "errorInfo", sizeof("errorInfo")-1, &error_info);
55 zend_update_property_long(php_pdo_get_exception(), Z_OBJ(pdo_exception), "code", sizeof("code")-1, driver_errcode);
58 Z_OBJ(pdo_exception),
59 "message",
60 sizeof("message")-1,
61 pdo_exception_message
62 );
63 efree(pdo_exception_message);
64 zval_ptr_dtor(&error_info);
65 zend_throw_exception_object(&pdo_exception);
66}
67
68void pdo_raise_impl_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, pdo_error_type sqlstate, const char *supp) /* {{{ */
69{
70 pdo_error_type *pdo_err = &dbh->error_code;
71 char *message = NULL;
72 const char *msg;
73
74 if (dbh->error_mode == PDO_ERRMODE_SILENT) {
75#if 0
76 /* BUG: if user is running in silent mode and hits an error at the driver level
77 * when they use the PDO methods to call up the error information, they may
78 * get bogus information */
79 return;
80#endif
81 }
82
83 if (stmt) {
84 pdo_err = &stmt->error_code;
85 }
86
87 memcpy(*pdo_err, sqlstate, sizeof(pdo_error_type));
88
89 /* hash sqlstate to error messages */
91 if (!msg) {
92 msg = "<<Unknown error>>";
93 }
94
95 if (supp) {
96 spprintf(&message, 0, "SQLSTATE[%s]: %s: %s", *pdo_err, msg, supp);
97 } else {
98 spprintf(&message, 0, "SQLSTATE[%s]: %s", *pdo_err, msg);
99 }
100
101 if (dbh->error_mode != PDO_ERRMODE_EXCEPTION) {
102 php_error_docref(NULL, E_WARNING, "%s", message);
103 } else {
104 zval ex, info;
106
107 object_init_ex(&ex, pdo_ex);
108
109 zend_update_property_string(zend_ce_exception, Z_OBJ(ex), "message", sizeof("message")-1, message);
110 zend_update_property_string(zend_ce_exception, Z_OBJ(ex), "code", sizeof("code")-1, *pdo_err);
111
112 array_init(&info);
113
114 add_next_index_string(&info, *pdo_err);
115 add_next_index_long(&info, 0);
116 zend_update_property(pdo_ex, Z_OBJ(ex), "errorInfo", sizeof("errorInfo")-1, &info);
117 zval_ptr_dtor(&info);
118
120 }
121
122 if (message) {
123 efree(message);
124 }
125}
126/* }}} */
127
128PDO_API void pdo_handle_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt) /* {{{ */
129{
130 pdo_error_type *pdo_err = &dbh->error_code;
131 const char *msg = "<<Unknown>>";
132 char *supp = NULL;
133 zend_long native_code = 0;
134 zend_string *message = NULL;
135 zval info;
136
137 if (dbh->error_mode == PDO_ERRMODE_SILENT) {
138 return;
139 }
140
141 if (stmt) {
142 pdo_err = &stmt->error_code;
143 }
144
145 /* hash sqlstate to error messages */
147 if (!msg) {
148 msg = "<<Unknown error>>";
149 }
150
151 ZVAL_UNDEF(&info);
152 if (dbh->methods->fetch_err) {
153 zval *item;
154 array_init(&info);
155
156 add_next_index_string(&info, *pdo_err);
157
158 dbh->methods->fetch_err(dbh, stmt, &info);
159
160 if ((item = zend_hash_index_find(Z_ARRVAL(info), 1)) != NULL
161 && Z_TYPE_P(item) == IS_LONG) {
162 native_code = Z_LVAL_P(item);
163 }
164
165 if ((item = zend_hash_index_find(Z_ARRVAL(info), 2)) != NULL) {
166 supp = estrndup(Z_STRVAL_P(item), Z_STRLEN_P(item));
167 }
168 }
169
170 if (native_code && supp) {
171 message = strpprintf(0, "SQLSTATE[%s]: %s: " ZEND_LONG_FMT " %s", *pdo_err, msg, native_code, supp);
172 } else if (supp) {
173 message = strpprintf(0, "SQLSTATE[%s]: %s: %s", *pdo_err, msg, supp);
174 } else {
175 message = strpprintf(0, "SQLSTATE[%s]: %s", *pdo_err, msg);
176 }
177
178 if (dbh->error_mode == PDO_ERRMODE_WARNING) {
179 php_error_docref(NULL, E_WARNING, "%s", ZSTR_VAL(message));
180 } else if (EG(exception) == NULL) {
181 zval ex;
183
184 object_init_ex(&ex, pdo_ex);
185
186 zend_update_property_str(zend_ce_exception, Z_OBJ(ex), "message", sizeof("message") - 1, message);
187 zend_update_property_string(zend_ce_exception, Z_OBJ(ex), "code", sizeof("code") - 1, *pdo_err);
188
189 if (!Z_ISUNDEF(info)) {
190 zend_update_property(pdo_ex, Z_OBJ(ex), "errorInfo", sizeof("errorInfo") - 1, &info);
191 }
192
194 }
195
196 if (!Z_ISUNDEF(info)) {
197 zval_ptr_dtor(&info);
198 }
199
200 zend_string_release_ex(message, false);
201
202 if (supp) {
203 efree(supp);
204 }
205}
206/* }}} */
207
208static char *dsn_from_uri(char *uri, char *buf, size_t buflen) /* {{{ */
209{
210 php_stream *stream;
211 char *dsn = NULL;
212
213 stream = php_stream_open_wrapper(uri, "rb", REPORT_ERRORS, NULL);
214 if (stream) {
215 dsn = php_stream_get_line(stream, buf, buflen, NULL);
216 php_stream_close(stream);
217 }
218 return dsn;
219}
220/* }}} */
221
222static bool create_driver_specific_pdo_object(pdo_driver_t *driver, zend_class_entry *called_scope, zval *new_zval_object)
223{
225 zend_class_entry *ce_based_on_driver_name = NULL, *ce_based_on_called_object = NULL;
226
227 ce_based_on_driver_name = zend_hash_str_find_ptr(&pdo_driver_specific_ce_hash, driver->driver_name, driver->driver_name_len);
228
230 if (called_scope != pdo_dbh_ce && instanceof_function(called_scope, ce)) {
231 ce_based_on_called_object = called_scope;
232 break;
233 }
235
236 if (ce_based_on_called_object) {
237 if (ce_based_on_driver_name) {
238 if (!instanceof_function(ce_based_on_called_object, ce_based_on_driver_name)) {
240 "%s::%s() cannot be used for connecting to the \"%s\" driver, "
241 "either call %s::%s() or PDO::%s() instead",
242 ZSTR_VAL(called_scope->name),
243 new_zval_object ? "connect" : "__construct",
244 driver->driver_name,
245 ZSTR_VAL(ce_based_on_driver_name->name),
246 new_zval_object ? "connect" : "__construct",
247 new_zval_object ? "connect" : "__construct"
248 );
249 return false;
250 }
251
252 /* A driver-specific implementation is instantiated with the appropriate driver class */
253 if (new_zval_object) {
254 object_init_ex(new_zval_object, called_scope);
255 }
256 return true;
257 } else {
259 "%s::%s() cannot be used for connecting to an unknown driver, "
260 "call PDO::%s() instead",
261 ZSTR_VAL(called_scope->name),
262 new_zval_object ? "connect" : "__construct",
263 new_zval_object ? "connect" : "__construct"
264 );
265 return false;
266 }
267 }
268
269 /* A non-driver specific PDO subclass is instantiated via the constructor. This results in the legacy behavior. */
270 if (called_scope != pdo_dbh_ce && new_zval_object == NULL) {
271 return true;
272 }
273
274 if (ce_based_on_driver_name) {
275 if (called_scope != pdo_dbh_ce) {
276 /* A driver-specific implementation is instantiated with a wrong driver class */
278 "%s::%s() cannot be used for connecting to the \"%s\" driver, "
279 "either call %s::%s() or PDO::%s() instead",
280 ZSTR_VAL(called_scope->name),
281 new_zval_object ? "connect" : "__construct",
282 driver->driver_name,
283 ZSTR_VAL(ce_based_on_driver_name->name),
284 new_zval_object ? "connect" : "__construct",
285 new_zval_object ? "connect" : "__construct"
286 );
287 return false;
288 }
289
290 if (new_zval_object) {
291 object_init_ex(new_zval_object, ce_based_on_driver_name);
292 }
293 } else if (new_zval_object) {
294 /* No driver-specific implementation found */
295 object_init_ex(new_zval_object, called_scope);
296 }
297
298 return true;
299}
300
302{
303 pdo_dbh_t *dbh = NULL;
304 bool is_persistent = 0;
305 char *data_source;
306 size_t data_source_len;
307 char *colon;
308 char *username=NULL, *password=NULL;
309 size_t usernamelen, passwordlen;
310 pdo_driver_t *driver = NULL;
311 zval *options = NULL;
312 char alt_dsn[512];
313 int call_factory = 1;
315
317 Z_PARAM_STRING(data_source, data_source_len)
319 Z_PARAM_STRING_OR_NULL(username, usernamelen)
320 Z_PARAM_STRING_OR_NULL(password, passwordlen)
323
324 /* parse the data source name */
325 colon = strchr(data_source, ':');
326
327 if (!colon) {
328 /* let's see if this string has a matching dsn in the php.ini */
329 char *ini_dsn = NULL;
330
331 snprintf(alt_dsn, sizeof(alt_dsn), "pdo.dsn.%s", data_source);
332 if (FAILURE == cfg_get_string(alt_dsn, &ini_dsn)) {
333 zend_argument_error(php_pdo_get_exception(), 1, "must be a valid data source name");
335 }
336
337 data_source = ini_dsn;
338 colon = strchr(data_source, ':');
339
340 if (!colon) {
341 zend_throw_exception_ex(php_pdo_get_exception(), 0, "invalid data source name (via INI: %s)", alt_dsn);
343 }
344 }
345
346 if (!strncmp(data_source, "uri:", sizeof("uri:")-1)) {
347 /* the specified URI holds connection details */
348 data_source = dsn_from_uri(data_source + sizeof("uri:")-1, alt_dsn, sizeof(alt_dsn));
349 if (!data_source) {
350 zend_argument_error(php_pdo_get_exception(), 1, "must be a valid data source URI");
352 }
353 colon = strchr(data_source, ':');
354 if (!colon) {
355 zend_argument_error(php_pdo_get_exception(), 1, "must be a valid data source name (via URI)");
357 }
358 }
359
360 driver = pdo_find_driver(data_source, colon - data_source);
361
362 if (!driver) {
363 /* NB: don't want to include the data_source in the error message as
364 * it might contain a password */
365 zend_throw_exception_ex(php_pdo_get_exception(), 0, "could not find driver");
367 }
368
369 ZEND_ASSERT((driver->driver_name != NULL) && "PDO driver name is null");
370
371 if (!create_driver_specific_pdo_object(driver, called_scope, new_zval_object)) {
373 }
374
375 if (new_zval_object) {
376 dbh = Z_PDO_DBH_P(new_zval_object);
377 } else {
378 dbh = php_pdo_dbh_fetch_inner(current_object);
379 }
380
381 /* is this supposed to be a persistent connection ? */
382 if (options) {
383 int plen = 0;
384 char *hashkey = NULL;
385 zend_resource *le;
386 pdo_dbh_t *pdbh = NULL;
387 zval *v;
388
389 if ((v = zend_hash_index_find_deref(Z_ARRVAL_P(options), PDO_ATTR_PERSISTENT)) != NULL) {
390 if (Z_TYPE_P(v) == IS_STRING &&
391 !is_numeric_string(Z_STRVAL_P(v), Z_STRLEN_P(v), NULL, NULL, 0) && Z_STRLEN_P(v) > 0) {
392 /* user specified key */
393 plen = spprintf(&hashkey, 0, "PDO:DBH:DSN=%s:%s:%s:%s", data_source,
394 username ? username : "",
395 password ? password : "",
396 Z_STRVAL_P(v));
397 is_persistent = 1;
398 } else {
399 is_persistent = zval_get_long(v) ? 1 : 0;
400 plen = spprintf(&hashkey, 0, "PDO:DBH:DSN=%s:%s:%s", data_source,
401 username ? username : "",
402 password ? password : "");
403 }
404 }
405
406 if (is_persistent) {
407 /* let's see if we have one cached.... */
408 if ((le = zend_hash_str_find_ptr(&EG(persistent_list), hashkey, plen)) != NULL) {
409 if (le->type == php_pdo_list_entry()) {
410 pdbh = (pdo_dbh_t*)le->ptr;
411
412 /* is the connection still alive ? */
413 if (pdbh->methods->check_liveness && FAILURE == (pdbh->methods->check_liveness)(pdbh)) {
414 /* nope... need to kill it */
415 pdbh->refcount--;
416 zend_list_close(le);
417 pdbh = NULL;
418 }
419 }
420 }
421
422 if (pdbh) {
423 call_factory = 0;
424 } else {
425 /* need a brand new pdbh */
426 pdbh = pecalloc(1, sizeof(*pdbh), 1);
427
428 pdbh->refcount = 1;
429 pdbh->is_persistent = 1;
430 pdbh->persistent_id = pemalloc(plen + 1, 1);
431 memcpy((char *)pdbh->persistent_id, hashkey, plen+1);
432 pdbh->persistent_id_len = plen;
433 pdbh->def_stmt_ce = dbh->def_stmt_ce;
434 }
435 }
436
437 if (pdbh) {
438 efree(dbh);
439
440 pdo_dbh_object_t *pdo_obj;
441 if (new_zval_object) {
442 pdo_obj = Z_PDO_OBJECT_P(new_zval_object);
443 } else {
444 pdo_obj = php_pdo_dbh_fetch_object(current_object);
445 }
446
447 /* switch over to the persistent one */
448 pdo_obj->inner = pdbh;
449 pdbh->refcount++;
450 dbh = pdbh;
451 }
452
453 if (hashkey) {
454 efree(hashkey);
455 }
456 }
457
458 if (call_factory) {
459 dbh->data_source_len = strlen(colon + 1);
460 dbh->data_source = (const char*)pestrdup(colon + 1, is_persistent);
461 dbh->username = username ? pestrdup(username, is_persistent) : NULL;
462 dbh->password = password ? pestrdup(password, is_persistent) : NULL;
464 }
465
466 dbh->auto_commit = pdo_attr_lval(options, PDO_ATTR_AUTOCOMMIT, 1);
468
469 if (!dbh->data_source || (username && !dbh->username) || (password && !dbh->password)) {
470 php_error_docref(NULL, E_ERROR, "Out of memory");
471 }
472
473 /* pdo_dbh_attribute_set() can emit a Warning if the ERR_MODE is set to warning
474 * As we are in a constructor we override the behaviour by replacing the error handler */
476
477 if (!call_factory) {
478 /* we got a persistent guy from our cache */
479 goto options;
480 }
481
482 if (driver->db_handle_factory(dbh, options)) {
483 /* all set */
484
485 if (is_persistent) {
486 /* register in the persistent list etc. */
487 /* we should also need to replace the object store entry,
488 since it was created with emalloc */
490 (char*)dbh->persistent_id, dbh->persistent_id_len, dbh, php_pdo_list_entry())) == NULL) {
491 php_error_docref(NULL, E_ERROR, "Failed to register persistent entry");
492 }
493 }
494
495 dbh->driver = driver;
496options:
497 if (options) {
498 zval *attr_value;
499 zend_ulong long_key;
500 zend_string *str_key = NULL;
501
502 ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(options), long_key, str_key, attr_value) {
503 if (str_key) {
504 continue;
505 }
506 ZVAL_DEREF(attr_value);
507
508 /* TODO: Should the constructor fail when the attribute cannot be set? */
509 pdo_dbh_attribute_set(dbh, long_key, attr_value);
511 }
512
514 return;
515 }
516
517 /* the connection failed; things will tidy up in free_storage */
518 if (is_persistent) {
519 dbh->refcount--;
520 }
521
522 /* XXX raise exception */
524 if (!EG(exception)) {
525 zend_throw_exception(pdo_exception_ce, "Constructor failed", 0);
526 }
527}
528
529/* {{{ */
534/* }}} */
535
536/* {{{ */
541/* }}} */
542
543static zval *pdo_stmt_instantiate(pdo_dbh_t *dbh, zval *object, zend_class_entry *dbstmt_ce, zval *ctor_args) /* {{{ */
544{
545 if (!Z_ISUNDEF_P(ctor_args)) {
546 /* This implies an error within PDO if this does not hold */
547 ZEND_ASSERT(Z_TYPE_P(ctor_args) == IS_ARRAY);
548 if (!dbstmt_ce->constructor) {
549 zend_throw_error(NULL, "User-supplied statement does not accept constructor arguments");
550 return NULL;
551 }
552 }
553
554 if (UNEXPECTED(object_init_ex(object, dbstmt_ce) != SUCCESS)) {
555 if (EXPECTED(!EG(exception))) {
556 zend_throw_error(NULL, "Cannot instantiate user-supplied statement class");
557 }
558 return NULL;
559 }
560
561 return object;
562} /* }}} */
563
564static void pdo_stmt_construct(pdo_stmt_t *stmt, zval *object, zend_class_entry *dbstmt_ce, HashTable *ctor_args)
565{
566 zval query_string;
568
569 ZVAL_STR(&query_string, stmt->query_string);
570 key = ZSTR_INIT_LITERAL("queryString", 0);
571 zend_std_write_property(Z_OBJ_P(object), key, &query_string, NULL);
573
574 if (dbstmt_ce->constructor) {
575 zend_call_known_function(dbstmt_ce->constructor, Z_OBJ_P(object), Z_OBJCE_P(object), NULL, 0, NULL, ctor_args);
576 }
577}
578
579/* {{{ Prepares a statement for execution and returns a statement object */
581{
582 pdo_stmt_t *stmt;
583 zend_string *statement;
584 zval *options = NULL, *value, *item, ctor_args;
585 zend_class_entry *dbstmt_ce, *pce;
587 pdo_dbh_t *dbh = dbh_obj->inner;
588
590 Z_PARAM_STR(statement)
594
596
597 if (ZSTR_LEN(statement) == 0) {
600 }
601
603
605 if (Z_TYPE_P(value) != IS_ARRAY) {
606 zend_type_error("PDO::ATTR_STATEMENT_CLASS value must be of type array, %s given",
609 }
610 if ((item = zend_hash_index_find(Z_ARRVAL_P(value), 0)) == NULL) {
611 zend_value_error("PDO::ATTR_STATEMENT_CLASS value must be an array with the format "
612 "array(classname, constructor_args)");
614 }
615 if (Z_TYPE_P(item) != IS_STRING || (pce = zend_lookup_class(Z_STR_P(item))) == NULL) {
616 zend_type_error("PDO::ATTR_STATEMENT_CLASS class must be a valid class");
618 }
619 dbstmt_ce = pce;
620 if (!instanceof_function(dbstmt_ce, pdo_dbstmt_ce)) {
621 zend_type_error("PDO::ATTR_STATEMENT_CLASS class must be derived from PDOStatement");
623 }
624 if (dbstmt_ce->constructor && !(dbstmt_ce->constructor->common.fn_flags & (ZEND_ACC_PRIVATE|ZEND_ACC_PROTECTED))) {
625 zend_type_error("User-supplied statement class cannot have a public constructor");
627 }
628 if ((item = zend_hash_index_find(Z_ARRVAL_P(value), 1)) != NULL) {
629 if (Z_TYPE_P(item) != IS_ARRAY) {
630 zend_type_error("PDO::ATTR_STATEMENT_CLASS constructor_args must be of type ?array, %s given",
633 }
634 ZVAL_COPY_VALUE(&ctor_args, item);
635 } else {
636 ZVAL_UNDEF(&ctor_args);
637 }
638 } else {
639 dbstmt_ce = dbh->def_stmt_ce;
640 ZVAL_COPY_VALUE(&ctor_args, &dbh->def_stmt_ctor_args);
641 }
642
643 if (!pdo_stmt_instantiate(dbh, return_value, dbstmt_ce, &ctor_args)) {
645 }
647
648 /* unconditionally keep this for later reference */
649 stmt->query_string = zend_string_copy(statement);
651 stmt->dbh = dbh;
652 /* give it a reference to me */
653 ZVAL_OBJ_COPY(&stmt->database_object_handle, &dbh_obj->std);
654 /* we haven't created a lazy object yet */
656
657 if (dbh->methods->preparer(dbh, statement, stmt, options)) {
658 if (Z_TYPE(ctor_args) == IS_ARRAY) {
659 pdo_stmt_construct(stmt, return_value, dbstmt_ce, Z_ARRVAL(ctor_args));
660 } else {
661 pdo_stmt_construct(stmt, return_value, dbstmt_ce, /* ctor_args */ NULL);
662 }
663 return;
664 }
665
667
668 /* kill the object handle for the stmt here */
670
672}
673/* }}} */
674
675
676static bool pdo_is_in_transaction(pdo_dbh_t *dbh) {
677 if (dbh->methods->in_transaction) {
678 return dbh->methods->in_transaction(dbh);
679 }
680 return dbh->in_txn;
681}
682
683/* {{{ Initiates a transaction */
684PHP_METHOD(PDO, beginTransaction)
685{
687
689
691
692 if (pdo_is_in_transaction(dbh)) {
693 zend_throw_exception_ex(php_pdo_get_exception(), 0, "There is already an active transaction");
695 }
696
697 if (!dbh->methods->begin) {
698 /* Throw an exception when the driver does not support transactions */
699 zend_throw_exception_ex(php_pdo_get_exception(), 0, "This driver doesn't support transactions");
701 }
702
703 if (dbh->methods->begin(dbh)) {
704 dbh->in_txn = true;
706 }
707
710}
711/* }}} */
712
713/* {{{ Commit a transaction */
715{
717
719
721
722 if (!pdo_is_in_transaction(dbh)) {
723 zend_throw_exception_ex(php_pdo_get_exception(), 0, "There is no active transaction");
725 }
726
727 if (dbh->methods->commit(dbh)) {
728 dbh->in_txn = false;
730 }
731
734}
735/* }}} */
736
737/* {{{ roll back a transaction */
738PHP_METHOD(PDO, rollBack)
739{
741
743
745
746 if (!pdo_is_in_transaction(dbh)) {
747 zend_throw_exception_ex(php_pdo_get_exception(), 0, "There is no active transaction");
749 }
750
751 if (dbh->methods->rollback(dbh)) {
752 dbh->in_txn = false;
754 }
755
758}
759/* }}} */
760
761/* {{{ determine if inside a transaction */
762PHP_METHOD(PDO, inTransaction)
763{
765
767
769
770 RETURN_BOOL(pdo_is_in_transaction(dbh));
771}
772/* }}} */
773
775{
776 switch (Z_TYPE_P(value)) {
777 case IS_LONG:
778 case IS_TRUE:
779 case IS_FALSE:
780 *lval = zval_get_long(value);
781 return true;
782 case IS_STRING:
784 return true;
785 }
787 default:
788 zend_type_error("Attribute value must be of type int for selected attribute, %s given", zend_zval_value_name(value));
789 return false;
790 }
791}
793{
794 switch (Z_TYPE_P(value)) {
795 case IS_TRUE:
796 *bval = true;
797 return true;
798 case IS_FALSE:
799 *bval = false;
800 return true;
801 case IS_LONG:
802 *bval = zval_is_true(value);
803 return true;
804 case IS_STRING: /* TODO Should string be allowed? */
805 default:
806 zend_type_error("Attribute value must be of type bool for selected attribute, %s given", zend_zval_value_name(value));
807 return false;
808 }
809}
810
811/* Return false on failure, true otherwise */
812static bool pdo_dbh_attribute_set(pdo_dbh_t *dbh, zend_long attr, zval *value) /* {{{ */
813{
814 zend_long lval;
815 bool bval;
816
817 switch (attr) {
818 case PDO_ATTR_ERRMODE:
819 if (!pdo_get_long_param(&lval, value)) {
820 return false;
821 }
822 switch (lval) {
826 dbh->error_mode = lval;
827 return true;
828 default:
829 zend_value_error("Error mode must be one of the PDO::ERRMODE_* constants");
830 return false;
831 }
832 return false;
833
834 case PDO_ATTR_CASE:
835 if (!pdo_get_long_param(&lval, value)) {
836 return false;
837 }
838 switch (lval) {
839 case PDO_CASE_NATURAL:
840 case PDO_CASE_UPPER:
841 case PDO_CASE_LOWER:
842 dbh->desired_case = lval;
843 return true;
844 default:
845 zend_value_error("Case folding mode must be one of the PDO::CASE_* constants");
846 return false;
847 }
848 return false;
849
851 if (!pdo_get_long_param(&lval, value)) {
852 return false;
853 }
854 /* TODO Check for valid value (NULL_NATURAL, NULL_EMPTY_STRING, NULL_TO_STRING)? */
855 dbh->oracle_nulls = lval;
856 return true;
857
859 if (Z_TYPE_P(value) == IS_ARRAY) {
860 zval *tmp;
861 if ((tmp = zend_hash_index_find(Z_ARRVAL_P(value), 0)) != NULL && Z_TYPE_P(tmp) == IS_LONG) {
862 if (Z_LVAL_P(tmp) == PDO_FETCH_INTO || Z_LVAL_P(tmp) == PDO_FETCH_CLASS) {
863 zend_value_error("PDO::FETCH_INTO and PDO::FETCH_CLASS cannot be set as the default fetch mode");
864 return false;
865 }
866 }
867 lval = zval_get_long(value);
868 } else {
869 if (!pdo_get_long_param(&lval, value)) {
870 return false;
871 }
872 }
873 if (lval == PDO_FETCH_USE_DEFAULT) {
874 zend_value_error("Fetch mode must be a bitmask of PDO::FETCH_* constants");
875 return false;
876 }
877 dbh->default_fetch_type = lval;
878 return true;
879
881 if (!pdo_get_bool_param(&bval, value)) {
882 return false;
883 }
884 dbh->stringify = bval;
885 if (dbh->methods->set_attribute) {
886 dbh->methods->set_attribute(dbh, attr, value);
887 }
888 return true;
889
891 /* array(string classname, array(mixed ctor_args)) */
892 zend_class_entry *pce;
893 zval *item;
894
895 if (dbh->is_persistent) {
896 /* TODO: ValueError/ PDOException? */
897 pdo_raise_impl_error(dbh, NULL, "HY000",
898 "PDO::ATTR_STATEMENT_CLASS cannot be used with persistent PDO instances"
899 );
901 return false;
902 }
903 if (Z_TYPE_P(value) != IS_ARRAY) {
904 zend_type_error("PDO::ATTR_STATEMENT_CLASS value must be of type array, %s given",
906 return false;
907 }
908 if ((item = zend_hash_index_find(Z_ARRVAL_P(value), 0)) == NULL) {
909 zend_value_error("PDO::ATTR_STATEMENT_CLASS value must be an array with the format "
910 "array(classname, constructor_args)");
911 return false;
912 }
913 if (Z_TYPE_P(item) != IS_STRING || (pce = zend_lookup_class(Z_STR_P(item))) == NULL) {
914 zend_type_error("PDO::ATTR_STATEMENT_CLASS class must be a valid class");
915 return false;
916 }
917 if (!instanceof_function(pce, pdo_dbstmt_ce)) {
918 zend_type_error("PDO::ATTR_STATEMENT_CLASS class must be derived from PDOStatement");
919 return false;
920 }
922 zend_type_error("User-supplied statement class cannot have a public constructor");
923 return false;
924 }
925 dbh->def_stmt_ce = pce;
926 if (!Z_ISUNDEF(dbh->def_stmt_ctor_args)) {
929 }
930 if ((item = zend_hash_index_find(Z_ARRVAL_P(value), 1)) != NULL) {
931 if (Z_TYPE_P(item) != IS_ARRAY) {
932 zend_type_error("PDO::ATTR_STATEMENT_CLASS constructor_args must be of type ?array, %s given",
934 return false;
935 }
936 ZVAL_COPY(&dbh->def_stmt_ctor_args, item);
937 }
938 return true;
939 }
940 /* Don't throw a ValueError as the attribute might be a driver specific one */
941 default:;
942 }
943
944 if (!dbh->methods->set_attribute) {
945 goto fail;
946 }
947
949 if (dbh->methods->set_attribute(dbh, attr, value)) {
950 return true;
951 }
952
953fail:
954 if (!dbh->methods->set_attribute) {
955 pdo_raise_impl_error(dbh, NULL, "IM001", "driver does not support setting attributes");
956 } else {
958 }
959 return false;
960}
961/* }}} */
962
963/* {{{ Set an attribute */
964PHP_METHOD(PDO, setAttribute)
965{
968 zval *value;
969
974
977
978 RETURN_BOOL(pdo_dbh_attribute_set(dbh, attr, value));
979}
980/* }}} */
981
982/* {{{ Get an attribute */
983PHP_METHOD(PDO, getAttribute)
984{
987
991
994
995 /* handle generic PDO-level attributes */
996 switch (attr) {
999
1000 case PDO_ATTR_CASE:
1002
1005
1006 case PDO_ATTR_ERRMODE:
1007 RETURN_LONG(dbh->error_mode);
1008
1011
1014 add_next_index_str(return_value, zend_string_copy(dbh->def_stmt_ce->name));
1015 if (!Z_ISUNDEF(dbh->def_stmt_ctor_args)) {
1017 add_next_index_zval(return_value, &dbh->def_stmt_ctor_args);
1018 }
1019 return;
1020
1023
1025 RETURN_BOOL(dbh->stringify);
1026
1027 default:
1028 break;
1029 }
1030
1031 if (!dbh->methods->get_attribute) {
1032 pdo_raise_impl_error(dbh, NULL, "IM001", "driver does not support getting attributes");
1034 }
1035
1036 switch (dbh->methods->get_attribute(dbh, attr, return_value)) {
1037 case -1:
1040
1041 case 0:
1042 pdo_raise_impl_error(dbh, NULL, "IM001", "driver does not support that attribute");
1044
1045 default:
1046 /* No error state, just return as the return_value has been assigned
1047 * by the get_attribute handler */
1048 return;
1049 }
1050}
1051/* }}} */
1052
1053/* {{{ Execute a statement that does not return a row set, returning the number of affected rows */
1055{
1057 zend_string *statement;
1058 zend_long ret;
1059
1061 Z_PARAM_STR(statement)
1063
1064 if (ZSTR_LEN(statement) == 0) {
1066 RETURN_THROWS();
1067 }
1068
1071 ret = dbh->methods->doer(dbh, statement);
1072 if (ret == -1) {
1075 } else {
1077 }
1078}
1079/* }}} */
1080
1081/* {{{ Returns the id of the last row that we affected on this connection. Some databases require a sequence or table name to be passed in. Not always meaningful. */
1082PHP_METHOD(PDO, lastInsertId)
1083{
1086 zend_string *last_id = NULL;
1087
1092
1094
1096
1097 if (!dbh->methods->last_id) {
1098 pdo_raise_impl_error(dbh, NULL, "IM001", "driver does not support lastInsertId()");
1100 }
1101 last_id = dbh->methods->last_id(dbh, name);
1102 if (!last_id) {
1105 }
1106 RETURN_STR(last_id);
1107}
1108/* }}} */
1109
1110/* {{{ Fetch the error code associated with the last operation on the database handle */
1111PHP_METHOD(PDO, errorCode)
1112{
1114
1116
1118
1119 if (dbh->query_stmt) {
1121 }
1122
1123 if (dbh->error_code[0] == '\0') {
1124 RETURN_NULL();
1125 }
1126
1132}
1133/* }}} */
1134
1135/* {{{ Fetch extended error information associated with the last operation on the database handle */
1136PHP_METHOD(PDO, errorInfo)
1137{
1138 int error_count;
1139 int error_count_diff = 0;
1140 int error_expected_count = 3;
1141
1143
1145
1147
1149
1150 if (dbh->query_stmt) {
1152 if(!strncmp(dbh->query_stmt->error_code, PDO_ERR_NONE, sizeof(PDO_ERR_NONE))) goto fill_array;
1153 } else {
1155 if(!strncmp(dbh->error_code, PDO_ERR_NONE, sizeof(PDO_ERR_NONE))) goto fill_array;
1156 }
1157
1158 if (dbh->methods->fetch_err) {
1159 dbh->methods->fetch_err(dbh, dbh->query_stmt, return_value);
1160 }
1161
1162fill_array:
1168 error_count = zend_hash_num_elements(Z_ARRVAL_P(return_value));
1169
1170 if (error_expected_count > error_count) {
1171 int current_index;
1172
1173 error_count_diff = error_expected_count - error_count;
1174 for (current_index = 0; current_index < error_count_diff; current_index++) {
1176 }
1177 }
1178}
1179/* }}} */
1180
1181/* {{{ Prepare and execute $sql; returns the statement object for iteration */
1183{
1184 pdo_stmt_t *stmt;
1185 zend_string *statement;
1186 zend_long fetch_mode;
1187 bool fetch_mode_is_null = 1;
1188 zval *args = NULL;
1189 uint32_t num_args = 0;
1191 pdo_dbh_t *dbh = dbh_obj->inner;
1192
1193 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "S|l!*", &statement,
1194 &fetch_mode, &fetch_mode_is_null, &args, &num_args)) {
1195 RETURN_THROWS();
1196 }
1197
1199
1200 if (ZSTR_LEN(statement) == 0) {
1202 RETURN_THROWS();
1203 }
1204
1206
1207 if (!pdo_stmt_instantiate(dbh, return_value, dbh->def_stmt_ce, &dbh->def_stmt_ctor_args)) {
1208 RETURN_THROWS();
1209 }
1210 stmt = Z_PDO_STMT_P(return_value);
1211
1212 /* unconditionally keep this for later reference */
1213 stmt->query_string = zend_string_copy(statement);
1214 stmt->active_query_string = zend_string_copy(stmt->query_string);
1216 stmt->dbh = dbh;
1217 /* give it a reference to me */
1218 ZVAL_OBJ_COPY(&stmt->database_object_handle, &dbh_obj->std);
1219 /* we haven't created a lazy object yet */
1221
1222 if (dbh->methods->preparer(dbh, statement, stmt, NULL)) {
1224 if (fetch_mode_is_null || pdo_stmt_setup_fetch_mode(stmt, fetch_mode, 2, args, num_args)) {
1225 /* now execute the statement */
1227 if (stmt->methods->executer(stmt)) {
1228 bool ret = true;
1229 if (!stmt->executed) {
1230 if (stmt->dbh->alloc_own_columns) {
1232 }
1233 stmt->executed = 1;
1234 }
1235 if (ret) {
1236 if (Z_TYPE(dbh->def_stmt_ctor_args) == IS_ARRAY) {
1237 pdo_stmt_construct(stmt, return_value, dbh->def_stmt_ce, Z_ARRVAL(dbh->def_stmt_ctor_args));
1238 } else {
1239 pdo_stmt_construct(stmt, return_value, dbh->def_stmt_ce, /* ctor_args */ NULL);
1240 }
1241 return;
1242 }
1243 }
1244 }
1245 /* something broke */
1246 dbh->query_stmt = stmt;
1251 } else {
1254 }
1255
1257}
1258/* }}} */
1259
1260/* {{{ quotes string for use in a query.
1261 * The optional paramtype acts as a hint for drivers that have alternate quoting styles.
1262 * The default value is PDO_PARAM_STR */
1264{
1266 zend_string *str, *quoted;
1267 zend_long paramtype = PDO_PARAM_STR;
1268
1270 Z_PARAM_STR(str)
1272 Z_PARAM_LONG(paramtype)
1274
1276
1278 if (!dbh->methods->quoter) {
1279 pdo_raise_impl_error(dbh, NULL, "IM001", "driver does not support quoting");
1281 }
1282 quoted = dbh->methods->quoter(dbh, str, paramtype);
1283
1284 if (quoted == NULL) {
1287 }
1288
1289 RETURN_STR(quoted);
1290}
1291/* }}} */
1292
1293/* {{{ Return array of available PDO drivers */
1294PHP_METHOD(PDO, getAvailableDrivers)
1295{
1296 pdo_driver_t *pdriver;
1297
1299
1301
1305}
1306/* }}} */
1307
1308static void cls_method_dtor(zval *el) /* {{{ */ {
1310 if (func->common.function_name) {
1311 zend_string_release_ex(func->common.function_name, 0);
1312 }
1313 if (ZEND_MAP_PTR(func->common.run_time_cache)) {
1314 efree(ZEND_MAP_PTR(func->common.run_time_cache));
1315 }
1316 efree(func);
1317}
1318/* }}} */
1319
1320static void cls_method_pdtor(zval *el) /* {{{ */ {
1322 if (func->common.function_name) {
1323 zend_string_release_ex(func->common.function_name, 1);
1324 }
1325 if (ZEND_MAP_PTR(func->common.run_time_cache)) {
1326 pefree(ZEND_MAP_PTR(func->common.run_time_cache), 1);
1327 }
1328 pefree(func, 1);
1329}
1330/* }}} */
1331
1332/* {{{ overloaded object handlers for PDO class */
1334{
1335 const zend_function_entry *funcs;
1337 size_t namelen;
1338 char *lc_name;
1339 pdo_dbh_t *dbh = dbh_obj->inner;
1340
1341 if (!dbh || !dbh->methods || !dbh->methods->get_driver_methods) {
1342 return false;
1343 }
1344 funcs = dbh->methods->get_driver_methods(dbh, kind);
1345 if (!funcs) {
1346 return false;
1347 }
1348
1349 dbh->cls_methods[kind] = pemalloc(sizeof(HashTable), dbh->is_persistent);
1351 dbh->is_persistent? cls_method_pdtor : cls_method_dtor, dbh->is_persistent);
1352
1353 memset(&func, 0, sizeof(func));
1354
1355 size_t rt_cache_size = zend_internal_run_time_cache_reserved_size();
1356 while (funcs->fname) {
1358 func.handler = funcs->handler;
1359 func.function_name = zend_string_init(funcs->fname, strlen(funcs->fname), dbh->is_persistent);
1360 func.scope = dbh_obj->std.ce;
1361 func.prototype = NULL;
1362 ZEND_MAP_PTR(func.run_time_cache) = rt_cache_size ? pecalloc(rt_cache_size, 1, dbh->is_persistent) : NULL;
1364 if (funcs->flags) {
1365 func.fn_flags = funcs->flags | ZEND_ACC_NEVER_CACHE;
1366 } else {
1368 }
1369 func.doc_comment = NULL;
1370 if (funcs->arg_info) {
1372
1373 func.arg_info = (zend_internal_arg_info*)funcs->arg_info + 1;
1374 func.num_args = funcs->num_args;
1375 if (info->required_num_args == (uint32_t)-1) {
1376 func.required_num_args = funcs->num_args;
1377 } else {
1378 func.required_num_args = info->required_num_args;
1379 }
1380 if (ZEND_ARG_SEND_MODE(info)) {
1381 func.fn_flags |= ZEND_ACC_RETURN_REFERENCE;
1382 }
1383 if (ZEND_ARG_IS_VARIADIC(&funcs->arg_info[funcs->num_args])) {
1384 func.fn_flags |= ZEND_ACC_VARIADIC;
1385 /* Don't count the variadic argument */
1386 func.num_args--;
1387 }
1388 } else {
1389 func.arg_info = NULL;
1390 func.num_args = 0;
1391 func.required_num_args = 0;
1392 }
1394 namelen = strlen(funcs->fname);
1395 lc_name = emalloc(namelen+1);
1396 zend_str_tolower_copy(lc_name, funcs->fname, namelen);
1397 zend_hash_str_add_mem(dbh->cls_methods[kind], lc_name, namelen, &func, sizeof(func));
1398 efree(lc_name);
1399 funcs++;
1400 }
1401
1402 return true;
1403}
1404
1405static zend_function *dbh_method_get(zend_object **object, zend_string *method_name, const zval *key)
1406{
1408 pdo_dbh_object_t *dbh_obj = php_pdo_dbh_fetch_object(*object);
1409 zend_string *lc_method_name;
1410
1411 if ((fbc = zend_std_get_method(object, method_name, key)) == NULL) {
1412 /* not a pre-defined method, nor a user-defined method; check
1413 * the driver specific methods */
1415 if (!pdo_hash_methods(dbh_obj,
1418 goto out;
1419 }
1420 }
1421
1422 lc_method_name = zend_string_tolower(method_name);
1423 fbc = zend_hash_find_ptr(dbh_obj->inner->cls_methods[PDO_DBH_DRIVER_METHOD_KIND_DBH], lc_method_name);
1424 zend_string_release_ex(lc_method_name, 0);
1425 }
1426
1427out:
1428 return fbc;
1429}
1430
1431static HashTable *dbh_get_gc(zend_object *object, zval **gc_data, int *gc_count)
1432{
1433 pdo_dbh_t *dbh = php_pdo_dbh_fetch_inner(object);
1435 zend_get_gc_buffer_add_zval(gc_buffer, &dbh->def_stmt_ctor_args);
1436 if (dbh->methods && dbh->methods->get_gc) {
1437 dbh->methods->get_gc(dbh, gc_buffer);
1438 }
1439 zend_get_gc_buffer_use(gc_buffer, gc_data, gc_count);
1440 return zend_std_get_properties(object);
1441}
1442
1443static zend_object_handlers pdo_dbh_object_handlers;
1444
1445static void pdo_dbh_free_storage(zend_object *std);
1446
1447void pdo_dbh_init(int module_number)
1448{
1449 pdo_dbh_ce = register_class_PDO();
1450 pdo_dbh_ce->create_object = pdo_dbh_new;
1451 pdo_dbh_ce->default_object_handlers = &pdo_dbh_object_handlers;
1452
1453 memcpy(&pdo_dbh_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
1454 pdo_dbh_object_handlers.offset = XtOffsetOf(pdo_dbh_object_t, std);
1455 pdo_dbh_object_handlers.free_obj = pdo_dbh_free_storage;
1456 pdo_dbh_object_handlers.clone_obj = NULL;
1457 pdo_dbh_object_handlers.get_method = dbh_method_get;
1458 pdo_dbh_object_handlers.compare = zend_objects_not_comparable;
1459 pdo_dbh_object_handlers.get_gc = dbh_get_gc;
1460}
1461
1462static void dbh_free(pdo_dbh_t *dbh, bool free_persistent)
1463{
1464 int i;
1465
1466 if (dbh->query_stmt) {
1468 dbh->query_stmt = NULL;
1469 }
1470
1471 if (dbh->is_persistent) {
1472#if ZEND_DEBUG
1473 ZEND_ASSERT(!free_persistent || (dbh->refcount == 1));
1474#endif
1475 if (!free_persistent && (--dbh->refcount)) {
1476 return;
1477 }
1478 }
1479
1480 if (dbh->methods) {
1481 dbh->methods->closer(dbh);
1482 }
1483
1484 if (dbh->data_source) {
1485 pefree((char *)dbh->data_source, dbh->is_persistent);
1486 }
1487 if (dbh->username) {
1488 pefree(dbh->username, dbh->is_persistent);
1489 }
1490 if (dbh->password) {
1491 pefree(dbh->password, dbh->is_persistent);
1492 }
1493
1494 if (dbh->persistent_id) {
1495 pefree((char *)dbh->persistent_id, dbh->is_persistent);
1496 }
1497
1498 if (!Z_ISUNDEF(dbh->def_stmt_ctor_args)) {
1500 }
1501
1502 for (i = 0; i < PDO_DBH_DRIVER_METHOD_KIND__MAX; i++) {
1503 if (dbh->cls_methods[i]) {
1505 pefree(dbh->cls_methods[i], dbh->is_persistent);
1506 }
1507 }
1508
1509 pefree(dbh, dbh->is_persistent);
1510}
1511
1512static void pdo_dbh_free_storage(zend_object *std)
1513{
1514 pdo_dbh_t *dbh = php_pdo_dbh_fetch_inner(std);
1515
1516 /* dbh might be null if we OOMed during object initialization. */
1517 if (!dbh) {
1518 return;
1519 }
1520
1521 if (dbh->driver_data && dbh->methods && dbh->methods->rollback && pdo_is_in_transaction(dbh)) {
1522 dbh->methods->rollback(dbh);
1523 dbh->in_txn = false;
1524 }
1525
1526 if (dbh->is_persistent && dbh->methods && dbh->methods->persistent_shutdown) {
1527 dbh->methods->persistent_shutdown(dbh);
1528 }
1530 dbh_free(dbh, 0);
1531}
1532
1534{
1535 pdo_dbh_object_t *dbh;
1536
1537 dbh = zend_object_alloc(sizeof(pdo_dbh_object_t), ce);
1538 zend_object_std_init(&dbh->std, ce);
1539 object_properties_init(&dbh->std, ce);
1540 /* rebuild properties */
1541 zend_std_get_properties_ex(&dbh->std);
1542 dbh->inner = ecalloc(1, sizeof(pdo_dbh_t));
1544
1545 return &dbh->std;
1546}
1547
1548/* }}} */
1549
1550ZEND_RSRC_DTOR_FUNC(php_pdo_pdbh_dtor) /* {{{ */
1551{
1552 if (res->ptr) {
1553 pdo_dbh_t *dbh = (pdo_dbh_t*)res->ptr;
1554 dbh_free(dbh, 1);
1555 res->ptr = NULL;
1556 }
1557}
1558/* }}} */
bool exception
Definition assert.c:30
strchr(string $haystack, string $needle, bool $before_needle=false)
uint32_t v
Definition cdf.c:1237
new_type kind
Definition ffi.c:4363
zend_string * res
Definition ffi.c:4692
memcpy(ptr1, ptr2, size)
memset(ptr, 0, type->size)
new_type attr
Definition ffi.c:4364
zend_ffi_ctype_name_buf buf
Definition ffi.c:4685
#define NULL
Definition gdcache.h:45
#define SUCCESS
Definition hash_sha3.c:261
PHPAPI ZEND_COLD void php_error_docref(const char *docref, int type, const char *format,...)
Definition main.c:1173
pdo_driver_t * pdo_find_driver(const char *name, int namelen)
Definition pdo.c:151
zend_class_entry * pdo_dbstmt_ce
Definition pdo.c:34
HashTable pdo_driver_specific_ce_hash
Definition pdo.c:45
HashTable pdo_driver_hash
Definition pdo.c:42
zend_class_entry * pdo_exception_ce
Definition pdo.c:37
zend_class_entry * pdo_dbh_ce
Definition pdo.c:34
PDO_API zend_class_entry * php_pdo_get_exception(void)
Definition pdo.c:62
int php_pdo_list_entry(void)
Definition pdo.c:50
PDO_API bool pdo_get_long_param(zend_long *lval, zval *value)
Definition pdo_dbh.c:774
void pdo_raise_impl_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, pdo_error_type sqlstate, const char *supp)
Definition pdo_dbh.c:68
void pdo_dbh_init(int module_number)
Definition pdo_dbh.c:1447
PDO_API void pdo_handle_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt)
Definition pdo_dbh.c:128
PDO_API bool pdo_get_bool_param(bool *bval, zval *value)
Definition pdo_dbh.c:792
bool pdo_hash_methods(pdo_dbh_object_t *dbh_obj, int kind)
Definition pdo_dbh.c:1333
void pdo_throw_exception(unsigned int driver_errcode, char *driver_errmsg, pdo_error_type *pdo_error)
Definition pdo_dbh.c:41
PDO_API void php_pdo_internal_construct_driver(INTERNAL_FUNCTION_PARAMETERS, zend_object *current_object, zend_class_entry *called_scope, zval *new_zval_object)
Definition pdo_dbh.c:301
zend_object * pdo_dbh_new(zend_class_entry *ce)
Definition pdo_dbh.c:1533
const char * pdo_sqlstate_state_to_description(char *state)
bool pdo_stmt_describe_columns(pdo_stmt_t *stmt)
Definition pdo_stmt.c:128
bool pdo_stmt_setup_fetch_mode(pdo_stmt_t *stmt, zend_long mode, uint32_t mode_arg_num, zval *args, uint32_t variadic_num_args)
Definition pdo_stmt.c:1713
#define PHP_METHOD
Definition php.h:365
PHPAPI int cfg_get_string(const char *varname, char **result)
Definition php_ini.c:927
PHP_JSON_API size_t int options
Definition php_json.h:102
#define PDO_API
Definition php_pdo.h:42
#define PDO_CONSTRUCT_CHECK
Definition php_pdo.h:64
char sqlstate[6]
struct _pdo_dbh_t pdo_dbh_t
@ PDO_ERRMODE_SILENT
@ PDO_ERRMODE_WARNING
@ PDO_ERRMODE_EXCEPTION
#define PDO_ERR_NONE
struct _pdo_stmt_t pdo_stmt_t
#define Z_PDO_STMT_P(zv)
@ PDO_PARAM_STR
@ PDO_CASE_UPPER
@ PDO_CASE_LOWER
@ PDO_CASE_NATURAL
char pdo_error_type[6]
@ PDO_FETCH_BOTH
@ PDO_FETCH_USE_DEFAULT
@ PDO_FETCH_CLASS
@ PDO_FETCH_INTO
@ PDO_DBH_DRIVER_METHOD_KIND_DBH
@ PDO_DBH_DRIVER_METHOD_KIND__MAX
#define Z_PDO_DBH_P(zv)
#define Z_PDO_OBJECT_P(zv)
struct _pdo_dbh_object_t pdo_dbh_object_t
@ PDO_ATTR_STATEMENT_CLASS
@ PDO_ATTR_CASE
@ PDO_ATTR_DRIVER_NAME
@ PDO_ATTR_ERRMODE
@ PDO_ATTR_PERSISTENT
@ PDO_ATTR_AUTOCOMMIT
@ PDO_ATTR_ORACLE_NULLS
@ PDO_ATTR_STRINGIFY_FETCHES
@ PDO_ATTR_DEFAULT_FETCH_MODE
#define PDO_HANDLE_DBH_ERR()
#define PDO_STMT_CLEAR_ERR()
#define PDO_HANDLE_STMT_ERR()
#define PDO_DBH_CLEAR_ERR()
unsigned char key[REFLECTION_KEY_LEN]
struct _php_stream php_stream
Definition php_streams.h:96
#define REPORT_ERRORS
#define php_stream_get_line(stream, buf, maxlen, retlen)
#define php_stream_close(stream)
#define php_stream_open_wrapper(path, mode, options, opened)
char * msg
Definition phpdbg.h:289
char * exec
Definition phpdbg.h:263
zend_object * ex
bool fail
Definition session.c:1065
ptrdiff_t namelen
Definition session.c:1097
#define strpprintf
Definition spprintf.h:30
#define spprintf
Definition spprintf.h:29
const char * data_source
unsigned int refcount
HashTable * cls_methods[PDO_DBH_DRIVER_METHOD_KIND__MAX]
unsigned is_persistent
const char * persistent_id
enum pdo_case_conversion native_case desired_case
enum pdo_fetch_type default_fetch_type
size_t persistent_id_len
size_t data_source_len
void * driver_data
pdo_driver_t * driver
unsigned stringify
pdo_error_type error_code
enum pdo_error_mode error_mode
pdo_stmt_t * query_stmt
unsigned alloc_own_columns
zend_class_entry * def_stmt_ce
unsigned auto_commit
zval def_stmt_ctor_args
const struct pdo_dbh_methods * methods
unsigned oracle_nulls
zend_string * active_query_string
zend_string * query_string
unsigned executed
pdo_error_type error_code
const struct pdo_stmt_methods * methods
enum pdo_fetch_type default_fetch_type
zval database_object_handle
pdo_dbh_t * dbh
zend_string * name
Definition zend.h:149
zend_function * constructor
Definition zend.h:172
zif_handler handler
Definition zend_API.h:37
const char * fname
Definition zend_API.h:36
uint32_t flags
Definition zend_API.h:40
const struct _zend_internal_arg_info * arg_info
Definition zend_API.h:38
uint32_t num_args
Definition zend_API.h:39
zend_class_entry * ce
Definition zend_types.h:560
pdo_dbh_txn_func rollback
pdo_dbh_fetch_error_func fetch_err
pdo_dbh_get_driver_methods_func get_driver_methods
pdo_dbh_do_func doer
pdo_dbh_check_liveness_func check_liveness
pdo_dbh_get_gc_func get_gc
pdo_dbh_quote_func quoter
pdo_dbh_get_attr_func get_attribute
pdo_dbh_last_id_func last_id
pdo_dbh_close_func closer
pdo_dbh_set_attr_func set_attribute
pdo_dbh_prepare_func preparer
pdo_dbh_txn_func commit
pdo_dbh_request_shutdown persistent_shutdown
pdo_dbh_txn_func in_transaction
pdo_dbh_txn_func begin
int(* db_handle_factory)(pdo_dbh_t *dbh, zval *driver_options)
size_t driver_name_len
const char * driver_name
pdo_stmt_execute_func executer
struct _zend_function::@236135173067030250234125302313220025134003177336 common
uint32_t fn_flags
ZEND_API ZEND_COLD void zend_throw_error(zend_class_entry *exception_ce, const char *format,...)
Definition zend.c:1772
ZEND_API ZEND_COLD void zend_type_error(const char *format,...)
Definition zend.c:1824
ZEND_API ZEND_COLD void zend_value_error(const char *format,...)
Definition zend.c:1849
#define INTERNAL_FUNCTION_PARAMETERS
Definition zend.h:49
@ EH_THROW
Definition zend.h:433
ZEND_API void zend_replace_error_handling(zend_error_handling_t error_handling, zend_class_entry *exception_class, zend_error_handling *current)
Definition zend_API.c:5242
ZEND_API void zend_restore_error_handling(zend_error_handling *saved)
Definition zend_API.c:5253
#define INTERNAL_FUNCTION_PARAM_PASSTHRU
Definition zend.h:50
ZEND_API zend_result add_next_index_null(zval *arg)
Definition zend_API.c:2141
ZEND_API const char * zend_zval_value_name(const zval *arg)
Definition zend_API.c:148
ZEND_API zend_result add_next_index_stringl(zval *arg, const char *str, size_t length)
Definition zend_API.c:2195
ZEND_API zend_result add_next_index_long(zval *arg, zend_long n)
Definition zend_API.c:2132
ZEND_API zend_result object_init_ex(zval *arg, zend_class_entry *class_type)
Definition zend_API.c:1849
ZEND_API ZEND_COLD void zend_argument_error(zend_class_entry *error_ce, uint32_t arg_num, const char *format,...)
Definition zend_API.c:413
ZEND_API void zend_update_property_string(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, const char *value)
Definition zend_API.c:5066
ZEND_API zend_result zend_parse_parameters(uint32_t num_args, const char *type_spec,...)
Definition zend_API.c:1300
ZEND_API void zend_update_property(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, zval *value)
Definition zend_API.c:4991
ZEND_API void object_properties_init(zend_object *object, zend_class_entry *class_type)
Definition zend_API.c:1688
ZEND_API ZEND_COLD void zend_argument_must_not_be_empty_error(uint32_t arg_num)
Definition zend_API.c:443
ZEND_API void zend_update_property_long(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, zend_long value)
Definition zend_API.c:5039
ZEND_API zend_result add_next_index_string(zval *arg, const char *str)
Definition zend_API.c:2186
ZEND_API void zend_update_property_str(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, zend_string *value)
Definition zend_API.c:5057
ZEND_API zend_result add_next_index_str(zval *arg, zend_string *str)
Definition zend_API.c:2177
#define ZEND_NUM_ARGS()
Definition zend_API.h:530
#define Z_PARAM_ARRAY_OR_NULL(dest)
Definition zend_API.h:1685
#define RETURN_STRING(s)
Definition zend_API.h:1043
#define RETURN_STRINGL(s, l)
Definition zend_API.h:1044
#define ZEND_PARSE_PARAMETERS_END()
Definition zend_API.h:1641
#define RETURN_FALSE
Definition zend_API.h:1058
struct _zend_function_entry zend_function_entry
#define Z_PARAM_STR_OR_NULL(dest)
Definition zend_API.h:2089
#define ZEND_PARSE_PARAMETERS_NONE()
Definition zend_API.h:1623
#define RETURN_NULL()
Definition zend_API.h:1036
#define Z_PARAM_OPTIONAL
Definition zend_API.h:1667
#define Z_PARAM_STRING(dest, dest_len)
Definition zend_API.h:2071
#define Z_PARAM_STR(dest)
Definition zend_API.h:2086
#define Z_PARAM_STRING_OR_NULL(dest, dest_len)
Definition zend_API.h:2074
#define ZEND_PARSE_PARAMETERS_START(min_num_args, max_num_args)
Definition zend_API.h:1620
#define Z_PARAM_LONG(dest)
Definition zend_API.h:1896
#define RETURN_LONG(l)
Definition zend_API.h:1037
#define RETURN_BOOL(b)
Definition zend_API.h:1035
#define RETURN_THROWS()
Definition zend_API.h:1060
#define RETURN_STR(s)
Definition zend_API.h:1039
#define ZEND_THIS
Definition zend_API.h:523
#define Z_PARAM_ARRAY(dest)
Definition zend_API.h:1682
ZEND_API void zend_call_known_function(zend_function *fn, zend_object *object, zend_class_entry *called_scope, zval *retval_ptr, uint32_t param_count, zval *params, HashTable *named_params)
#define Z_PARAM_ZVAL(dest)
Definition zend_API.h:2100
#define RETURN_TRUE
Definition zend_API.h:1059
#define array_init(arg)
Definition zend_API.h:537
#define estrndup(s, length)
Definition zend_alloc.h:165
#define pestrdup(s, persistent)
Definition zend_alloc.h:206
#define ecalloc(nmemb, size)
Definition zend_alloc.h:158
#define efree(ptr)
Definition zend_alloc.h:155
#define pefree(ptr, persistent)
Definition zend_alloc.h:191
#define pemalloc(size, persistent)
Definition zend_alloc.h:189
#define pecalloc(nmemb, size, persistent)
Definition zend_alloc.h:200
#define emalloc(size)
Definition zend_alloc.h:151
struct _zval_struct zval
strlen(string $string)
strncmp(string $string1, string $string2, int $length)
uint32_t num_args
zend_string_release_ex(func->internal_function.function_name, 0)
execute_data func
zval * args
ZEND_API void zend_set_function_arg_flags(zend_function *func)
struct _zend_internal_function_info zend_internal_function_info
#define ZEND_INTERNAL_FUNCTION
#define ZEND_ARG_SEND_MODE(arg_info)
#define ZEND_ACC_PRIVATE
struct _zend_internal_arg_info zend_internal_arg_info
#define ZEND_ARG_IS_VARIADIC(arg_info)
#define ZEND_ACC_PUBLIC
#define ZEND_ACC_VARIADIC
struct _zend_internal_function zend_internal_function
#define ZEND_ACC_RETURN_REFERENCE
#define ZEND_ACC_PROTECTED
#define ZEND_ACC_NEVER_CACHE
#define snprintf
#define E_ERROR
Definition zend_errors.h:23
#define E_WARNING
Definition zend_errors.h:24
ZEND_API zend_class_entry * zend_ce_exception
ZEND_API ZEND_COLD void zend_throw_exception_object(zval *exception)
ZEND_API ZEND_COLD zend_object * zend_throw_exception(zend_class_entry *exception_ce, const char *message, zend_long code)
ZEND_API ZEND_COLD zend_object * zend_throw_exception_ex(zend_class_entry *exception_ce, zend_long code, const char *format,...)
ZEND_API zend_class_entry * zend_lookup_class(zend_string *name)
ZEND_API size_t zend_internal_run_time_cache_reserved_size(void)
union _zend_function zend_function
ZEND_API zend_get_gc_buffer * zend_get_gc_buffer_create(void)
Definition zend_gc.c:2130
#define EG(v)
ZEND_API void ZEND_FASTCALL zend_hash_destroy(HashTable *ht)
Definition zend_hash.c:1727
ZEND_API zval *ZEND_FASTCALL zend_hash_index_find(const HashTable *ht, zend_ulong h)
Definition zend_hash.c:2701
#define zend_hash_init(ht, nSize, pHashFunction, pDestructor, persistent)
Definition zend_hash.h:108
#define ZEND_HASH_MAP_FOREACH_PTR(ht, _ptr)
Definition zend_hash.h:1326
#define ZEND_HASH_FOREACH_KEY_VAL(ht, _h, _key, _val)
Definition zend_hash.h:1181
#define ZEND_HASH_FOREACH_END()
Definition zend_hash.h:1086
ZEND_API zend_resource * zend_register_persistent_resource(const char *key, size_t key_len, void *rsrc_pointer, int rsrc_type)
Definition zend_list.c:342
ZEND_API void ZEND_FASTCALL zend_list_close(zend_resource *res)
Definition zend_list.c:78
#define ZEND_RSRC_DTOR_FUNC(name)
Definition zend_list.h:29
int32_t zend_long
Definition zend_long.h:42
uint32_t zend_ulong
Definition zend_long.h:43
#define ZEND_LONG_FMT
Definition zend_long.h:87
struct _zend_string zend_string
#define ZEND_MAP_PTR(ptr)
ZEND_API zend_function * zend_std_get_method(zend_object **obj_ptr, zend_string *method_name, const zval *key)
ZEND_API int zend_objects_not_comparable(zval *o1, zval *o2)
ZEND_API HashTable * zend_std_get_properties(zend_object *zobj)
ZEND_API const zend_object_handlers std_object_handlers
ZEND_API zval * zend_std_write_property(zend_object *zobj, zend_string *name, zval *value, void **cache_slot)
ZEND_API void ZEND_FASTCALL zend_object_std_init(zend_object *object, zend_class_entry *ce)
ZEND_API void zend_object_std_dtor(zend_object *object)
#define ZEND_OBSERVER_ENABLED
ZEND_API char *ZEND_FASTCALL zend_str_tolower_copy(char *dest, const char *source, size_t length)
ZEND_API uint8_t ZEND_FASTCALL is_numeric_str_function(const zend_string *str, zend_long *lval, double *dval)
#define zval_is_true(op)
#define ZEND_FALLTHROUGH
#define EXPECTED(condition)
#define XtOffsetOf(s_type, field)
#define ZEND_ASSERT(c)
#define UNEXPECTED(condition)
struct _zend_class_entry zend_class_entry
struct _zend_object zend_object
#define ZSTR_VAL(zstr)
Definition zend_string.h:68
#define ZSTR_INIT_LITERAL(s, persistent)
#define ZSTR_LEN(zstr)
Definition zend_string.h:69
#define Z_TYPE_P(zval_p)
Definition zend_types.h:660
#define IS_TRUE
Definition zend_types.h:603
#define ZVAL_STR(z, s)
#define ZVAL_UNDEF(z)
#define IS_FALSE
Definition zend_types.h:602
#define Z_STRVAL_P(zval_p)
Definition zend_types.h:975
#define Z_ISUNDEF_P(zval_p)
Definition zend_types.h:957
#define Z_ARRVAL_P(zval_p)
Definition zend_types.h:987
#define ZVAL_DEREF(z)
#define IS_STRING
Definition zend_types.h:606
struct _zend_resource zend_resource
Definition zend_types.h:99
struct _zend_array HashTable
Definition zend_types.h:386
#define Z_OBJ_P(zval_p)
Definition zend_types.h:990
#define IS_ARRAY
Definition zend_types.h:607
#define Z_ISUNDEF(zval)
Definition zend_types.h:956
#define Z_STR_P(zval_p)
Definition zend_types.h:972
#define Z_PTR_P(zval_p)
#define Z_STRLEN_P(zval_p)
Definition zend_types.h:978
#define Z_OBJCE_P(zval_p)
#define ZVAL_OBJ(z, o)
@ FAILURE
Definition zend_types.h:61
#define Z_TRY_ADDREF(z)
#define IS_LONG
Definition zend_types.h:604
#define ZVAL_COPY(z, v)
#define ZVAL_OBJ_COPY(z, o)
#define Z_CE_P(zval_p)
struct _zend_object_handlers zend_object_handlers
Definition zend_types.h:88
#define Z_TYPE(zval)
Definition zend_types.h:659
#define Z_ARRVAL(zval)
Definition zend_types.h:986
#define Z_LVAL_P(zval_p)
Definition zend_types.h:966
#define ZVAL_COPY_VALUE(z, v)
#define Z_DELREF(z)
#define Z_OBJ(zval)
Definition zend_types.h:989
ZEND_API void zval_ptr_dtor(zval *zval_ptr)
zval * return_value
zend_string * name
zend_function * fbc
object
zval * ret
value
out($f, $s)