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-19 Instrumented lines: 750
Code covered: 77.1 % Executed lines: 578
Legend: not executed executed

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

Generated by: LTP GCOV extension version 1.5

Generated at Thu, 19 Nov 2009 08:20:15 +0000 (5 days ago)

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