PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/pdo - pdo_dbh.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 642 765 83.9 %
Date: 2016-06-25 Functions: 31 34 91.2 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :   +----------------------------------------------------------------------+
       3             :   | PHP Version 7                                                        |
       4             :   +----------------------------------------------------------------------+
       5             :   | Copyright (c) 1997-2016 The PHP Group                                |
       6             :   +----------------------------------------------------------------------+
       7             :   | This source file is subject to version 3.01 of the PHP license,      |
       8             :   | that is bundled with this package in the file LICENSE, and is        |
       9             :   | available through the world-wide-web at the following url:           |
      10             :   | http://www.php.net/license/3_01.txt                                  |
      11             :   | If you did not receive a copy of the PHP license and are unable to   |
      12             :   | obtain it through the world-wide-web, please send a note to          |
      13             :   | license@php.net so we can mail you a copy immediately.               |
      14             :   +----------------------------------------------------------------------+
      15             :   | Author: Wez Furlong <wez@php.net>                                    |
      16             :   |         Marcus Boerger <helly@php.net>                               |
      17             :   |         Sterling Hughes <sterling@php.net>                           |
      18             :   +----------------------------------------------------------------------+
      19             : */
      20             : 
      21             : /* $Id$ */
      22             : 
      23             : /* The PDO Database Handle Class */
      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 "php_pdo.h"
      33             : #include "php_pdo_driver.h"
      34             : #include "php_pdo_int.h"
      35             : #include "zend_exceptions.h"
      36             : #include "zend_object_handlers.h"
      37             : #include "zend_hash.h"
      38             : 
      39             : static int pdo_dbh_attribute_set(pdo_dbh_t *dbh, zend_long attr, zval *value);
      40             : 
      41         445 : void pdo_raise_impl_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, const char *sqlstate, const char *supp) /* {{{ */
      42             : {
      43         445 :         pdo_error_type *pdo_err = &dbh->error_code;
      44         445 :         char *message = NULL;
      45             :         const char *msg;
      46             : 
      47         445 :         if (dbh && dbh->error_mode == PDO_ERRMODE_SILENT) {
      48             : #if 0
      49             :                 /* BUG: if user is running in silent mode and hits an error at the driver level
      50             :                  * when they use the PDO methods to call up the error information, they may
      51             :                  * get bogus information */
      52             :                 return;
      53             : #endif
      54             :         }
      55             : 
      56         445 :         if (stmt) {
      57         380 :                 pdo_err = &stmt->error_code;
      58             :         }
      59             : 
      60         445 :         strncpy(*pdo_err, sqlstate, 6);
      61             : 
      62             :         /* hash sqlstate to error messages */
      63         445 :         msg = pdo_sqlstate_state_to_description(*pdo_err);
      64         445 :         if (!msg) {
      65           0 :                 msg = "<<Unknown error>>";
      66             :         }
      67             : 
      68         445 :         if (supp) {
      69         445 :                 spprintf(&message, 0, "SQLSTATE[%s]: %s: %s", *pdo_err, msg, supp);
      70             :         } else {
      71           0 :                 spprintf(&message, 0, "SQLSTATE[%s]: %s", *pdo_err, msg);
      72             :         }
      73             : 
      74         861 :         if (dbh && dbh->error_mode != PDO_ERRMODE_EXCEPTION) {
      75         416 :                 php_error_docref(NULL, E_WARNING, "%s", message);
      76             :         } else {
      77             :                 zval ex, info;
      78          29 :                 zend_class_entry *def_ex = php_pdo_get_exception_base(1), *pdo_ex = php_pdo_get_exception();
      79             : 
      80          29 :                 object_init_ex(&ex, pdo_ex);
      81             : 
      82          29 :                 zend_update_property_string(def_ex, &ex, "message", sizeof("message")-1, message);
      83          29 :                 zend_update_property_string(def_ex, &ex, "code", sizeof("code")-1, *pdo_err);
      84             : 
      85          29 :                 array_init(&info);
      86             : 
      87          29 :                 add_next_index_string(&info, *pdo_err);
      88          29 :                 add_next_index_long(&info, 0);
      89          29 :                 zend_update_property(pdo_ex, &ex, "errorInfo", sizeof("errorInfo")-1, &info);
      90          29 :                 zval_ptr_dtor(&info);
      91             : 
      92          29 :                 zend_throw_exception_object(&ex);
      93             :         }
      94             : 
      95         445 :         if (message) {
      96         445 :                 efree(message);
      97             :         }
      98         445 : }
      99             : /* }}} */
     100             : 
     101        2886 : PDO_API void pdo_handle_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt) /* {{{ */
     102             : {
     103        2886 :         pdo_error_type *pdo_err = &dbh->error_code;
     104        2886 :         const char *msg = "<<Unknown>>";
     105        2886 :         char *supp = NULL;
     106        2886 :         zend_long native_code = 0;
     107        2886 :         zend_string *message = NULL;
     108             :         zval info;
     109             : 
     110        2886 :         if (dbh == NULL || dbh->error_mode == PDO_ERRMODE_SILENT) {
     111        2506 :                 return;
     112             :         }
     113             : 
     114         380 :         if (stmt) {
     115         298 :                 pdo_err = &stmt->error_code;
     116             :         }
     117             : 
     118             :         /* hash sqlstate to error messages */
     119         380 :         msg = pdo_sqlstate_state_to_description(*pdo_err);
     120         380 :         if (!msg) {
     121           1 :                 msg = "<<Unknown error>>";
     122             :         }
     123             : 
     124         380 :         ZVAL_UNDEF(&info);
     125         380 :         if (dbh->methods->fetch_err) {
     126         380 :                 array_init(&info);
     127             : 
     128         380 :                 add_next_index_string(&info, *pdo_err);
     129             : 
     130         380 :                 if (dbh->methods->fetch_err(dbh, stmt, &info)) {
     131             :                         zval *item;
     132             : 
     133         380 :                         if ((item = zend_hash_index_find(Z_ARRVAL(info), 1)) != NULL) {
     134         141 :                                 native_code = Z_LVAL_P(item);
     135             :                         }
     136             : 
     137         380 :                         if ((item = zend_hash_index_find(Z_ARRVAL(info), 2)) != NULL) {
     138         141 :                                 supp = estrndup(Z_STRVAL_P(item), Z_STRLEN_P(item));
     139             :                         }
     140             :                 }
     141             :         }
     142             : 
     143         380 :         if (supp) {
     144         141 :                 message = strpprintf(0, "SQLSTATE[%s]: %s: %ld %s", *pdo_err, msg, native_code, supp);
     145             :         } else {
     146         239 :                 message = strpprintf(0, "SQLSTATE[%s]: %s", *pdo_err, msg);
     147             :         }
     148             : 
     149         380 :         if (dbh->error_mode == PDO_ERRMODE_WARNING) {
     150         340 :                 php_error_docref(NULL, E_WARNING, "%s", ZSTR_VAL(message));
     151          40 :         } else if (EG(exception) == NULL) {
     152             :                 zval ex;
     153          28 :                 zend_class_entry *def_ex = php_pdo_get_exception_base(1), *pdo_ex = php_pdo_get_exception();
     154             : 
     155          28 :                 object_init_ex(&ex, pdo_ex);
     156             : 
     157          28 :                 zend_update_property_str(def_ex, &ex, "message", sizeof("message") - 1, message);
     158          28 :                 zend_update_property_string(def_ex, &ex, "code", sizeof("code") - 1, *pdo_err);
     159             : 
     160          28 :                 if (!Z_ISUNDEF(info)) {
     161          28 :                         zend_update_property(pdo_ex, &ex, "errorInfo", sizeof("errorInfo") - 1, &info);
     162             :                 }
     163             : 
     164          28 :                 zend_throw_exception_object(&ex);
     165             :         }
     166             : 
     167         380 :         if (!Z_ISUNDEF(info)) {
     168         380 :                 zval_ptr_dtor(&info);
     169             :         }
     170             : 
     171         380 :         if (message) {
     172             :                 zend_string_release(message);
     173             :         }
     174             : 
     175         380 :         if (supp) {
     176         141 :                 efree(supp);
     177             :         }
     178             : }
     179             : /* }}} */
     180             : 
     181           2 : static char *dsn_from_uri(char *uri, char *buf, size_t buflen) /* {{{ */
     182             : {
     183             :         php_stream *stream;
     184           2 :         char *dsn = NULL;
     185             : 
     186           2 :         stream = php_stream_open_wrapper(uri, "rb", REPORT_ERRORS, NULL);
     187           2 :         if (stream) {
     188           0 :                 dsn = php_stream_get_line(stream, buf, buflen, NULL);
     189           0 :                 php_stream_close(stream);
     190             :         }
     191           2 :         return dsn;
     192             : }
     193             : /* }}} */
     194             : 
     195             : /* {{{ proto void PDO::__construct(string dsn[, string username[, string passwd [, array options]]])
     196             :    */
     197        1282 : static PHP_METHOD(PDO, dbh_constructor)
     198             : {
     199        1282 :         zval *object = getThis();
     200        1282 :         pdo_dbh_t *dbh = NULL;
     201        1282 :         zend_bool is_persistent = 0;
     202             :         char *data_source;
     203             :         size_t data_source_len;
     204             :         char *colon;
     205        1282 :         char *username=NULL, *password=NULL;
     206             :         size_t usernamelen, passwordlen;
     207        1282 :         pdo_driver_t *driver = NULL;
     208        1282 :         zval *options = NULL;
     209             :         char alt_dsn[512];
     210        1282 :         int call_factory = 1;
     211             :         zend_error_handling zeh;
     212             : 
     213        1282 :         if (FAILURE == zend_parse_parameters_throw(ZEND_NUM_ARGS(),
     214             :                                 "s|s!s!a!", &data_source, &data_source_len,
     215             :                                 &username, &usernamelen, &password, &passwordlen, &options)) {
     216           2 :                 return;
     217             :         }
     218             : 
     219             :         /* parse the data source name */
     220        1280 :         colon = strchr(data_source, ':');
     221             : 
     222        1280 :         if (!colon) {
     223             :                 /* let's see if this string has a matching dsn in the php.ini */
     224           5 :                 char *ini_dsn = NULL;
     225             : 
     226           5 :                 snprintf(alt_dsn, sizeof(alt_dsn), "pdo.dsn.%s", data_source);
     227           5 :                 if (FAILURE == cfg_get_string(alt_dsn, &ini_dsn)) {
     228           5 :                         zend_throw_exception_ex(php_pdo_get_exception(), 0, "invalid data source name");
     229           5 :                         return;
     230             :                 }
     231             : 
     232           0 :                 data_source = ini_dsn;
     233           0 :                 colon = strchr(data_source, ':');
     234             : 
     235           0 :                 if (!colon) {
     236           0 :                         zend_throw_exception_ex(php_pdo_get_exception(), 0, "invalid data source name (via INI: %s)", alt_dsn);
     237           0 :                         return;
     238             :                 }
     239             :         }
     240             : 
     241        1275 :         if (!strncmp(data_source, "uri:", sizeof("uri:")-1)) {
     242             :                 /* the specified URI holds connection details */
     243           2 :                 data_source = dsn_from_uri(data_source + sizeof("uri:")-1, alt_dsn, sizeof(alt_dsn));
     244           2 :                 if (!data_source) {
     245           2 :                         zend_throw_exception_ex(php_pdo_get_exception(), 0, "invalid data source URI");
     246           2 :                         return;
     247             :                 }
     248           0 :                 colon = strchr(data_source, ':');
     249           0 :                 if (!colon) {
     250           0 :                         zend_throw_exception_ex(php_pdo_get_exception(), 0, "invalid data source name (via URI)");
     251           0 :                         return;
     252             :                 }
     253             :         }
     254             : 
     255        1273 :         driver = pdo_find_driver(data_source, colon - data_source);
     256             : 
     257        1273 :         if (!driver) {
     258             :                 /* NB: don't want to include the data_source in the error message as
     259             :                  * it might contain a password */
     260           1 :                 zend_throw_exception_ex(php_pdo_get_exception(), 0, "could not find driver");
     261           1 :                 return;
     262             :         }
     263             : 
     264        1272 :         dbh = Z_PDO_DBH_P(object);
     265             : 
     266             :         /* is this supposed to be a persistent connection ? */
     267        1272 :         if (options) {
     268          78 :                 int plen = 0;
     269          78 :                 char *hashkey = NULL;
     270             :                 zend_resource *le;
     271          78 :                 pdo_dbh_t *pdbh = NULL;
     272             :                 zval *v;
     273             : 
     274          78 :                 if ((v = zend_hash_index_find(Z_ARRVAL_P(options), PDO_ATTR_PERSISTENT)) != NULL) {
     275          45 :                         if (Z_TYPE_P(v) == IS_STRING &&
     276           0 :                                 !is_numeric_string(Z_STRVAL_P(v), Z_STRLEN_P(v), NULL, NULL, 0) && Z_STRLEN_P(v) > 0) {
     277             :                                 /* user specified key */
     278           0 :                                 plen = spprintf(&hashkey, 0, "PDO:DBH:DSN=%s:%s:%s:%s", data_source,
     279           0 :                                                 username ? username : "",
     280           0 :                                                 password ? password : "",
     281           0 :                                                 Z_STRVAL_P(v));
     282           0 :                                 is_persistent = 1;
     283             :                         } else {
     284          45 :                                 is_persistent = zval_get_long(v) ? 1 : 0;
     285          90 :                                 plen = spprintf(&hashkey, 0, "PDO:DBH:DSN=%s:%s:%s", data_source,
     286          45 :                                                 username ? username : "",
     287          45 :                                                 password ? password : "");
     288             :                         }
     289             :                 }
     290             : 
     291          78 :                 if (is_persistent) {
     292             :                         /* let's see if we have one cached.... */
     293          88 :                         if ((le = zend_hash_str_find_ptr(&EG(persistent_list), hashkey, plen)) != NULL) {
     294          29 :                                 if (le->type == php_pdo_list_entry()) {
     295          29 :                                         pdbh = (pdo_dbh_t*)le->ptr;
     296             : 
     297             :                                         /* is the connection still alive ? */
     298          29 :                                         if (pdbh->methods->check_liveness && FAILURE == (pdbh->methods->check_liveness)(pdbh)) {
     299             :                                                 /* nope... need to kill it */
     300             :                                                 /*??? memory leak */
     301           1 :                                                 zend_list_close(le);
     302           1 :                                                 pdbh = NULL;
     303             :                                         }
     304             :                                 }
     305             :                         }
     306             : 
     307          44 :                         if (pdbh) {
     308          28 :                                 call_factory = 0;
     309             :                         } else {
     310             :                                 /* need a brand new pdbh */
     311          16 :                                 pdbh = pecalloc(1, sizeof(*pdbh), 1);
     312             : 
     313          16 :                                 pdbh->is_persistent = 1;
     314          16 :                                 pdbh->persistent_id = pemalloc(plen + 1, 1);
     315          16 :                                 memcpy((char *)pdbh->persistent_id, hashkey, plen+1);
     316          16 :                                 pdbh->persistent_id_len = plen;
     317          16 :                                 pdbh->def_stmt_ce = dbh->def_stmt_ce;
     318             :                         }
     319             :                 }
     320             : 
     321          78 :                 if (pdbh) {
     322          44 :                         efree(dbh);
     323             :                         /* switch over to the persistent one */
     324          44 :                         Z_PDO_OBJECT_P(object)->inner = pdbh;
     325          44 :                         dbh = pdbh;
     326             :                 }
     327             : 
     328          78 :                 if (hashkey) {
     329          45 :                         efree(hashkey);
     330             :                 }
     331             :         }
     332             : 
     333        1272 :         if (call_factory) {
     334        1244 :                 dbh->data_source_len = strlen(colon + 1);
     335        1244 :                 dbh->data_source = (const char*)pestrdup(colon + 1, is_persistent);
     336        1244 :                 dbh->username = username ? pestrdup(username, is_persistent) : NULL;
     337        1244 :                 dbh->password = password ? pestrdup(password, is_persistent) : NULL;
     338        1244 :                 dbh->default_fetch_type = PDO_FETCH_BOTH;
     339             :         }
     340             : 
     341        1272 :         dbh->auto_commit = pdo_attr_lval(options, PDO_ATTR_AUTOCOMMIT, 1);
     342             : 
     343        1272 :         if (!dbh->data_source || (username && !dbh->username) || (password && !dbh->password)) {
     344           0 :                 php_error_docref(NULL, E_ERROR, "out of memory");
     345             :         }
     346             : 
     347        1272 :         zend_replace_error_handling(EH_THROW, pdo_exception_ce, &zeh);
     348             : 
     349        1272 :         if (!call_factory) {
     350             :                 /* we got a persistent guy from our cache */
     351          28 :                 goto options;
     352             :         }
     353             : 
     354        1244 :         if (driver->db_handle_factory(dbh, options)) {
     355             :                 /* all set */
     356             : 
     357        1222 :                 if (is_persistent) {
     358             :                         zend_resource le;
     359             : 
     360             :                         /* register in the persistent list etc. */
     361             :                         /* we should also need to replace the object store entry,
     362             :                            since it was created with emalloc */
     363             : 
     364          16 :                         le.type = php_pdo_list_entry();
     365          16 :                         le.ptr = dbh;
     366          16 :                         GC_REFCOUNT(&le) = 1;
     367             : 
     368          32 :                         if ((zend_hash_str_update_mem(&EG(persistent_list),
     369             :                                                 (char*)dbh->persistent_id, dbh->persistent_id_len, &le, sizeof(le))) == NULL) {
     370           0 :                                 php_error_docref(NULL, E_ERROR, "Failed to register persistent entry");
     371             :                         }
     372             :                 }
     373             : 
     374        1222 :                 dbh->driver = driver;
     375             : options:
     376        1250 :                 if (options) {
     377             :                         zval *attr_value;
     378             :                         zend_ulong long_key;
     379          75 :                         zend_string *str_key = NULL;
     380             : 
     381         251 :                         ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(options), long_key, str_key, attr_value) {
     382          79 :                                 if (str_key) {
     383           0 :                                         continue;
     384             :                                 }
     385          79 :                                 pdo_dbh_attribute_set(dbh, long_key, attr_value);
     386             :                         } ZEND_HASH_FOREACH_END();
     387             :                 }
     388             : 
     389        1250 :                 zend_restore_error_handling(&zeh);
     390        1250 :                 return;
     391             :         }
     392             : 
     393             :         /* the connection failed; things will tidy up in free_storage */
     394             :         /* XXX raise exception */
     395          22 :         zend_restore_error_handling(&zeh);
     396          22 :         if (!EG(exception)) {
     397           0 :                 zend_throw_exception(pdo_exception_ce, "Constructor failed", 0);
     398             :         }
     399             : }
     400             : /* }}} */
     401             : 
     402       12477 : static zval *pdo_stmt_instantiate(pdo_dbh_t *dbh, zval *object, zend_class_entry *dbstmt_ce, zval *ctor_args) /* {{{ */
     403             : {
     404       12477 :         if (!Z_ISUNDEF_P(ctor_args)) {
     405          29 :                 if (Z_TYPE_P(ctor_args) != IS_ARRAY) {
     406           0 :                         pdo_raise_impl_error(dbh, NULL, "HY000", "constructor arguments must be passed as an array");
     407           0 :                         return NULL;
     408             :                 }
     409          29 :                 if (!dbstmt_ce->constructor) {
     410           0 :                         pdo_raise_impl_error(dbh, NULL, "HY000", "user-supplied statement does not accept constructor arguments");
     411           0 :                         return NULL;
     412             :                 }
     413             :         }
     414             : 
     415       12477 :         if (UNEXPECTED(object_init_ex(object, dbstmt_ce) != SUCCESS)) {
     416           1 :                 return NULL;
     417             :         }
     418             : 
     419       12476 :         return object;
     420             : } /* }}} */
     421             : 
     422       12395 : static void pdo_stmt_construct(zend_execute_data *execute_data, pdo_stmt_t *stmt, zval *object, zend_class_entry *dbstmt_ce, zval *ctor_args) /* {{{ */
     423             : {
     424             :         zval query_string;
     425             :         zval z_key;
     426             : 
     427       24790 :         ZVAL_STRINGL(&query_string, stmt->query_string, stmt->query_stringlen);
     428       24790 :         ZVAL_STRINGL(&z_key, "queryString", sizeof("queryString") - 1);
     429       12395 :         std_object_handlers.write_property(object, &z_key, &query_string, NULL);
     430       12395 :         zval_ptr_dtor(&query_string);
     431       12395 :         zval_ptr_dtor(&z_key);
     432             : 
     433       12395 :         if (dbstmt_ce->constructor) {
     434             :                 zend_fcall_info fci;
     435             :                 zend_fcall_info_cache fcc;
     436             :                 zval retval;
     437             : 
     438          58 :                 fci.size = sizeof(zend_fcall_info);
     439          58 :                 fci.function_table = &dbstmt_ce->function_table;
     440          58 :                 ZVAL_UNDEF(&fci.function_name);
     441          58 :                 fci.object = Z_OBJ_P(object);
     442          58 :                 fci.symbol_table = NULL;
     443          58 :                 fci.retval = &retval;
     444          58 :                 fci.param_count = 0;
     445          58 :                 fci.params = NULL;
     446          58 :                 fci.no_separation = 1;
     447             : 
     448          58 :                 zend_fcall_info_args(&fci, ctor_args);
     449             : 
     450          58 :                 fcc.initialized = 1;
     451          58 :                 fcc.function_handler = dbstmt_ce->constructor;
     452          58 :                 fcc.calling_scope = EG(scope);
     453          58 :                 fcc.called_scope = Z_OBJCE_P(object);
     454          58 :                 fcc.object = Z_OBJ_P(object);
     455             : 
     456          58 :                 if (zend_call_function(&fci, &fcc) != FAILURE) {
     457          58 :                         zval_ptr_dtor(&retval);
     458             :                 }
     459             : 
     460          58 :                 zend_fcall_info_args_clear(&fci, 1);
     461             :         }
     462       12395 : }
     463             : /* }}} */
     464             : 
     465             : /* {{{ proto object PDO::prepare(string statement [, array options])
     466             :    Prepares a statement for execution and returns a statement object */
     467       11590 : static PHP_METHOD(PDO, prepare)
     468             : {
     469             :         pdo_stmt_t *stmt;
     470             :         char *statement;
     471             :         size_t statement_len;
     472       11590 :         zval *options = NULL, *opt, *item, ctor_args;
     473             :         zend_class_entry *dbstmt_ce, *pce;
     474       11590 :         pdo_dbh_object_t *dbh_obj = Z_PDO_OBJECT_P(getThis());
     475       11590 :         pdo_dbh_t *dbh = dbh_obj->inner;
     476             : 
     477       11590 :         if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "s|a", &statement,
     478             :                         &statement_len, &options)) {
     479           0 :                 RETURN_FALSE;
     480             :         }
     481             : 
     482       11590 :         PDO_DBH_CLEAR_ERR();
     483       11590 :         PDO_CONSTRUCT_CHECK;
     484             : 
     485       11638 :         if (ZEND_NUM_ARGS() > 1 && (opt = zend_hash_index_find(Z_ARRVAL_P(options), PDO_ATTR_STATEMENT_CLASS)) != NULL) {
     486         144 :                 if (Z_TYPE_P(opt) != IS_ARRAY || (item = zend_hash_index_find(Z_ARRVAL_P(opt), 0)) == NULL
     487             :                         || Z_TYPE_P(item) != IS_STRING
     488          48 :                         || (pce = zend_lookup_class(Z_STR_P(item))) == NULL
     489             :                 ) {
     490           0 :                         pdo_raise_impl_error(dbh, NULL, "HY000",
     491             :                                 "PDO::ATTR_STATEMENT_CLASS requires format array(classname, array(ctor_args)); "
     492             :                                 "the classname must be a string specifying an existing class"
     493             :                                 );
     494           0 :                         PDO_HANDLE_DBH_ERR();
     495           0 :                         RETURN_FALSE;
     496             :                 }
     497          48 :                 dbstmt_ce = pce;
     498          48 :                 if (!instanceof_function(dbstmt_ce, pdo_dbstmt_ce)) {
     499           0 :                         pdo_raise_impl_error(dbh, NULL, "HY000",
     500             :                                 "user-supplied statement class must be derived from PDOStatement");
     501           0 :                         PDO_HANDLE_DBH_ERR();
     502           0 :                         RETURN_FALSE;
     503             :                 }
     504          48 :                 if (dbstmt_ce->constructor && !(dbstmt_ce->constructor->common.fn_flags & (ZEND_ACC_PRIVATE|ZEND_ACC_PROTECTED))) {
     505           0 :                         pdo_raise_impl_error(dbh, NULL, "HY000",
     506             :                                 "user-supplied statement class cannot have a public constructor");
     507           0 :                         PDO_HANDLE_DBH_ERR();
     508           0 :                         RETURN_FALSE;
     509             :                 }
     510          48 :                 if ((item = zend_hash_index_find(Z_ARRVAL_P(opt), 1)) != NULL) {
     511          18 :                         if (Z_TYPE_P(item) != IS_ARRAY) {
     512           0 :                                 pdo_raise_impl_error(dbh, NULL, "HY000",
     513             :                                         "PDO::ATTR_STATEMENT_CLASS requires format array(classname, ctor_args); "
     514             :                                         "ctor_args must be an array"
     515             :                                 );
     516           0 :                                 PDO_HANDLE_DBH_ERR();
     517           0 :                                 RETURN_FALSE;
     518             :                         }
     519          18 :                         ZVAL_COPY_VALUE(&ctor_args, item);
     520             :                 } else {
     521          30 :                         ZVAL_UNDEF(&ctor_args);
     522             :                 }
     523             :         } else {
     524       11542 :                 dbstmt_ce = dbh->def_stmt_ce;
     525       11542 :                 ZVAL_COPY_VALUE(&ctor_args, &dbh->def_stmt_ctor_args);
     526             :         }
     527             : 
     528       11590 :         if (!pdo_stmt_instantiate(dbh, return_value, dbstmt_ce, &ctor_args)) {
     529           0 :                 if (EXPECTED(!EG(exception))) {
     530           0 :                         pdo_raise_impl_error(dbh, NULL, "HY000",
     531             :                                 "failed to instantiate user-supplied statement class"
     532             :                                 );
     533             :                 }
     534           0 :                 PDO_HANDLE_DBH_ERR();
     535           0 :                 RETURN_FALSE;
     536             :         }
     537       11590 :         stmt = Z_PDO_STMT_P(return_value);
     538             : 
     539             :         /* unconditionally keep this for later reference */
     540       11590 :         stmt->query_string = estrndup(statement, statement_len);
     541       11590 :         stmt->query_stringlen = statement_len;
     542       11590 :         stmt->default_fetch_type = dbh->default_fetch_type;
     543       11590 :         stmt->dbh = dbh;
     544             :         /* give it a reference to me */
     545       11590 :         ZVAL_OBJ(&stmt->database_object_handle, &dbh_obj->std);
     546       11590 :         Z_ADDREF(stmt->database_object_handle);
     547             :         /* we haven't created a lazy object yet */
     548       11590 :         ZVAL_UNDEF(&stmt->lazy_object_ref);
     549             : 
     550       11590 :         if (dbh->methods->preparer(dbh, statement, statement_len, stmt, options)) {
     551       11585 :                 pdo_stmt_construct(execute_data, stmt, return_value, dbstmt_ce, &ctor_args);
     552       11585 :                 return;
     553             :         }
     554             : 
     555           5 :         PDO_HANDLE_DBH_ERR();
     556             : 
     557             :         /* kill the object handle for the stmt here */
     558             :         zval_dtor(return_value);
     559             : 
     560           5 :         RETURN_FALSE;
     561             : }
     562             : /* }}} */
     563             : 
     564             : /* {{{ proto bool PDO::beginTransaction()
     565             :    Initiates a transaction */
     566       10065 : static PHP_METHOD(PDO, beginTransaction)
     567             : {
     568       10065 :         pdo_dbh_t *dbh = Z_PDO_DBH_P(getThis());
     569             : 
     570       10065 :         if (zend_parse_parameters_none() == FAILURE) {
     571           0 :                 return;
     572             :         }
     573       10065 :         PDO_CONSTRUCT_CHECK;
     574             : 
     575       10065 :         if (dbh->in_txn) {
     576           3 :                 zend_throw_exception_ex(php_pdo_get_exception(), 0, "There is already an active transaction");
     577           3 :                 RETURN_FALSE;
     578             :         }
     579             : 
     580       10062 :         if (!dbh->methods->begin) {
     581             :                 /* TODO: this should be an exception; see the auto-commit mode
     582             :                  * comments below */
     583           0 :                 zend_throw_exception_ex(php_pdo_get_exception(), 0, "This driver doesn't support transactions");
     584           0 :                 RETURN_FALSE;
     585             :         }
     586             : 
     587       10062 :         if (dbh->methods->begin(dbh)) {
     588       10062 :                 dbh->in_txn = 1;
     589       10062 :                 RETURN_TRUE;
     590             :         }
     591             : 
     592           0 :         PDO_HANDLE_DBH_ERR();
     593           0 :         RETURN_FALSE;
     594             : }
     595             : /* }}} */
     596             : 
     597             : /* {{{ proto bool PDO::commit()
     598             :    Commit a transaction */
     599       10021 : static PHP_METHOD(PDO, commit)
     600             : {
     601       10021 :         pdo_dbh_t *dbh = Z_PDO_DBH_P(getThis());
     602             : 
     603       10021 :         if (zend_parse_parameters_none() == FAILURE) {
     604           0 :                 return;
     605             :         }
     606       10021 :         PDO_CONSTRUCT_CHECK;
     607             : 
     608       10021 :         if (!dbh->in_txn) {
     609           0 :                 zend_throw_exception_ex(php_pdo_get_exception(), 0, "There is no active transaction");
     610           0 :                 RETURN_FALSE;
     611             :         }
     612             : 
     613       10021 :         if (dbh->methods->commit(dbh)) {
     614       10021 :                 dbh->in_txn = 0;
     615       10021 :                 RETURN_TRUE;
     616             :         }
     617             : 
     618           0 :         PDO_HANDLE_DBH_ERR();
     619           0 :         RETURN_FALSE;
     620             : }
     621             : /* }}} */
     622             : 
     623             : /* {{{ proto bool PDO::rollBack()
     624             :    roll back a transaction */
     625          30 : static PHP_METHOD(PDO, rollBack)
     626             : {
     627          30 :         pdo_dbh_t *dbh = Z_PDO_DBH_P(getThis());
     628             : 
     629          30 :         if (zend_parse_parameters_none() == FAILURE) {
     630           0 :                 return;
     631             :         }
     632          30 :         PDO_CONSTRUCT_CHECK;
     633             : 
     634          30 :         if (!dbh->in_txn) {
     635           2 :                 zend_throw_exception_ex(php_pdo_get_exception(), 0, "There is no active transaction");
     636           2 :                 RETURN_FALSE;
     637             :         }
     638             : 
     639          28 :         if (dbh->methods->rollback(dbh)) {
     640          28 :                 dbh->in_txn = 0;
     641          28 :                 RETURN_TRUE;
     642             :         }
     643             : 
     644           0 :         PDO_HANDLE_DBH_ERR();
     645           0 :         RETURN_FALSE;
     646             : }
     647             : /* }}} */
     648             : 
     649             : /* {{{ proto bool PDO::inTransaction()
     650             :    determine if inside a transaction */
     651           5 : static PHP_METHOD(PDO, inTransaction)
     652             : {
     653           5 :         pdo_dbh_t *dbh = Z_PDO_DBH_P(getThis());
     654             : 
     655           5 :         if (zend_parse_parameters_none() == FAILURE) {
     656           0 :                 return;
     657             :         }
     658           5 :         PDO_CONSTRUCT_CHECK;
     659             : 
     660           5 :         if (!dbh->methods->in_transaction) {
     661           0 :                 RETURN_BOOL(dbh->in_txn);
     662             :         }
     663             : 
     664           5 :         RETURN_BOOL(dbh->methods->in_transaction(dbh));
     665             : }
     666             : /* }}} */
     667             : 
     668        3904 : static int pdo_dbh_attribute_set(pdo_dbh_t *dbh, zend_long attr, zval *value) /* {{{ */
     669             : {
     670             :         zend_long lval;
     671             : 
     672             : #define PDO_LONG_PARAM_CHECK \
     673             :         if (Z_TYPE_P(value) != IS_LONG && Z_TYPE_P(value) != IS_STRING && Z_TYPE_P(value) != IS_FALSE && Z_TYPE_P(value) != IS_TRUE) { \
     674             :                 pdo_raise_impl_error(dbh, NULL, "HY000", "attribute value must be an integer"); \
     675             :                 PDO_HANDLE_DBH_ERR(); \
     676             :                 return FAILURE; \
     677             :         } \
     678             : 
     679        3904 :         switch (attr) {
     680             :                 case PDO_ATTR_ERRMODE:
     681        1210 :                         PDO_LONG_PARAM_CHECK;
     682        1201 :                         lval = zval_get_long(value);
     683        1201 :                         switch (lval) {
     684             :                                 case PDO_ERRMODE_SILENT:
     685             :                                 case PDO_ERRMODE_WARNING:
     686             :                                 case PDO_ERRMODE_EXCEPTION:
     687        1200 :                                         dbh->error_mode = lval;
     688        1200 :                                         return SUCCESS;
     689             :                                 default:
     690           1 :                                         pdo_raise_impl_error(dbh, NULL, "HY000", "invalid error mode");
     691           1 :                                         PDO_HANDLE_DBH_ERR();
     692           1 :                                         return FAILURE;
     693             :                         }
     694             :                         return FAILURE;
     695             : 
     696             :                 case PDO_ATTR_CASE:
     697        1134 :                         PDO_LONG_PARAM_CHECK;
     698        1134 :                         lval = zval_get_long(value);
     699        1134 :                         switch (lval) {
     700             :                                 case PDO_CASE_NATURAL:
     701             :                                 case PDO_CASE_UPPER:
     702             :                                 case PDO_CASE_LOWER:
     703        1134 :                                         dbh->desired_case = lval;
     704        1134 :                                         return SUCCESS;
     705             :                                 default:
     706           0 :                                         pdo_raise_impl_error(dbh, NULL, "HY000", "invalid case folding mode");
     707           0 :                                         PDO_HANDLE_DBH_ERR();
     708           0 :                                         return FAILURE;
     709             :                         }
     710             :                         return FAILURE;
     711             : 
     712             :                 case PDO_ATTR_ORACLE_NULLS:
     713          16 :                         PDO_LONG_PARAM_CHECK;
     714           7 :                         dbh->oracle_nulls = zval_get_long(value);
     715           7 :                         return SUCCESS;
     716             : 
     717             :                 case PDO_ATTR_DEFAULT_FETCH_MODE:
     718          22 :                         if (Z_TYPE_P(value) == IS_ARRAY) {
     719             :                                 zval *tmp;
     720           0 :                                 if ((tmp = zend_hash_index_find(Z_ARRVAL_P(value), 0)) != NULL && Z_TYPE_P(tmp) == IS_LONG) {
     721           0 :                                         if (Z_LVAL_P(tmp) == PDO_FETCH_INTO || Z_LVAL_P(tmp) == PDO_FETCH_CLASS) {
     722           0 :                                                 pdo_raise_impl_error(dbh, NULL, "HY000", "FETCH_INTO and FETCH_CLASS are not yet supported as default fetch modes");
     723           0 :                                                 return FAILURE;
     724             :                                         }
     725             :                                 }
     726             :                         } else {
     727          22 :                                 PDO_LONG_PARAM_CHECK;
     728             :                         }
     729          22 :                         lval = zval_get_long(value);
     730          22 :                         if (lval == PDO_FETCH_USE_DEFAULT) {
     731           0 :                                 pdo_raise_impl_error(dbh, NULL, "HY000", "invalid fetch mode type");
     732           0 :                                 return FAILURE;
     733             :                         }
     734          22 :                         dbh->default_fetch_type = lval;
     735          22 :                         return SUCCESS;
     736             : 
     737             :                 case PDO_ATTR_STRINGIFY_FETCHES:
     738        4291 :                         PDO_LONG_PARAM_CHECK;
     739        1095 :                         dbh->stringify = zval_get_long(value) ? 1 : 0;
     740        1095 :                         return SUCCESS;
     741             : 
     742             :                 case PDO_ATTR_STATEMENT_CLASS: {
     743             :                         /* array(string classname, array(mixed ctor_args)) */
     744             :                         zend_class_entry *pce;
     745             :                         zval *item;
     746             : 
     747          40 :                         if (dbh->is_persistent) {
     748           0 :                                 pdo_raise_impl_error(dbh, NULL, "HY000",
     749             :                                         "PDO::ATTR_STATEMENT_CLASS cannot be used with persistent PDO instances"
     750             :                                         );
     751           0 :                                 PDO_HANDLE_DBH_ERR();
     752           0 :                                 return FAILURE;
     753             :                         }
     754          94 :                         if (Z_TYPE_P(value) != IS_ARRAY
     755          18 :                                 || (item = zend_hash_index_find(Z_ARRVAL_P(value), 0)) == NULL
     756             :                                 || Z_TYPE_P(item) != IS_STRING
     757          18 :                                 || (pce = zend_lookup_class(Z_STR_P(item))) == NULL
     758             :                         ) {
     759          24 :                                 pdo_raise_impl_error(dbh, NULL, "HY000",
     760             :                                         "PDO::ATTR_STATEMENT_CLASS requires format array(classname, array(ctor_args)); "
     761             :                                         "the classname must be a string specifying an existing class"
     762             :                                         );
     763          24 :                                 PDO_HANDLE_DBH_ERR();
     764          24 :                                 return FAILURE;
     765             :                         }
     766          16 :                         if (!instanceof_function(pce, pdo_dbstmt_ce)) {
     767           1 :                                 pdo_raise_impl_error(dbh, NULL, "HY000",
     768             :                                         "user-supplied statement class must be derived from PDOStatement");
     769           1 :                                 PDO_HANDLE_DBH_ERR();
     770           1 :                                 return FAILURE;
     771             :                         }
     772          15 :                         if (pce->constructor && !(pce->constructor->common.fn_flags & (ZEND_ACC_PRIVATE|ZEND_ACC_PROTECTED))) {
     773           1 :                                 pdo_raise_impl_error(dbh, NULL, "HY000",
     774             :                                         "user-supplied statement class cannot have a public constructor");
     775           1 :                                 PDO_HANDLE_DBH_ERR();
     776           1 :                                 return FAILURE;
     777             :                         }
     778          14 :                         dbh->def_stmt_ce = pce;
     779          28 :                         if (!Z_ISUNDEF(dbh->def_stmt_ctor_args)) {
     780           4 :                                 zval_ptr_dtor(&dbh->def_stmt_ctor_args);
     781           4 :                                 ZVAL_UNDEF(&dbh->def_stmt_ctor_args);
     782             :                         }
     783          14 :                         if ((item = zend_hash_index_find(Z_ARRVAL_P(value), 1)) != NULL) {
     784          13 :                                 if (Z_TYPE_P(item) != IS_ARRAY) {
     785           0 :                                         pdo_raise_impl_error(dbh, NULL, "HY000",
     786             :                                                 "PDO::ATTR_STATEMENT_CLASS requires format array(classname, array(ctor_args)); "
     787             :                                                 "ctor_args must be an array"
     788             :                                         );
     789           0 :                                         PDO_HANDLE_DBH_ERR();
     790           0 :                                         return FAILURE;
     791             :                                 }
     792          13 :                                 ZVAL_COPY(&dbh->def_stmt_ctor_args, item);
     793             :                         }
     794          14 :                         return SUCCESS;
     795             :                 }
     796             : 
     797             :                 default:
     798             :                         ;
     799             :         }
     800             : 
     801         394 :         if (!dbh->methods->set_attribute) {
     802           0 :                 goto fail;
     803             :         }
     804             : 
     805         394 :         PDO_DBH_CLEAR_ERR();
     806         394 :         if (dbh->methods->set_attribute(dbh, attr, value)) {
     807         321 :                 return SUCCESS;
     808             :         }
     809             : 
     810             : fail:
     811          73 :         if (attr == PDO_ATTR_AUTOCOMMIT) {
     812           0 :                 zend_throw_exception_ex(php_pdo_get_exception(), 0, "The auto-commit mode cannot be changed for this driver");
     813          73 :         } else if (!dbh->methods->set_attribute) {
     814           0 :                 pdo_raise_impl_error(dbh, NULL, "IM001", "driver does not support setting attributes");
     815             :         } else {
     816          73 :                 PDO_HANDLE_DBH_ERR();
     817             :         }
     818          73 :         return FAILURE;
     819             : }
     820             : /* }}} */
     821             : 
     822             : /* {{{ proto bool PDO::setAttribute(long attribute, mixed value)
     823             :    Set an attribute */
     824        3826 : static PHP_METHOD(PDO, setAttribute)
     825             : {
     826        3826 :         pdo_dbh_t *dbh = Z_PDO_DBH_P(getThis());
     827             :         zend_long attr;
     828             :         zval *value;
     829             : 
     830        3826 :         if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "lz", &attr, &value)) {
     831           1 :                 RETURN_FALSE;
     832             :         }
     833             : 
     834        3825 :         PDO_DBH_CLEAR_ERR();
     835        3825 :         PDO_CONSTRUCT_CHECK;
     836             : 
     837        3825 :         if (pdo_dbh_attribute_set(dbh, attr, value) != FAILURE) {
     838        3774 :                 RETURN_TRUE;
     839             :         }
     840          51 :         RETURN_FALSE;
     841             : }
     842             : /* }}} */
     843             : 
     844             : /* {{{ proto mixed PDO::getAttribute(long attribute)
     845             :    Get an attribute */
     846         268 : static PHP_METHOD(PDO, getAttribute)
     847             : {
     848         268 :         pdo_dbh_t *dbh = Z_PDO_DBH_P(getThis());
     849             :         zend_long attr;
     850             : 
     851         268 :         if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "l", &attr)) {
     852           0 :                 RETURN_FALSE;
     853             :         }
     854             : 
     855         268 :         PDO_DBH_CLEAR_ERR();
     856         268 :         PDO_CONSTRUCT_CHECK;
     857             : 
     858             :         /* handle generic PDO-level attributes */
     859         268 :         switch (attr) {
     860             :                 case PDO_ATTR_PERSISTENT:
     861           3 :                         RETURN_BOOL(dbh->is_persistent);
     862             : 
     863             :                 case PDO_ATTR_CASE:
     864           9 :                         RETURN_LONG(dbh->desired_case);
     865             : 
     866             :                 case PDO_ATTR_ORACLE_NULLS:
     867           6 :                         RETURN_LONG(dbh->oracle_nulls);
     868             : 
     869             :                 case PDO_ATTR_ERRMODE:
     870           2 :                         RETURN_LONG(dbh->error_mode);
     871             : 
     872             :                 case PDO_ATTR_DRIVER_NAME:
     873         160 :                         RETURN_STRINGL((char*)dbh->driver->driver_name, dbh->driver->driver_name_len);
     874             : 
     875             :                 case PDO_ATTR_STATEMENT_CLASS:
     876          16 :                         array_init(return_value);
     877          32 :                         add_next_index_str(return_value, zend_string_copy(dbh->def_stmt_ce->name));
     878          32 :                         if (!Z_ISUNDEF(dbh->def_stmt_ctor_args)) {
     879           7 :                                 if (Z_REFCOUNTED(dbh->def_stmt_ctor_args)) Z_ADDREF(dbh->def_stmt_ctor_args);
     880           7 :                                 add_next_index_zval(return_value, &dbh->def_stmt_ctor_args);
     881             :                         }
     882          16 :                         return;
     883             :                 case PDO_ATTR_DEFAULT_FETCH_MODE:
     884           2 :                         RETURN_LONG(dbh->default_fetch_type);
     885             :                 default:
     886             :                         break;
     887             :         }
     888             : 
     889         150 :         if (!dbh->methods->get_attribute) {
     890           0 :                 pdo_raise_impl_error(dbh, NULL, "IM001", "driver does not support getting attributes");
     891           0 :                 RETURN_FALSE;
     892             :         }
     893             : 
     894         150 :         switch (dbh->methods->get_attribute(dbh, attr, return_value)) {
     895             :                 case -1:
     896           0 :                         PDO_HANDLE_DBH_ERR();
     897           0 :                         RETURN_FALSE;
     898             : 
     899             :                 case 0:
     900          27 :                         pdo_raise_impl_error(dbh, NULL, "IM001", "driver does not support that attribute");
     901          27 :                         RETURN_FALSE;
     902             : 
     903             :                 default:
     904         123 :                         return;
     905             :         }
     906             : }
     907             : /* }}} */
     908             : 
     909             : /* {{{ proto long PDO::exec(string query)
     910             :    Execute a query that does not return a row set, returning the number of affected rows */
     911        4735 : static PHP_METHOD(PDO, exec)
     912             : {
     913        4735 :         pdo_dbh_t *dbh = Z_PDO_DBH_P(getThis());
     914             :         char *statement;
     915             :         size_t statement_len;
     916             :         zend_long ret;
     917             : 
     918        4735 :         if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "s", &statement, &statement_len)) {
     919           0 :                 RETURN_FALSE;
     920             :         }
     921             : 
     922        4735 :         if (!statement_len) {
     923           0 :                 pdo_raise_impl_error(dbh, NULL, "HY000",  "trying to execute an empty query");
     924           0 :                 RETURN_FALSE;
     925             :         }
     926        4735 :         PDO_DBH_CLEAR_ERR();
     927        4735 :         PDO_CONSTRUCT_CHECK;
     928        4735 :         ret = dbh->methods->doer(dbh, statement, statement_len);
     929        4735 :         if(ret == -1) {
     930        2511 :                 PDO_HANDLE_DBH_ERR();
     931        2511 :                 RETURN_FALSE;
     932             :         } else {
     933        2224 :                 RETURN_LONG(ret);
     934             :         }
     935             : }
     936             : /* }}} */
     937             : 
     938             : /* {{{ proto string PDO::lastInsertId([string seqname])
     939             :    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. */
     940          14 : static PHP_METHOD(PDO, lastInsertId)
     941             : {
     942          14 :         pdo_dbh_t *dbh = Z_PDO_DBH_P(getThis());
     943          14 :         char *name = NULL;
     944             :         size_t namelen;
     945             : 
     946          14 :         if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "|s!", &name, &namelen)) {
     947           0 :                 RETURN_FALSE;
     948             :         }
     949             : 
     950          14 :         PDO_DBH_CLEAR_ERR();
     951          14 :         PDO_CONSTRUCT_CHECK;
     952          14 :         if (!dbh->methods->last_id) {
     953           0 :                 pdo_raise_impl_error(dbh, NULL, "IM001", "driver does not support lastInsertId()");
     954           0 :                 RETURN_FALSE;
     955             :         } else {
     956             :                 size_t id_len;
     957             :                 char *id;
     958          14 :                 id = dbh->methods->last_id(dbh, name, &id_len);
     959          14 :                 if (!id) {
     960           0 :                         PDO_HANDLE_DBH_ERR();
     961           0 :                         RETURN_FALSE;
     962             :                 } else {
     963             :                         //??? use zend_string ?
     964          28 :                         RETVAL_STRINGL(id, id_len);
     965          14 :                         efree(id);
     966             :                 }
     967             :         }
     968             : }
     969             : /* }}} */
     970             : 
     971             : /* {{{ proto string PDO::errorCode()
     972             :    Fetch the error code associated with the last operation on the database handle */
     973         102 : static PHP_METHOD(PDO, errorCode)
     974             : {
     975         102 :         pdo_dbh_t *dbh = Z_PDO_DBH_P(getThis());
     976             : 
     977         102 :         if (zend_parse_parameters_none() == FAILURE) {
     978           0 :                 return;
     979             :         }
     980         102 :         PDO_CONSTRUCT_CHECK;
     981             : 
     982         102 :         if (dbh->query_stmt) {
     983          22 :                 RETURN_STRING(dbh->query_stmt->error_code);
     984             :         }
     985             : 
     986          91 :         if (dbh->error_code[0] == '\0') {
     987           0 :                 RETURN_NULL();
     988             :         }
     989             : 
     990             :         /**
     991             :          * Making sure that we fallback to the default implementation
     992             :          * if the dbh->error_code is not null.
     993             :          */
     994         182 :         RETURN_STRING(dbh->error_code);
     995             : }
     996             : /* }}} */
     997             : 
     998             : /* {{{ proto int PDO::errorInfo()
     999             :    Fetch extended error information associated with the last operation on the database handle */
    1000          88 : static PHP_METHOD(PDO, errorInfo)
    1001             : {
    1002             :         int error_count;
    1003          88 :         int error_count_diff     = 0;
    1004          88 :         int error_expected_count = 3;
    1005             : 
    1006          88 :         pdo_dbh_t *dbh = Z_PDO_DBH_P(getThis());
    1007             : 
    1008          88 :         if (zend_parse_parameters_none() == FAILURE) {
    1009           0 :                 return;
    1010             :         }
    1011             : 
    1012          88 :         PDO_CONSTRUCT_CHECK;
    1013             : 
    1014          88 :         array_init(return_value);
    1015             : 
    1016          88 :         if (dbh->query_stmt) {
    1017          22 :                 add_next_index_string(return_value, dbh->query_stmt->error_code);
    1018          22 :                 if(!strncmp(dbh->query_stmt->error_code, PDO_ERR_NONE, sizeof(PDO_ERR_NONE))) goto fill_array;
    1019             :         } else {
    1020          66 :                 add_next_index_string(return_value, dbh->error_code);
    1021          66 :                 if(!strncmp(dbh->error_code, PDO_ERR_NONE, sizeof(PDO_ERR_NONE))) goto fill_array;
    1022             :         }
    1023             : 
    1024          62 :         if (dbh->methods->fetch_err) {
    1025          62 :                 dbh->methods->fetch_err(dbh, dbh->query_stmt, return_value);
    1026             :         }
    1027             : 
    1028             : fill_array:
    1029             :         /**
    1030             :          * In order to be consistent, we have to make sure we add the good amount
    1031             :          * of nulls depending on the current number of elements. We make a simple
    1032             :          * difference and add the needed elements
    1033             :          */
    1034          88 :         error_count = zend_hash_num_elements(Z_ARRVAL_P(return_value));
    1035             : 
    1036          88 :         if (error_expected_count > error_count) {
    1037             :                 int current_index;
    1038             : 
    1039          28 :                 error_count_diff = error_expected_count - error_count;
    1040          84 :                 for (current_index = 0; current_index < error_count_diff; current_index++) {
    1041          56 :                         add_next_index_null(return_value);
    1042             :                 }
    1043             :         }
    1044             : }
    1045             : /* }}} */
    1046             : 
    1047             : /* {{{ proto object PDO::query(string sql [, PDOStatement::setFetchMode() args])
    1048             :    Prepare and execute $sql; returns the statement object for iteration */
    1049         893 : static PHP_METHOD(PDO, query)
    1050             : {
    1051             :         pdo_stmt_t *stmt;
    1052             :         char *statement;
    1053             :         size_t statement_len;
    1054         893 :         pdo_dbh_object_t *dbh_obj = Z_PDO_OBJECT_P(getThis());
    1055         893 :         pdo_dbh_t *dbh = dbh_obj->inner;
    1056             : 
    1057             :         /* Return a meaningful error when no parameters were passed */
    1058         893 :         if (!ZEND_NUM_ARGS()) {
    1059           6 :                 zend_parse_parameters(0, "z|z", NULL, NULL);
    1060           6 :                 RETURN_FALSE;
    1061             :         }
    1062             : 
    1063         887 :         if (FAILURE == zend_parse_parameters(1, "s", &statement,
    1064             :                         &statement_len)) {
    1065           0 :                 RETURN_FALSE;
    1066             :         }
    1067             : 
    1068         887 :         PDO_DBH_CLEAR_ERR();
    1069         887 :         PDO_CONSTRUCT_CHECK;
    1070             : 
    1071         887 :         if (!pdo_stmt_instantiate(dbh, return_value, dbh->def_stmt_ce, &dbh->def_stmt_ctor_args)) {
    1072           1 :                 if (EXPECTED(!EG(exception))) {
    1073           0 :                         pdo_raise_impl_error(dbh, NULL, "HY000", "failed to instantiate user supplied statement class");
    1074             :                 }
    1075           1 :                 return;
    1076             :         }
    1077         886 :         stmt = Z_PDO_STMT_P(return_value);
    1078             : 
    1079             :         /* unconditionally keep this for later reference */
    1080         886 :         stmt->query_string = estrndup(statement, statement_len);
    1081         886 :         stmt->query_stringlen = statement_len;
    1082             : 
    1083         886 :         stmt->default_fetch_type = dbh->default_fetch_type;
    1084         886 :         stmt->active_query_string = stmt->query_string;
    1085         886 :         stmt->active_query_stringlen = statement_len;
    1086         886 :         stmt->dbh = dbh;
    1087             :         /* give it a reference to me */
    1088         886 :         ZVAL_OBJ(&stmt->database_object_handle, &dbh_obj->std);
    1089         886 :         Z_ADDREF(stmt->database_object_handle);
    1090             :         /* we haven't created a lazy object yet */
    1091         886 :         ZVAL_UNDEF(&stmt->lazy_object_ref);
    1092             : 
    1093         886 :         if (dbh->methods->preparer(dbh, statement, statement_len, stmt, NULL)) {
    1094         876 :                 PDO_STMT_CLEAR_ERR();
    1095         876 :                 if (ZEND_NUM_ARGS() == 1 || SUCCESS == pdo_stmt_setup_fetch_mode(INTERNAL_FUNCTION_PARAM_PASSTHRU, stmt, 1)) {
    1096             : 
    1097             :                         /* now execute the statement */
    1098         840 :                         PDO_STMT_CLEAR_ERR();
    1099         840 :                         if (stmt->methods->executer(stmt)) {
    1100         810 :                                 int ret = 1;
    1101         810 :                                 if (!stmt->executed) {
    1102         810 :                                         if (stmt->dbh->alloc_own_columns) {
    1103         810 :                                                 ret = pdo_stmt_describe_columns(stmt);
    1104             :                                         }
    1105         810 :                                         stmt->executed = 1;
    1106             :                                 }
    1107         810 :                                 if (ret) {
    1108         810 :                                         pdo_stmt_construct(execute_data, stmt, return_value, dbh->def_stmt_ce, &dbh->def_stmt_ctor_args);
    1109         810 :                                         return;
    1110             :                                 }
    1111             :                         }
    1112             :                 }
    1113             :                 /* something broke */
    1114          66 :                 dbh->query_stmt = stmt;
    1115          66 :                 ZVAL_COPY_VALUE(&dbh->query_stmt_zval, return_value);
    1116          66 :                 Z_DELREF(stmt->database_object_handle);
    1117          66 :                 ZVAL_UNDEF(&stmt->database_object_handle);
    1118          66 :                 PDO_HANDLE_STMT_ERR();
    1119             :         } else {
    1120          10 :                 PDO_HANDLE_DBH_ERR();
    1121          10 :                 zval_ptr_dtor(return_value);
    1122             :         }
    1123             : 
    1124          76 :         RETURN_FALSE;
    1125             : }
    1126             : /* }}} */
    1127             : 
    1128             : /* {{{ proto string PDO::quote(string string [, int paramtype])
    1129             :    quotes string for use in a query.  The optional paramtype acts as a hint for drivers that have alternate quoting styles.  The default value is PDO_PARAM_STR */
    1130          33 : static PHP_METHOD(PDO, quote)
    1131             : {
    1132          33 :         pdo_dbh_t *dbh = Z_PDO_DBH_P(getThis());
    1133             :         char *str;
    1134             :         size_t str_len;
    1135          33 :         zend_long paramtype = PDO_PARAM_STR;
    1136             :         char *qstr;
    1137             :         size_t qlen;
    1138             : 
    1139          33 :         if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &str, &str_len, &paramtype)) {
    1140           0 :                 RETURN_FALSE;
    1141             :         }
    1142             : 
    1143          33 :         PDO_DBH_CLEAR_ERR();
    1144          33 :         PDO_CONSTRUCT_CHECK;
    1145          33 :         if (!dbh->methods->quoter) {
    1146           0 :                 pdo_raise_impl_error(dbh, NULL, "IM001", "driver does not support quoting");
    1147           0 :                 RETURN_FALSE;
    1148             :         }
    1149             : 
    1150          33 :         if (dbh->methods->quoter(dbh, str, str_len, &qstr, &qlen, paramtype)) {
    1151          64 :                 RETVAL_STRINGL(qstr, qlen);
    1152          32 :                 efree(qstr);
    1153          32 :                 return;
    1154             :         }
    1155           1 :         PDO_HANDLE_DBH_ERR();
    1156           1 :         RETURN_FALSE;
    1157             : }
    1158             : /* }}} */
    1159             : 
    1160             : /* {{{ proto int PDO::__wakeup()
    1161             :    Prevents use of a PDO instance that has been unserialized */
    1162           0 : static PHP_METHOD(PDO, __wakeup)
    1163             : {
    1164           0 :         zend_throw_exception_ex(php_pdo_get_exception(), 0, "You cannot serialize or unserialize PDO instances");
    1165           0 : }
    1166             : /* }}} */
    1167             : 
    1168             : /* {{{ proto int PDO::__sleep()
    1169             :    Prevents serialization of a PDO instance */
    1170           6 : static PHP_METHOD(PDO, __sleep)
    1171             : {
    1172           6 :         zend_throw_exception_ex(php_pdo_get_exception(), 0, "You cannot serialize or unserialize PDO instances");
    1173           6 : }
    1174             : /* }}} */
    1175             : 
    1176             : /* {{{ proto array PDO::getAvailableDrivers()
    1177             :    Return array of available PDO drivers */
    1178           1 : static PHP_METHOD(PDO, getAvailableDrivers)
    1179             : {
    1180             :         pdo_driver_t *pdriver;
    1181             : 
    1182           1 :         if (zend_parse_parameters_none() == FAILURE) {
    1183           0 :                 return;
    1184             :         }
    1185             : 
    1186           1 :         array_init(return_value);
    1187             : 
    1188          15 :         ZEND_HASH_FOREACH_PTR(&pdo_driver_hash, pdriver) {
    1189           7 :                 add_next_index_stringl(return_value, (char*)pdriver->driver_name, pdriver->driver_name_len);
    1190             :         } ZEND_HASH_FOREACH_END();
    1191             : }
    1192             : /* }}} */
    1193             : 
    1194             : /* {{{ arginfo */
    1195             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pdo___construct, 0, 0, 1)
    1196             :         ZEND_ARG_INFO(0, dsn)
    1197             :         ZEND_ARG_INFO(0, username)
    1198             :         ZEND_ARG_INFO(0, passwd)
    1199             :         ZEND_ARG_INFO(0, options) /* array */
    1200             : ZEND_END_ARG_INFO()
    1201             : 
    1202             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pdo_prepare, 0, 0, 1)
    1203             :         ZEND_ARG_INFO(0, statement)
    1204             :         ZEND_ARG_INFO(0, options) /* array */
    1205             : ZEND_END_ARG_INFO()
    1206             : 
    1207             : ZEND_BEGIN_ARG_INFO(arginfo_pdo_setattribute, 0)
    1208             :         ZEND_ARG_INFO(0, attribute)
    1209             :         ZEND_ARG_INFO(0, value)
    1210             : ZEND_END_ARG_INFO()
    1211             : 
    1212             : ZEND_BEGIN_ARG_INFO(arginfo_pdo_getattribute, 0)
    1213             :         ZEND_ARG_INFO(0, attribute)
    1214             : ZEND_END_ARG_INFO()
    1215             : 
    1216             : ZEND_BEGIN_ARG_INFO(arginfo_pdo_exec, 0)
    1217             :         ZEND_ARG_INFO(0, query)
    1218             : ZEND_END_ARG_INFO()
    1219             : 
    1220             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pdo_lastinsertid, 0, 0, 0)
    1221             :         ZEND_ARG_INFO(0, seqname)
    1222             : ZEND_END_ARG_INFO()
    1223             : 
    1224             : ZEND_BEGIN_ARG_INFO_EX(arginfo_pdo_quote, 0, 0, 1)
    1225             :         ZEND_ARG_INFO(0, string)
    1226             :         ZEND_ARG_INFO(0, paramtype)
    1227             : ZEND_END_ARG_INFO()
    1228             : 
    1229             : ZEND_BEGIN_ARG_INFO(arginfo_pdo__void, 0)
    1230             : ZEND_END_ARG_INFO()
    1231             : /* }}} */
    1232             : 
    1233             : const zend_function_entry pdo_dbh_functions[] = /* {{{ */ {
    1234             :         ZEND_MALIAS(PDO, __construct, dbh_constructor,  arginfo_pdo___construct,        ZEND_ACC_PUBLIC)
    1235             :         PHP_ME(PDO, prepare,                            arginfo_pdo_prepare,            ZEND_ACC_PUBLIC)
    1236             :         PHP_ME(PDO, beginTransaction,       arginfo_pdo__void,         ZEND_ACC_PUBLIC)
    1237             :         PHP_ME(PDO, commit,                 arginfo_pdo__void,         ZEND_ACC_PUBLIC)
    1238             :         PHP_ME(PDO, rollBack,               arginfo_pdo__void,         ZEND_ACC_PUBLIC)
    1239             :         PHP_ME(PDO, inTransaction,          arginfo_pdo__void,         ZEND_ACC_PUBLIC)
    1240             :         PHP_ME(PDO, setAttribute,       arginfo_pdo_setattribute,       ZEND_ACC_PUBLIC)
    1241             :         PHP_ME(PDO, exec,                       arginfo_pdo_exec,               ZEND_ACC_PUBLIC)
    1242             :         PHP_ME(PDO, query,                      NULL,                                   ZEND_ACC_PUBLIC)
    1243             :         PHP_ME(PDO, lastInsertId,       arginfo_pdo_lastinsertid,       ZEND_ACC_PUBLIC)
    1244             :         PHP_ME(PDO, errorCode,              arginfo_pdo__void,         ZEND_ACC_PUBLIC)
    1245             :         PHP_ME(PDO, errorInfo,              arginfo_pdo__void,         ZEND_ACC_PUBLIC)
    1246             :         PHP_ME(PDO, getAttribute,       arginfo_pdo_getattribute,       ZEND_ACC_PUBLIC)
    1247             :         PHP_ME(PDO, quote,                      arginfo_pdo_quote,              ZEND_ACC_PUBLIC)
    1248             :         PHP_ME(PDO, __wakeup,               arginfo_pdo__void,         ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
    1249             :         PHP_ME(PDO, __sleep,                arginfo_pdo__void,         ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
    1250             :         PHP_ME(PDO, getAvailableDrivers,    arginfo_pdo__void,         ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
    1251             :         {NULL, NULL, NULL}
    1252             : };
    1253             : /* }}} */
    1254             : 
    1255          78 : static void cls_method_dtor(zval *el) /* {{{ */ {
    1256          78 :         zend_function *func = (zend_function*)Z_PTR_P(el);
    1257          78 :         if (func->common.function_name) {
    1258          78 :                 zend_string_release(func->common.function_name);
    1259             :         }
    1260          78 :         efree(func);
    1261          78 : }
    1262             : /* }}} */
    1263             : 
    1264           3 : static void cls_method_pdtor(zval *el) /* {{{ */ {
    1265           3 :         zend_function *func = (zend_function*)Z_PTR_P(el);
    1266           3 :         if (func->common.function_name) {
    1267           3 :                 zend_string_release(func->common.function_name);
    1268             :         }
    1269           3 :         pefree(func, 1);
    1270           3 : }
    1271             : /* }}} */
    1272             : 
    1273             : /* {{{ overloaded object handlers for PDO class */
    1274          20 : int pdo_hash_methods(pdo_dbh_object_t *dbh_obj, int kind)
    1275             : {
    1276             :         const zend_function_entry *funcs;
    1277             :         zend_internal_function func;
    1278             :         size_t namelen;
    1279             :         char *lc_name;
    1280          20 :         pdo_dbh_t *dbh = dbh_obj->inner;
    1281             : 
    1282          20 :         if (!dbh || !dbh->methods || !dbh->methods->get_driver_methods) {
    1283           0 :                 return 0;
    1284             :         }
    1285          20 :         funcs = dbh->methods->get_driver_methods(dbh, kind);
    1286          20 :         if (!funcs) {
    1287           1 :                 return 0;
    1288             :         }
    1289             : 
    1290          19 :         if (!(dbh->cls_methods[kind] = pemalloc(sizeof(HashTable), dbh->is_persistent))) {
    1291           0 :                 php_error_docref(NULL, E_ERROR, "out of memory while allocating PDO methods.");
    1292             :         }
    1293          19 :         zend_hash_init_ex(dbh->cls_methods[kind], 8, NULL,
    1294             :                         dbh->is_persistent? cls_method_pdtor : cls_method_dtor, dbh->is_persistent, 0);
    1295             : 
    1296          19 :         memset(&func, 0, sizeof(func));
    1297             : 
    1298         119 :         while (funcs->fname) {
    1299          81 :                 func.type = ZEND_INTERNAL_FUNCTION;
    1300          81 :                 func.handler = funcs->handler;
    1301         162 :                 func.function_name = zend_string_init(funcs->fname, strlen(funcs->fname), dbh->is_persistent);
    1302          81 :                 func.scope = dbh_obj->std.ce;
    1303          81 :                 func.prototype = NULL;
    1304          81 :                 if (funcs->flags) {
    1305          81 :                         func.fn_flags = funcs->flags | ZEND_ACC_NEVER_CACHE;
    1306             :                 } else {
    1307           0 :                         func.fn_flags = ZEND_ACC_PUBLIC | ZEND_ACC_NEVER_CACHE;
    1308             :                 }
    1309          81 :                 if (funcs->arg_info) {
    1310           0 :                         zend_internal_function_info *info = (zend_internal_function_info*)funcs->arg_info;
    1311             : 
    1312           0 :                         func.arg_info = (zend_internal_arg_info*)funcs->arg_info + 1;
    1313           0 :                         func.num_args = funcs->num_args;
    1314           0 :                         if (info->required_num_args == -1) {
    1315           0 :                                 func.required_num_args = funcs->num_args;
    1316             :                         } else {
    1317           0 :                                 func.required_num_args = info->required_num_args;
    1318             :                         }
    1319           0 :                         if (info->return_reference) {
    1320           0 :                                 func.fn_flags |= ZEND_ACC_RETURN_REFERENCE;
    1321             :                         }
    1322           0 :                         if (funcs->arg_info[funcs->num_args].is_variadic) {
    1323           0 :                                 func.fn_flags |= ZEND_ACC_VARIADIC;
    1324             :                                 /* Don't count the variadic argument */
    1325           0 :                                 func.num_args--;
    1326             :                         }
    1327             :                 } else {
    1328          81 :                         func.arg_info = NULL;
    1329          81 :                         func.num_args = 0;
    1330          81 :                         func.required_num_args = 0;
    1331             :                 }
    1332          81 :                 zend_set_function_arg_flags((zend_function*)&func);
    1333          81 :                 namelen = strlen(funcs->fname);
    1334          81 :                 lc_name = emalloc(namelen+1);
    1335          81 :                 zend_str_tolower_copy(lc_name, funcs->fname, namelen);
    1336          81 :                 zend_hash_str_add_mem(dbh->cls_methods[kind], lc_name, namelen, &func, sizeof(func));
    1337          81 :                 efree(lc_name);
    1338          81 :                 funcs++;
    1339             :         }
    1340             : 
    1341          19 :         return 1;
    1342             : }
    1343             : 
    1344        7352 : static union _zend_function *dbh_method_get(zend_object **object, zend_string *method_name, const zval *key)
    1345             : {
    1346        7352 :         zend_function *fbc = NULL;
    1347        7352 :         pdo_dbh_object_t *dbh_obj = php_pdo_dbh_fetch_object(*object);
    1348             :         zend_string *lc_method_name;
    1349             : 
    1350       14704 :         lc_method_name = zend_string_init(ZSTR_VAL(method_name), ZSTR_LEN(method_name), 0);
    1351        7352 :         zend_str_tolower_copy(ZSTR_VAL(lc_method_name), ZSTR_VAL(method_name), ZSTR_LEN(method_name));
    1352             : 
    1353        7352 :         if ((fbc = std_object_handlers.get_method(object, method_name, key)) == NULL) {
    1354             :                 /* not a pre-defined method, nor a user-defined method; check
    1355             :                  * the driver specific methods */
    1356          48 :                 if (!dbh_obj->inner->cls_methods[PDO_DBH_DRIVER_METHOD_KIND_DBH]) {
    1357          38 :                         if (!pdo_hash_methods(dbh_obj,
    1358             :                                 PDO_DBH_DRIVER_METHOD_KIND_DBH)
    1359          19 :                                 || !dbh_obj->inner->cls_methods[PDO_DBH_DRIVER_METHOD_KIND_DBH]) {
    1360             :                                 goto out;
    1361             :                         }
    1362             :                 }
    1363             : 
    1364          96 :                 fbc = zend_hash_find_ptr(dbh_obj->inner->cls_methods[PDO_DBH_DRIVER_METHOD_KIND_DBH], lc_method_name);
    1365             :         }
    1366             : 
    1367             : out:
    1368             :         zend_string_release(lc_method_name);
    1369        7352 :         return fbc;
    1370             : }
    1371             : 
    1372           0 : static int dbh_compare(zval *object1, zval *object2)
    1373             : {
    1374           0 :         return -1;
    1375             : }
    1376             : 
    1377           0 : static HashTable *dbh_get_gc(zval *object, zval **gc_data, int *gc_count)
    1378             : {
    1379           0 :         pdo_dbh_t *dbh = Z_PDO_DBH_P(object);
    1380           0 :         *gc_data = &dbh->def_stmt_ctor_args;
    1381           0 :         *gc_count = 1;
    1382           0 :         return zend_std_get_properties(object);
    1383             : }
    1384             : 
    1385             : static zend_object_handlers pdo_dbh_object_handlers;
    1386             : static void pdo_dbh_free_storage(zend_object *std);
    1387             : 
    1388       22587 : void pdo_dbh_init(void)
    1389             : {
    1390             :         zend_class_entry ce;
    1391             : 
    1392       22587 :         INIT_CLASS_ENTRY(ce, "PDO", pdo_dbh_functions);
    1393       22587 :         pdo_dbh_ce = zend_register_internal_class(&ce);
    1394       22587 :         pdo_dbh_ce->create_object = pdo_dbh_new;
    1395             : 
    1396       22587 :         memcpy(&pdo_dbh_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
    1397       22587 :         pdo_dbh_object_handlers.offset = XtOffsetOf(pdo_dbh_object_t, std);
    1398       22587 :         pdo_dbh_object_handlers.dtor_obj = zend_objects_destroy_object;
    1399       22587 :         pdo_dbh_object_handlers.free_obj = pdo_dbh_free_storage;
    1400       22587 :         pdo_dbh_object_handlers.get_method = dbh_method_get;
    1401       22587 :         pdo_dbh_object_handlers.compare_objects = dbh_compare;
    1402       22587 :         pdo_dbh_object_handlers.get_gc = dbh_get_gc;
    1403             : 
    1404       22587 :         REGISTER_PDO_CLASS_CONST_LONG("PARAM_BOOL", (zend_long)PDO_PARAM_BOOL);
    1405       22587 :         REGISTER_PDO_CLASS_CONST_LONG("PARAM_NULL", (zend_long)PDO_PARAM_NULL);
    1406       22587 :         REGISTER_PDO_CLASS_CONST_LONG("PARAM_INT",  (zend_long)PDO_PARAM_INT);
    1407       22587 :         REGISTER_PDO_CLASS_CONST_LONG("PARAM_STR",  (zend_long)PDO_PARAM_STR);
    1408       22587 :         REGISTER_PDO_CLASS_CONST_LONG("PARAM_LOB",  (zend_long)PDO_PARAM_LOB);
    1409       22587 :         REGISTER_PDO_CLASS_CONST_LONG("PARAM_STMT", (zend_long)PDO_PARAM_STMT);
    1410       22587 :         REGISTER_PDO_CLASS_CONST_LONG("PARAM_INPUT_OUTPUT", (zend_long)PDO_PARAM_INPUT_OUTPUT);
    1411             : 
    1412       22587 :         REGISTER_PDO_CLASS_CONST_LONG("PARAM_EVT_ALLOC",              (zend_long)PDO_PARAM_EVT_ALLOC);
    1413       22587 :         REGISTER_PDO_CLASS_CONST_LONG("PARAM_EVT_FREE",                       (zend_long)PDO_PARAM_EVT_FREE);
    1414       22587 :         REGISTER_PDO_CLASS_CONST_LONG("PARAM_EVT_EXEC_PRE",           (zend_long)PDO_PARAM_EVT_EXEC_PRE);
    1415       22587 :         REGISTER_PDO_CLASS_CONST_LONG("PARAM_EVT_EXEC_POST",  (zend_long)PDO_PARAM_EVT_EXEC_POST);
    1416       22587 :         REGISTER_PDO_CLASS_CONST_LONG("PARAM_EVT_FETCH_PRE",  (zend_long)PDO_PARAM_EVT_FETCH_PRE);
    1417       22587 :         REGISTER_PDO_CLASS_CONST_LONG("PARAM_EVT_FETCH_POST", (zend_long)PDO_PARAM_EVT_FETCH_POST);
    1418       22587 :         REGISTER_PDO_CLASS_CONST_LONG("PARAM_EVT_NORMALIZE",  (zend_long)PDO_PARAM_EVT_NORMALIZE);
    1419             : 
    1420       22587 :         REGISTER_PDO_CLASS_CONST_LONG("FETCH_LAZY", (zend_long)PDO_FETCH_LAZY);
    1421       22587 :         REGISTER_PDO_CLASS_CONST_LONG("FETCH_ASSOC", (zend_long)PDO_FETCH_ASSOC);
    1422       22587 :         REGISTER_PDO_CLASS_CONST_LONG("FETCH_NUM",  (zend_long)PDO_FETCH_NUM);
    1423       22587 :         REGISTER_PDO_CLASS_CONST_LONG("FETCH_BOTH", (zend_long)PDO_FETCH_BOTH);
    1424       22587 :         REGISTER_PDO_CLASS_CONST_LONG("FETCH_OBJ",  (zend_long)PDO_FETCH_OBJ);
    1425       22587 :         REGISTER_PDO_CLASS_CONST_LONG("FETCH_BOUND", (zend_long)PDO_FETCH_BOUND);
    1426       22587 :         REGISTER_PDO_CLASS_CONST_LONG("FETCH_COLUMN", (zend_long)PDO_FETCH_COLUMN);
    1427       22587 :         REGISTER_PDO_CLASS_CONST_LONG("FETCH_CLASS", (zend_long)PDO_FETCH_CLASS);
    1428       22587 :         REGISTER_PDO_CLASS_CONST_LONG("FETCH_INTO", (zend_long)PDO_FETCH_INTO);
    1429       22587 :         REGISTER_PDO_CLASS_CONST_LONG("FETCH_FUNC", (zend_long)PDO_FETCH_FUNC);
    1430       22587 :         REGISTER_PDO_CLASS_CONST_LONG("FETCH_GROUP", (zend_long)PDO_FETCH_GROUP);
    1431       22587 :         REGISTER_PDO_CLASS_CONST_LONG("FETCH_UNIQUE", (zend_long)PDO_FETCH_UNIQUE);
    1432       22587 :         REGISTER_PDO_CLASS_CONST_LONG("FETCH_KEY_PAIR", (zend_long)PDO_FETCH_KEY_PAIR);
    1433       22587 :         REGISTER_PDO_CLASS_CONST_LONG("FETCH_CLASSTYPE", (zend_long)PDO_FETCH_CLASSTYPE);
    1434             : 
    1435       22587 :         REGISTER_PDO_CLASS_CONST_LONG("FETCH_SERIALIZE",(zend_long)PDO_FETCH_SERIALIZE);
    1436       22587 :         REGISTER_PDO_CLASS_CONST_LONG("FETCH_PROPS_LATE", (zend_long)PDO_FETCH_PROPS_LATE);
    1437       22587 :         REGISTER_PDO_CLASS_CONST_LONG("FETCH_NAMED", (zend_long)PDO_FETCH_NAMED);
    1438             : 
    1439       22587 :         REGISTER_PDO_CLASS_CONST_LONG("ATTR_AUTOCOMMIT",      (zend_long)PDO_ATTR_AUTOCOMMIT);
    1440       22587 :         REGISTER_PDO_CLASS_CONST_LONG("ATTR_PREFETCH",                (zend_long)PDO_ATTR_PREFETCH);
    1441       22587 :         REGISTER_PDO_CLASS_CONST_LONG("ATTR_TIMEOUT",                 (zend_long)PDO_ATTR_TIMEOUT);
    1442       22587 :         REGISTER_PDO_CLASS_CONST_LONG("ATTR_ERRMODE",                 (zend_long)PDO_ATTR_ERRMODE);
    1443       22587 :         REGISTER_PDO_CLASS_CONST_LONG("ATTR_SERVER_VERSION",  (zend_long)PDO_ATTR_SERVER_VERSION);
    1444       22587 :         REGISTER_PDO_CLASS_CONST_LONG("ATTR_CLIENT_VERSION",  (zend_long)PDO_ATTR_CLIENT_VERSION);
    1445       22587 :         REGISTER_PDO_CLASS_CONST_LONG("ATTR_SERVER_INFO",             (zend_long)PDO_ATTR_SERVER_INFO);
    1446       22587 :         REGISTER_PDO_CLASS_CONST_LONG("ATTR_CONNECTION_STATUS",       (zend_long)PDO_ATTR_CONNECTION_STATUS);
    1447       22587 :         REGISTER_PDO_CLASS_CONST_LONG("ATTR_CASE",                    (zend_long)PDO_ATTR_CASE);
    1448       22587 :         REGISTER_PDO_CLASS_CONST_LONG("ATTR_CURSOR_NAME",     (zend_long)PDO_ATTR_CURSOR_NAME);
    1449       22587 :         REGISTER_PDO_CLASS_CONST_LONG("ATTR_CURSOR",          (zend_long)PDO_ATTR_CURSOR);
    1450       22587 :         REGISTER_PDO_CLASS_CONST_LONG("ATTR_ORACLE_NULLS",    (zend_long)PDO_ATTR_ORACLE_NULLS);
    1451       22587 :         REGISTER_PDO_CLASS_CONST_LONG("ATTR_PERSISTENT",      (zend_long)PDO_ATTR_PERSISTENT);
    1452       22587 :         REGISTER_PDO_CLASS_CONST_LONG("ATTR_STATEMENT_CLASS",         (zend_long)PDO_ATTR_STATEMENT_CLASS);
    1453       22587 :         REGISTER_PDO_CLASS_CONST_LONG("ATTR_FETCH_TABLE_NAMES",               (zend_long)PDO_ATTR_FETCH_TABLE_NAMES);
    1454       22587 :         REGISTER_PDO_CLASS_CONST_LONG("ATTR_FETCH_CATALOG_NAMES",             (zend_long)PDO_ATTR_FETCH_CATALOG_NAMES);
    1455       22587 :         REGISTER_PDO_CLASS_CONST_LONG("ATTR_DRIVER_NAME",             (zend_long)PDO_ATTR_DRIVER_NAME);
    1456       22587 :         REGISTER_PDO_CLASS_CONST_LONG("ATTR_STRINGIFY_FETCHES", (zend_long)PDO_ATTR_STRINGIFY_FETCHES);
    1457       22587 :         REGISTER_PDO_CLASS_CONST_LONG("ATTR_MAX_COLUMN_LEN", (zend_long)PDO_ATTR_MAX_COLUMN_LEN);
    1458       22587 :         REGISTER_PDO_CLASS_CONST_LONG("ATTR_EMULATE_PREPARES", (zend_long)PDO_ATTR_EMULATE_PREPARES);
    1459       22587 :         REGISTER_PDO_CLASS_CONST_LONG("ATTR_DEFAULT_FETCH_MODE", (zend_long)PDO_ATTR_DEFAULT_FETCH_MODE);
    1460             : 
    1461       22587 :         REGISTER_PDO_CLASS_CONST_LONG("ERRMODE_SILENT",       (zend_long)PDO_ERRMODE_SILENT);
    1462       22587 :         REGISTER_PDO_CLASS_CONST_LONG("ERRMODE_WARNING",      (zend_long)PDO_ERRMODE_WARNING);
    1463       22587 :         REGISTER_PDO_CLASS_CONST_LONG("ERRMODE_EXCEPTION",    (zend_long)PDO_ERRMODE_EXCEPTION);
    1464             : 
    1465       22587 :         REGISTER_PDO_CLASS_CONST_LONG("CASE_NATURAL", (zend_long)PDO_CASE_NATURAL);
    1466       22587 :         REGISTER_PDO_CLASS_CONST_LONG("CASE_LOWER",   (zend_long)PDO_CASE_LOWER);
    1467       22587 :         REGISTER_PDO_CLASS_CONST_LONG("CASE_UPPER",   (zend_long)PDO_CASE_UPPER);
    1468             : 
    1469       22587 :         REGISTER_PDO_CLASS_CONST_LONG("NULL_NATURAL", (zend_long)PDO_NULL_NATURAL);
    1470       22587 :         REGISTER_PDO_CLASS_CONST_LONG("NULL_EMPTY_STRING",    (zend_long)PDO_NULL_EMPTY_STRING);
    1471       22587 :         REGISTER_PDO_CLASS_CONST_LONG("NULL_TO_STRING",       (zend_long)PDO_NULL_TO_STRING);
    1472             : 
    1473       22587 :         REGISTER_PDO_CLASS_CONST_STRING("ERR_NONE",   PDO_ERR_NONE);
    1474             : 
    1475       22587 :         REGISTER_PDO_CLASS_CONST_LONG("FETCH_ORI_NEXT", (zend_long)PDO_FETCH_ORI_NEXT);
    1476       22587 :         REGISTER_PDO_CLASS_CONST_LONG("FETCH_ORI_PRIOR", (zend_long)PDO_FETCH_ORI_PRIOR);
    1477       22587 :         REGISTER_PDO_CLASS_CONST_LONG("FETCH_ORI_FIRST", (zend_long)PDO_FETCH_ORI_FIRST);
    1478       22587 :         REGISTER_PDO_CLASS_CONST_LONG("FETCH_ORI_LAST", (zend_long)PDO_FETCH_ORI_LAST);
    1479       22587 :         REGISTER_PDO_CLASS_CONST_LONG("FETCH_ORI_ABS", (zend_long)PDO_FETCH_ORI_ABS);
    1480       22587 :         REGISTER_PDO_CLASS_CONST_LONG("FETCH_ORI_REL", (zend_long)PDO_FETCH_ORI_REL);
    1481             : 
    1482       22587 :         REGISTER_PDO_CLASS_CONST_LONG("CURSOR_FWDONLY", (zend_long)PDO_CURSOR_FWDONLY);
    1483       22587 :         REGISTER_PDO_CLASS_CONST_LONG("CURSOR_SCROLL", (zend_long)PDO_CURSOR_SCROLL);
    1484             : 
    1485             : #if 0
    1486             :         REGISTER_PDO_CLASS_CONST_LONG("ERR_CANT_MAP",                 (zend_long)PDO_ERR_CANT_MAP);
    1487             :         REGISTER_PDO_CLASS_CONST_LONG("ERR_SYNTAX",           (zend_long)PDO_ERR_SYNTAX);
    1488             :         REGISTER_PDO_CLASS_CONST_LONG("ERR_CONSTRAINT",       (zend_long)PDO_ERR_CONSTRAINT);
    1489             :         REGISTER_PDO_CLASS_CONST_LONG("ERR_NOT_FOUND",                (zend_long)PDO_ERR_NOT_FOUND);
    1490             :         REGISTER_PDO_CLASS_CONST_LONG("ERR_ALREADY_EXISTS",   (zend_long)PDO_ERR_ALREADY_EXISTS);
    1491             :         REGISTER_PDO_CLASS_CONST_LONG("ERR_NOT_IMPLEMENTED",  (zend_long)PDO_ERR_NOT_IMPLEMENTED);
    1492             :         REGISTER_PDO_CLASS_CONST_LONG("ERR_MISMATCH",                 (zend_long)PDO_ERR_MISMATCH);
    1493             :         REGISTER_PDO_CLASS_CONST_LONG("ERR_TRUNCATED",                (zend_long)PDO_ERR_TRUNCATED);
    1494             :         REGISTER_PDO_CLASS_CONST_LONG("ERR_DISCONNECTED",     (zend_long)PDO_ERR_DISCONNECTED);
    1495             :         REGISTER_PDO_CLASS_CONST_LONG("ERR_NO_PERM",          (zend_long)PDO_ERR_NO_PERM);
    1496             : #endif
    1497             : 
    1498       22587 : }
    1499             : 
    1500        1297 : static void dbh_free(pdo_dbh_t *dbh, zend_bool free_persistent)
    1501             : {
    1502             :         int i;
    1503             : 
    1504        1297 :         if (dbh->is_persistent && !free_persistent) {
    1505          44 :                 return;
    1506             :         }
    1507             : 
    1508        1253 :         if (dbh->query_stmt) {
    1509          16 :                 zval_ptr_dtor(&dbh->query_stmt_zval);
    1510          16 :                 dbh->query_stmt = NULL;
    1511             :         }
    1512             : 
    1513        1253 :         if (dbh->methods) {
    1514        1242 :                 dbh->methods->closer(dbh);
    1515             :         }
    1516             : 
    1517        1253 :         if (dbh->data_source) {
    1518        1243 :                 pefree((char *)dbh->data_source, dbh->is_persistent);
    1519             :         }
    1520        1253 :         if (dbh->username) {
    1521         903 :                 pefree(dbh->username, dbh->is_persistent);
    1522             :         }
    1523        1253 :         if (dbh->password) {
    1524         903 :                 pefree(dbh->password, dbh->is_persistent);
    1525             :         }
    1526             : 
    1527        1253 :         if (dbh->persistent_id) {
    1528          15 :                 pefree((char *)dbh->persistent_id, dbh->is_persistent);
    1529             :         }
    1530             : 
    1531        2506 :         if (!Z_ISUNDEF(dbh->def_stmt_ctor_args)) {
    1532           9 :                 zval_ptr_dtor(&dbh->def_stmt_ctor_args);
    1533             :         }
    1534             : 
    1535        3759 :         for (i = 0; i < PDO_DBH_DRIVER_METHOD_KIND__MAX; i++) {
    1536        2506 :                 if (dbh->cls_methods[i]) {
    1537          19 :                         zend_hash_destroy(dbh->cls_methods[i]);
    1538          19 :                         pefree(dbh->cls_methods[i], dbh->is_persistent);
    1539             :                 }
    1540             :         }
    1541             : 
    1542        1253 :         pefree(dbh, dbh->is_persistent);
    1543             : }
    1544             : 
    1545        1282 : static void pdo_dbh_free_storage(zend_object *std)
    1546             : {
    1547        1282 :         pdo_dbh_t *dbh = php_pdo_dbh_fetch_inner(std);
    1548        1282 :         if (dbh->in_txn && dbh->methods && dbh->methods->rollback) {
    1549         122 :                 dbh->methods->rollback(dbh);
    1550         122 :                 dbh->in_txn = 0;
    1551             :         }
    1552             : 
    1553        1282 :         if (dbh->is_persistent && dbh->methods && dbh->methods->persistent_shutdown) {
    1554           6 :                 dbh->methods->persistent_shutdown(dbh);
    1555             :         }
    1556        1282 :         zend_object_std_dtor(std);
    1557        1282 :         dbh_free(dbh, 0);
    1558        1282 : }
    1559             : 
    1560        1282 : zend_object *pdo_dbh_new(zend_class_entry *ce)
    1561             : {
    1562             :         pdo_dbh_object_t *dbh;
    1563             : 
    1564        1282 :         dbh = ecalloc(1, sizeof(pdo_dbh_object_t) + zend_object_properties_size(ce));
    1565        1282 :         zend_object_std_init(&dbh->std, ce);
    1566        1282 :         object_properties_init(&dbh->std, ce);
    1567        1282 :         rebuild_object_properties(&dbh->std);
    1568        1282 :         dbh->inner = ecalloc(1, sizeof(pdo_dbh_t));
    1569        1282 :         dbh->inner->def_stmt_ce = pdo_dbstmt_ce;
    1570             : 
    1571        1282 :         dbh->std.handlers = &pdo_dbh_object_handlers;
    1572             : 
    1573        1282 :         return &dbh->std;
    1574             : }
    1575             : 
    1576             : /* }}} */
    1577             : 
    1578          15 : ZEND_RSRC_DTOR_FUNC(php_pdo_pdbh_dtor) /* {{{ */
    1579             : {
    1580          15 :         if (res->ptr) {
    1581          15 :                 pdo_dbh_t *dbh = (pdo_dbh_t*)res->ptr;
    1582          15 :                 dbh_free(dbh, 1);
    1583          15 :                 res->ptr = NULL;
    1584             :         }
    1585          15 : }
    1586             : /* }}} */
    1587             : 
    1588             : /*
    1589             :  * Local variables:
    1590             :  * tab-width: 4
    1591             :  * c-basic-offset: 4
    1592             :  * End:
    1593             :  * vim600: noet sw=4 ts=4 fdm=marker
    1594             :  * vim<600: noet sw=4 ts=4
    1595             :  */

Generated by: LCOV version 1.10

Generated at Sat, 25 Jun 2016 07:09:01 +0000 (10 hours ago)

Copyright © 2005-2016 The PHP Group
All rights reserved.