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: 623 757 82.3 %
Date: 2014-12-13 Functions: 29 32 90.6 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Sat, 13 Dec 2014 06:16:18 +0000 (8 days ago)

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