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

LTP GCOV extension - code coverage report
Current view: directory - pdo - pdo_dbh.c
Test: PHP Code Coverage
Date: 2009-11-23 Instrumented lines: 768
Code covered: 81.0 % Executed lines: 622
Legend: not executed executed

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

Generated by: LTP GCOV extension version 1.5

Generated at Mon, 23 Nov 2009 17:39:34 +0000 (34 hours ago)

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