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

LCOV - code coverage report
Current view: top level - ext/pdo_mysql - mysql_driver.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 323 360 89.7 %
Date: 2019-05-13 Functions: 15 15 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :   +----------------------------------------------------------------------+
       3             :   | PHP Version 7                                                        |
       4             :   +----------------------------------------------------------------------+
       5             :   | Copyright (c) 1997-2018 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: George Schlossnagle <george@omniti.com>                      |
      16             :   |         Wez Furlong <wez@php.net>                                    |
      17             :   |         Johannes Schlueter <johannes@mysql.com>                      |
      18             :   +----------------------------------------------------------------------+
      19             : */
      20             : 
      21             : /* $Id$ */
      22             : 
      23             : #ifdef HAVE_CONFIG_H
      24             : #include "config.h"
      25             : #endif
      26             : 
      27             : #include "php.h"
      28             : #include "php_ini.h"
      29             : #include "ext/standard/info.h"
      30             : #include "pdo/php_pdo.h"
      31             : #include "pdo/php_pdo_driver.h"
      32             : #include "php_pdo_mysql.h"
      33             : #include "php_pdo_mysql_int.h"
      34             : #ifndef PDO_USE_MYSQLND
      35             : #include <mysqld_error.h>
      36             : #endif
      37             : #include "zend_exceptions.h"
      38             : 
      39             : #if defined(PDO_USE_MYSQLND)
      40             : #       define pdo_mysql_init(persistent) mysqlnd_init(MYSQLND_CLIENT_NO_FLAG, persistent)
      41             : #else
      42             : #       define pdo_mysql_init(persistent) mysql_init(NULL)
      43             : #endif
      44             : 
      45             : /* {{{ _pdo_mysql_error */
      46         835 : int _pdo_mysql_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, const char *file, int line)
      47             : {
      48         835 :         pdo_mysql_db_handle *H = (pdo_mysql_db_handle *)dbh->driver_data;
      49             :         pdo_error_type *pdo_err;
      50             :         pdo_mysql_error_info *einfo;
      51         835 :         pdo_mysql_stmt *S = NULL;
      52             : 
      53         835 :         PDO_DBG_ENTER("_pdo_mysql_error");
      54         835 :         PDO_DBG_INF_FMT("file=%s line=%d", file, line);
      55         835 :         if (stmt) {
      56          35 :                 S = (pdo_mysql_stmt*)stmt->driver_data;
      57          35 :                 pdo_err = &stmt->error_code;
      58          35 :                 einfo   = &S->einfo;
      59             :         } else {
      60         800 :                 pdo_err = &dbh->error_code;
      61         800 :                 einfo   = &H->einfo;
      62             :         }
      63             : 
      64         835 :         if (S && S->stmt) {
      65           5 :                 einfo->errcode = mysql_stmt_errno(S->stmt);
      66             :         } else {
      67         830 :                 einfo->errcode = mysql_errno(H->server);
      68             :         }
      69             : 
      70         835 :         einfo->file = file;
      71         835 :         einfo->line = line;
      72             : 
      73         835 :         if (einfo->errmsg) {
      74         496 :                 pefree(einfo->errmsg, dbh->is_persistent);
      75         496 :                 einfo->errmsg = NULL;
      76             :         }
      77             : 
      78         835 :         if (einfo->errcode) {
      79         832 :                 if (einfo->errcode == 2014) {
      80           8 :                         einfo->errmsg = pestrdup(
      81             :                                 "Cannot execute queries while other unbuffered queries are active.  "
      82             :                                 "Consider using PDOStatement::fetchAll().  Alternatively, if your code "
      83             :                                 "is only ever going to run against mysql, you may enable query "
      84             :                                 "buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute.",
      85             :                                 dbh->is_persistent);
      86         824 :                 } else if (einfo->errcode == 2057) {
      87           0 :                         einfo->errmsg = pestrdup(
      88             :                                 "A stored procedure returning result sets of different size was called. "
      89             :                                 "This is not supported by libmysql",
      90             :                                 dbh->is_persistent);
      91             : 
      92             :                 } else {
      93         824 :                         einfo->errmsg = pestrdup(mysql_error(H->server), dbh->is_persistent);
      94             :                 }
      95             :         } else { /* no error */
      96           3 :                 strcpy(*pdo_err, PDO_ERR_NONE);
      97           3 :                 PDO_DBG_RETURN(0);
      98             :         }
      99             : 
     100         832 :         if (S && S->stmt) {
     101           5 :                 strcpy(*pdo_err, mysql_stmt_sqlstate(S->stmt));
     102             :         } else {
     103         827 :                 strcpy(*pdo_err, mysql_sqlstate(H->server));
     104             :         }
     105             : 
     106         832 :         if (!dbh->methods) {
     107          16 :                 PDO_DBG_INF("Throwing exception");
     108          16 :                 zend_throw_exception_ex(php_pdo_get_exception(), einfo->errcode, "SQLSTATE[%s] [%d] %s",
     109             :                                 *pdo_err, einfo->errcode, einfo->errmsg);
     110             :         }
     111             : 
     112         832 :         PDO_DBG_RETURN(einfo->errcode);
     113             : }
     114             : /* }}} */
     115             : 
     116             : /* {{{ pdo_mysql_fetch_error_func */
     117         828 : static int pdo_mysql_fetch_error_func(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *info)
     118             : {
     119         828 :         pdo_mysql_db_handle *H = (pdo_mysql_db_handle *)dbh->driver_data;
     120         828 :         pdo_mysql_error_info *einfo = &H->einfo;
     121             : 
     122         828 :         PDO_DBG_ENTER("pdo_mysql_fetch_error_func");
     123         828 :         PDO_DBG_INF_FMT("dbh=%p stmt=%p", dbh, stmt);
     124         828 :         if (stmt) {
     125         767 :                 pdo_mysql_stmt *S = (pdo_mysql_stmt*)stmt->driver_data;
     126         767 :                 einfo = &S->einfo;
     127             :         } else {
     128          61 :                 einfo = &H->einfo;
     129             :         }
     130             : 
     131         828 :         if (einfo->errcode) {
     132         107 :                 add_next_index_long(info, einfo->errcode);
     133         107 :                 add_next_index_string(info, einfo->errmsg);
     134             :         }
     135             : 
     136         828 :         PDO_DBG_RETURN(1);
     137             : }
     138             : /* }}} */
     139             : 
     140             : /* {{{ mysql_handle_closer */
     141         542 : static int mysql_handle_closer(pdo_dbh_t *dbh)
     142             : {
     143         542 :         pdo_mysql_db_handle *H = (pdo_mysql_db_handle *)dbh->driver_data;
     144             : 
     145         542 :         PDO_DBG_ENTER("mysql_handle_closer");
     146         542 :         PDO_DBG_INF_FMT("dbh=%p", dbh);
     147         542 :         if (H) {
     148         542 :                 if (H->server) {
     149         542 :                         mysql_close(H->server);
     150             :                 }
     151         542 :                 if (H->einfo.errmsg) {
     152         302 :                         pefree(H->einfo.errmsg, dbh->is_persistent);
     153             :                 }
     154         542 :                 pefree(H, dbh->is_persistent);
     155         542 :                 dbh->driver_data = NULL;
     156             :         }
     157         542 :         PDO_DBG_RETURN(0);
     158             : }
     159             : /* }}} */
     160             : 
     161             : /* {{{ mysql_handle_preparer */
     162        1752 : static int mysql_handle_preparer(pdo_dbh_t *dbh, const char *sql, size_t sql_len, pdo_stmt_t *stmt, zval *driver_options)
     163             : {
     164        1752 :         pdo_mysql_db_handle *H = (pdo_mysql_db_handle *)dbh->driver_data;
     165        1752 :         pdo_mysql_stmt *S = ecalloc(1, sizeof(pdo_mysql_stmt));
     166        1752 :         char *nsql = NULL;
     167        1752 :         size_t nsql_len = 0;
     168             :         int ret;
     169             :         int server_version;
     170             : 
     171        1752 :         PDO_DBG_ENTER("mysql_handle_preparer");
     172        1752 :         PDO_DBG_INF_FMT("dbh=%p", dbh);
     173        1752 :         PDO_DBG_INF_FMT("sql=%.*s", (int)sql_len, sql);
     174             : 
     175        1752 :         S->H = H;
     176        1752 :         stmt->driver_data = S;
     177        1752 :         stmt->methods = &mysql_stmt_methods;
     178             : 
     179        1752 :         if (H->emulate_prepare) {
     180         869 :                 goto end;
     181             :         }
     182             : 
     183         883 :         server_version = mysql_get_server_version(H->server);
     184         883 :         if (server_version < 40100) {
     185           0 :                 goto fallback;
     186             :         }
     187         883 :         stmt->supports_placeholders = PDO_PLACEHOLDER_POSITIONAL;
     188         883 :         ret = pdo_parse_params(stmt, (char*)sql, sql_len, &nsql, &nsql_len);
     189             : 
     190         883 :         if (ret == 1) {
     191             :                 /* query was rewritten */
     192         116 :                 sql = nsql;
     193         116 :                 sql_len = nsql_len;
     194         767 :         } else if (ret == -1) {
     195             :                 /* failed to parse */
     196           1 :                 strcpy(dbh->error_code, stmt->error_code);
     197           1 :                 PDO_DBG_RETURN(0);
     198             :         }
     199             : 
     200         882 :         if (!(S->stmt = mysql_stmt_init(H->server))) {
     201           0 :                 pdo_mysql_error(dbh);
     202           0 :                 if (nsql) {
     203           0 :                         efree(nsql);
     204             :                 }
     205           0 :                 PDO_DBG_RETURN(0);
     206             :         }
     207             : 
     208         882 :         if (mysql_stmt_prepare(S->stmt, sql, sql_len)) {
     209             :                 /* TODO: might need to pull statement specific info here? */
     210             :                 /* if the query isn't supported by the protocol, fallback to emulation */
     211          11 :                 if (mysql_errno(H->server) == 1295) {
     212           1 :                         if (nsql) {
     213           0 :                                 efree(nsql);
     214             :                         }
     215           1 :                         goto fallback;
     216             :                 }
     217          10 :                 pdo_mysql_error(dbh);
     218          10 :                 if (nsql) {
     219           1 :                         efree(nsql);
     220             :                 }
     221          10 :                 PDO_DBG_RETURN(0);
     222             :         }
     223         871 :         if (nsql) {
     224         115 :                 efree(nsql);
     225             :         }
     226             : 
     227         871 :         S->num_params = mysql_stmt_param_count(S->stmt);
     228             : 
     229         871 :         if (S->num_params) {
     230         384 :                 S->params_given = 0;
     231             : #if defined(PDO_USE_MYSQLND)
     232         384 :                 S->params = NULL;
     233             : #else
     234             :                 S->params = ecalloc(S->num_params, sizeof(MYSQL_BIND));
     235             :                 S->in_null = ecalloc(S->num_params, sizeof(my_bool));
     236             :                 S->in_length = ecalloc(S->num_params, sizeof(zend_ulong));
     237             : #endif
     238             :         }
     239         871 :         dbh->alloc_own_columns = 1;
     240             : 
     241         871 :         S->max_length = pdo_attr_lval(driver_options, PDO_ATTR_MAX_COLUMN_LEN, 0);
     242             : 
     243         871 :         PDO_DBG_RETURN(1);
     244             : 
     245         870 : fallback:
     246         870 : end:
     247         870 :         stmt->supports_placeholders = PDO_PLACEHOLDER_NONE;
     248             : 
     249         870 :         PDO_DBG_RETURN(1);
     250             : }
     251             : /* }}} */
     252             : 
     253             : /* {{{ mysql_handle_doer */
     254        1963 : static zend_long mysql_handle_doer(pdo_dbh_t *dbh, const char *sql, size_t sql_len)
     255             : {
     256        1963 :         pdo_mysql_db_handle *H = (pdo_mysql_db_handle *)dbh->driver_data;
     257        1963 :         PDO_DBG_ENTER("mysql_handle_doer");
     258        1963 :         PDO_DBG_INF_FMT("dbh=%p", dbh);
     259        1963 :         PDO_DBG_INF_FMT("sql=%.*s", (int)sql_len, sql);
     260             : 
     261        1963 :         if (mysql_real_query(H->server, sql, sql_len)) {
     262         771 :                 pdo_mysql_error(dbh);
     263         771 :                 PDO_DBG_RETURN(-1);
     264             :         } else {
     265        1192 :                 my_ulonglong c = mysql_affected_rows(H->server);
     266        1192 :                 if (c == (my_ulonglong) -1) {
     267           3 :                         pdo_mysql_error(dbh);
     268           3 :                         PDO_DBG_RETURN(H->einfo.errcode ? -1 : 0);
     269             :                 } else {
     270             : 
     271             :                         /* MULTI_QUERY support - eat up all unfetched result sets */
     272             :                         MYSQL_RES* result;
     273        2382 :                         while (mysql_more_results(H->server)) {
     274           4 :                                 if (mysql_next_result(H->server)) {
     275           0 :                                         PDO_DBG_RETURN(1);
     276             :                                 }
     277           4 :                                 result = mysql_store_result(H->server);
     278           4 :                                 if (result) {
     279           0 :                                         mysql_free_result(result);
     280             :                                 }
     281             :                         }
     282        1189 :                         PDO_DBG_RETURN((int)c);
     283             :                 }
     284             :         }
     285             : }
     286             : /* }}} */
     287             : 
     288             : /* {{{ pdo_mysql_last_insert_id */
     289          13 : static char *pdo_mysql_last_insert_id(pdo_dbh_t *dbh, const char *name, size_t *len)
     290             : {
     291          13 :         pdo_mysql_db_handle *H = (pdo_mysql_db_handle *)dbh->driver_data;
     292          13 :         char *id = php_pdo_int64_to_str(mysql_insert_id(H->server));
     293          13 :         PDO_DBG_ENTER("pdo_mysql_last_insert_id");
     294          13 :         *len = strlen(id);
     295          13 :         PDO_DBG_RETURN(id);
     296             : }
     297             : /* }}} */
     298             : 
     299             : /* {{{ mysql_handle_quoter */
     300         366 : static int mysql_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, size_t unquotedlen, char **quoted, size_t *quotedlen, enum pdo_param_type paramtype )
     301             : {
     302         366 :         pdo_mysql_db_handle *H = (pdo_mysql_db_handle *)dbh->driver_data;
     303         366 :         zend_bool use_national_character_set = 0;
     304             : 
     305         366 :         if (H->assume_national_character_set_strings) {
     306           3 :                 use_national_character_set = 1;
     307             :         }
     308         366 :         if ((paramtype & PDO_PARAM_STR_NATL) == PDO_PARAM_STR_NATL) {
     309           2 :                 use_national_character_set = 1;
     310             :         }
     311         366 :         if ((paramtype & PDO_PARAM_STR_CHAR) == PDO_PARAM_STR_CHAR) {
     312           2 :                 use_national_character_set = 0;
     313             :         }
     314             : 
     315         366 :         PDO_DBG_ENTER("mysql_handle_quoter");
     316         366 :         PDO_DBG_INF_FMT("dbh=%p", dbh);
     317         366 :         PDO_DBG_INF_FMT("unquoted=%.*s", (int)unquotedlen, unquoted);
     318         366 :         *quoted = safe_emalloc(2, unquotedlen, 3 + (use_national_character_set ? 1 : 0));
     319             : 
     320         366 :         if (use_national_character_set) {
     321           3 :                 *quotedlen = mysql_real_escape_string(H->server, *quoted + 2, unquoted, unquotedlen);
     322           3 :                 (*quoted)[0] = 'N';
     323           3 :                 (*quoted)[1] = '\'';
     324             : 
     325           3 :                 ++*quotedlen; /* N prefix */
     326             :         } else {
     327         363 :                 *quotedlen = mysql_real_escape_string(H->server, *quoted + 1, unquoted, unquotedlen);
     328         363 :                 (*quoted)[0] = '\'';
     329             :         }
     330             : 
     331         366 :         (*quoted)[++*quotedlen] = '\'';
     332         366 :         (*quoted)[++*quotedlen] = '\0';
     333         366 :         PDO_DBG_INF_FMT("quoted=%.*s", (int)*quotedlen, *quoted);
     334         366 :         PDO_DBG_RETURN(1);
     335             : }
     336             : /* }}} */
     337             : 
     338             : /* {{{ mysql_handle_begin */
     339          21 : static int mysql_handle_begin(pdo_dbh_t *dbh)
     340             : {
     341          21 :         PDO_DBG_ENTER("mysql_handle_quoter");
     342          21 :         PDO_DBG_INF_FMT("dbh=%p", dbh);
     343          21 :         PDO_DBG_RETURN(0 <= mysql_handle_doer(dbh, ZEND_STRL("START TRANSACTION")));
     344             : }
     345             : /* }}} */
     346             : 
     347             : /* {{{ mysql_handle_commit */
     348          10 : static int mysql_handle_commit(pdo_dbh_t *dbh)
     349             : {
     350          10 :         PDO_DBG_ENTER("mysql_handle_commit");
     351          10 :         PDO_DBG_INF_FMT("dbh=%p", dbh);
     352             : #if MYSQL_VERSION_ID >= 40100 || defined(PDO_USE_MYSQLND)
     353          10 :         PDO_DBG_RETURN(0 == mysql_commit(((pdo_mysql_db_handle *)dbh->driver_data)->server));
     354             : #else
     355             :         PDO_DBG_RETURN(0 <= mysql_handle_doer(dbh, ZEND_STRL("COMMIT")));
     356             : #endif
     357             : }
     358             : /* }}} */
     359             : 
     360             : /* {{{ mysql_handle_rollback */
     361          11 : static int mysql_handle_rollback(pdo_dbh_t *dbh)
     362             : {
     363          11 :         PDO_DBG_ENTER("mysql_handle_rollback");
     364          11 :         PDO_DBG_INF_FMT("dbh=%p", dbh);
     365             : #if MYSQL_VERSION_ID >= 40100 || defined(PDO_USE_MYSQLND)
     366          11 :         PDO_DBG_RETURN(0 <= mysql_rollback(((pdo_mysql_db_handle *)dbh->driver_data)->server));
     367             : #else
     368             :         PDO_DBG_RETURN(0 <= mysql_handle_doer(dbh, ZEND_STRL("ROLLBACK")));
     369             : #endif
     370             : }
     371             : /* }}} */
     372             : 
     373             : /* {{{ mysql_handle_autocommit */
     374           7 : static inline int mysql_handle_autocommit(pdo_dbh_t *dbh)
     375             : {
     376           7 :         PDO_DBG_ENTER("mysql_handle_autocommit");
     377           7 :         PDO_DBG_INF_FMT("dbh=%p", dbh);
     378           7 :         PDO_DBG_INF_FMT("dbh->autocommit=%d", dbh->auto_commit);
     379             : #if MYSQL_VERSION_ID >= 40100 || defined(PDO_USE_MYSQLND)
     380           7 :         PDO_DBG_RETURN(0 <= mysql_autocommit(((pdo_mysql_db_handle *)dbh->driver_data)->server, dbh->auto_commit));
     381             : #else
     382             :         if (dbh->auto_commit) {
     383             :                 PDO_DBG_RETURN(0 <= mysql_handle_doer(dbh, ZEND_STRL("SET AUTOCOMMIT=1")));
     384             :         } else {
     385             :                 PDO_DBG_RETURN(0 <= mysql_handle_doer(dbh, ZEND_STRL("SET AUTOCOMMIT=0")));
     386             :         }
     387             : #endif
     388             : }
     389             : /* }}} */
     390             : 
     391             : /* {{{ pdo_mysql_set_attribute */
     392         339 : static int pdo_mysql_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval *val)
     393             : {
     394         339 :         zend_long lval = zval_get_long(val);
     395         339 :         zend_bool bval = lval ? 1 : 0;
     396         339 :         PDO_DBG_ENTER("pdo_mysql_set_attribute");
     397         339 :         PDO_DBG_INF_FMT("dbh=%p", dbh);
     398         339 :         PDO_DBG_INF_FMT("attr=%l", attr);
     399         339 :         switch (attr) {
     400          10 :                 case PDO_ATTR_AUTOCOMMIT:
     401             :                         /* ignore if the new value equals the old one */
     402          10 :                         if (dbh->auto_commit ^ bval) {
     403           6 :                                 dbh->auto_commit = bval;
     404           6 :                                 mysql_handle_autocommit(dbh);
     405             :                         }
     406          10 :                         PDO_DBG_RETURN(1);
     407             : 
     408           1 :                 case PDO_ATTR_DEFAULT_STR_PARAM:
     409           1 :                         ((pdo_mysql_db_handle *)dbh->driver_data)->assume_national_character_set_strings = lval == PDO_PARAM_STR_NATL ? 1 : 0;
     410           1 :                         PDO_DBG_RETURN(1);
     411             : 
     412          38 :                 case PDO_MYSQL_ATTR_USE_BUFFERED_QUERY:
     413             :                         /* ignore if the new value equals the old one */
     414          38 :                         ((pdo_mysql_db_handle *)dbh->driver_data)->buffered = bval;
     415          38 :                         PDO_DBG_RETURN(1);
     416             : 
     417         230 :                 case PDO_MYSQL_ATTR_DIRECT_QUERY:
     418             :                 case PDO_ATTR_EMULATE_PREPARES:
     419             :                         /* ignore if the new value equals the old one */
     420         230 :                         ((pdo_mysql_db_handle *)dbh->driver_data)->emulate_prepare = bval;
     421         230 :                         PDO_DBG_RETURN(1);
     422             : 
     423           2 :                 case PDO_ATTR_FETCH_TABLE_NAMES:
     424           2 :                         ((pdo_mysql_db_handle *)dbh->driver_data)->fetch_table_names = bval;
     425           2 :                         PDO_DBG_RETURN(1);
     426             : 
     427             : #ifndef PDO_USE_MYSQLND
     428             :                 case PDO_MYSQL_ATTR_MAX_BUFFER_SIZE:
     429             :                         if (lval < 0) {
     430             :                                 /* TODO: Johannes, can we throw a warning here? */
     431             :                                 ((pdo_mysql_db_handle *)dbh->driver_data)->max_buffer_size = 1024*1024;
     432             :                                 PDO_DBG_INF_FMT("Adjusting invalid buffer size to =%l", ((pdo_mysql_db_handle *)dbh->driver_data)->max_buffer_size);
     433             :                         } else {
     434             :                                 ((pdo_mysql_db_handle *)dbh->driver_data)->max_buffer_size = lval;
     435             :                         }
     436             :                         PDO_DBG_RETURN(1);
     437             :                         break;
     438             : #endif
     439             : 
     440          58 :                 default:
     441          58 :                         PDO_DBG_RETURN(0);
     442             :         }
     443             : }
     444             : /* }}} */
     445             : 
     446             : /* {{{ pdo_mysql_get_attribute */
     447         117 : static int pdo_mysql_get_attribute(pdo_dbh_t *dbh, zend_long attr, zval *return_value)
     448             : {
     449         117 :         pdo_mysql_db_handle *H = (pdo_mysql_db_handle *)dbh->driver_data;
     450             : 
     451         117 :         PDO_DBG_ENTER("pdo_mysql_get_attribute");
     452         117 :         PDO_DBG_INF_FMT("dbh=%p", dbh);
     453         117 :         PDO_DBG_INF_FMT("attr=%l", attr);
     454         117 :         switch (attr) {
     455           4 :                 case PDO_ATTR_CLIENT_VERSION:
     456           8 :                         ZVAL_STRING(return_value, (char *)mysql_get_client_info());
     457           4 :                         break;
     458             : 
     459           5 :                 case PDO_ATTR_SERVER_VERSION:
     460          10 :                         ZVAL_STRING(return_value, (char *)mysql_get_server_info(H->server));
     461           5 :                         break;
     462             : 
     463           3 :                 case PDO_ATTR_CONNECTION_STATUS:
     464           6 :                         ZVAL_STRING(return_value, (char *)mysql_get_host_info(H->server));
     465           3 :                         break;
     466           3 :                 case PDO_ATTR_SERVER_INFO: {
     467             : #if defined(PDO_USE_MYSQLND)
     468             :                         zend_string *tmp;
     469             : 
     470           3 :                         if (mysqlnd_stat(H->server, &tmp) == PASS) {
     471           3 :                                 ZVAL_STR(return_value, tmp);
     472             : #else
     473             :                         char *tmp;
     474             :                         if ((tmp = (char *)mysql_stat(H->server))) {
     475             :                                 ZVAL_STRING(return_value, tmp);
     476             : #endif
     477             :                         } else {
     478           0 :                                 pdo_mysql_error(dbh);
     479           0 :                                 PDO_DBG_RETURN(-1);
     480             :                         }
     481             :                 }
     482           3 :                         break;
     483             : 
     484          19 :                 case PDO_ATTR_AUTOCOMMIT:
     485          19 :                         ZVAL_LONG(return_value, dbh->auto_commit);
     486          19 :                         break;
     487             : 
     488           2 :                 case PDO_ATTR_DEFAULT_STR_PARAM:
     489           2 :                         ZVAL_LONG(return_value, H->assume_national_character_set_strings ? PDO_PARAM_STR_NATL : PDO_PARAM_STR_CHAR);
     490           2 :                         break;
     491             : 
     492           6 :                 case PDO_MYSQL_ATTR_USE_BUFFERED_QUERY:
     493           6 :                         ZVAL_LONG(return_value, H->buffered);
     494           6 :                         break;
     495             : 
     496          55 :                 case PDO_ATTR_EMULATE_PREPARES:
     497             :                 case PDO_MYSQL_ATTR_DIRECT_QUERY:
     498          55 :                         ZVAL_LONG(return_value, H->emulate_prepare);
     499          55 :                         break;
     500             : 
     501             : #ifndef PDO_USE_MYSQLND
     502             :                 case PDO_MYSQL_ATTR_MAX_BUFFER_SIZE:
     503             :                         ZVAL_LONG(return_value, H->max_buffer_size);
     504             :                         break;
     505             : #else
     506           5 :                 case PDO_MYSQL_ATTR_LOCAL_INFILE:
     507           5 :                         ZVAL_BOOL(
     508             :                                 return_value,
     509             :                                 (H->server->data->options->flags & CLIENT_LOCAL_FILES) == CLIENT_LOCAL_FILES);
     510           5 :                         break;
     511             : #endif
     512             : 
     513          15 :                 default:
     514          15 :                         PDO_DBG_RETURN(0);
     515             :         }
     516             : 
     517         102 :         PDO_DBG_RETURN(1);
     518             : }
     519             : /* }}} */
     520             : 
     521             : /* {{{ pdo_mysql_check_liveness */
     522          26 : static int pdo_mysql_check_liveness(pdo_dbh_t *dbh)
     523             : {
     524          26 :         pdo_mysql_db_handle *H = (pdo_mysql_db_handle *)dbh->driver_data;
     525             : #if MYSQL_VERSION_ID <= 32230
     526             :         void (*handler) (int);
     527             :         unsigned int my_errno;
     528             : #endif
     529             : 
     530          26 :         PDO_DBG_ENTER("pdo_mysql_check_liveness");
     531          26 :         PDO_DBG_INF_FMT("dbh=%p", dbh);
     532             : 
     533             : #if MYSQL_VERSION_ID > 32230
     534          26 :         if (mysql_ping(H->server)) {
     535           1 :                 PDO_DBG_RETURN(FAILURE);
     536             :         }
     537             : #else /* no mysql_ping() */
     538             :         handler = signal(SIGPIPE, SIG_IGN);
     539             :         mysql_stat(H->server);
     540             :         switch (mysql_errno(H->server)) {
     541             :                 case CR_SERVER_GONE_ERROR:
     542             :                 case CR_SERVER_LOST:
     543             :                         signal(SIGPIPE, handler);
     544             :                         PDO_DBG_RETURN(FAILURE);
     545             :                 default:
     546             :                         break;
     547             :         }
     548             :         signal(SIGPIPE, handler);
     549             : #endif /* end mysql_ping() */
     550          25 :         PDO_DBG_RETURN(SUCCESS);
     551             : }
     552             : /* }}} */
     553             : 
     554             : /* {{{ mysql_methods */
     555             : static struct pdo_dbh_methods mysql_methods = {
     556             :         mysql_handle_closer,
     557             :         mysql_handle_preparer,
     558             :         mysql_handle_doer,
     559             :         mysql_handle_quoter,
     560             :         mysql_handle_begin,
     561             :         mysql_handle_commit,
     562             :         mysql_handle_rollback,
     563             :         pdo_mysql_set_attribute,
     564             :         pdo_mysql_last_insert_id,
     565             :         pdo_mysql_fetch_error_func,
     566             :         pdo_mysql_get_attribute,
     567             :         pdo_mysql_check_liveness,
     568             :         NULL,
     569             :         NULL,
     570             :         NULL
     571             : };
     572             : /* }}} */
     573             : 
     574             : #ifdef PHP_WIN32
     575             : # define PDO_DEFAULT_MYSQL_UNIX_ADDR    NULL
     576             : #else
     577             : # define PDO_DEFAULT_MYSQL_UNIX_ADDR    PDO_MYSQL_G(default_socket)
     578             : #endif
     579             : 
     580             : /* {{{ pdo_mysql_handle_factory */
     581         542 : static int pdo_mysql_handle_factory(pdo_dbh_t *dbh, zval *driver_options)
     582             : {
     583             :         pdo_mysql_db_handle *H;
     584             :         size_t i;
     585         542 :         int ret = 0;
     586         542 :         char *host = NULL, *unix_socket = NULL;
     587         542 :         unsigned int port = 3306;
     588             :         char *dbname;
     589        1084 :         struct pdo_data_src_parser vars[] = {
     590             :                 { "charset",  NULL,   0 },
     591             :                 { "dbname",   "",   0 },
     592             :                 { "host",   "localhost",    0 },
     593             :                 { "port",   "3306", 0 },
     594         542 :                 { "unix_socket",  PDO_DEFAULT_MYSQL_UNIX_ADDR,        0 },
     595             :         };
     596         542 :         int connect_opts = 0
     597             : #ifdef CLIENT_MULTI_RESULTS
     598             :                 |CLIENT_MULTI_RESULTS
     599             : #endif
     600             :                 ;
     601             : #if defined(PDO_USE_MYSQLND)
     602         542 :         size_t dbname_len = 0;
     603         542 :         size_t password_len = 0;
     604             : #endif
     605             : 
     606             : #ifdef CLIENT_MULTI_STATEMENTS
     607         542 :         if (!driver_options) {
     608         503 :                 connect_opts |= CLIENT_MULTI_STATEMENTS;
     609          39 :         } else if (pdo_attr_lval(driver_options, PDO_MYSQL_ATTR_MULTI_STATEMENTS, 1)) {
     610          36 :                 connect_opts |= CLIENT_MULTI_STATEMENTS;
     611             :         }
     612             : #endif
     613             : 
     614         542 :         PDO_DBG_ENTER("pdo_mysql_handle_factory");
     615         542 :         PDO_DBG_INF_FMT("dbh=%p", dbh);
     616             : #ifdef CLIENT_MULTI_RESULTS
     617         542 :         PDO_DBG_INF("multi results");
     618             : #endif
     619             : 
     620         542 :         php_pdo_parse_data_source(dbh->data_source, dbh->data_source_len, vars, 5);
     621             : 
     622         542 :         H = pecalloc(1, sizeof(pdo_mysql_db_handle), dbh->is_persistent);
     623             : 
     624         542 :         H->einfo.errcode = 0;
     625         542 :         H->einfo.errmsg = NULL;
     626             : 
     627             :         /* allocate an environment */
     628             : 
     629             :         /* handle for the server */
     630         542 :         if (!(H->server = pdo_mysql_init(dbh->is_persistent))) {
     631           0 :                 pdo_mysql_error(dbh);
     632           0 :                 goto cleanup;
     633             :         }
     634             : 
     635         542 :         dbh->driver_data = H;
     636             : 
     637             : #ifndef PDO_USE_MYSQLND
     638             :         H->max_buffer_size = 1024*1024;
     639             : #endif
     640             : 
     641         542 :         H->assume_national_character_set_strings = 0;
     642         542 :         H->buffered = H->emulate_prepare = 1;
     643             : 
     644             :         /* handle MySQL options */
     645         542 :         if (driver_options) {
     646          39 :                 zend_long connect_timeout = pdo_attr_lval(driver_options, PDO_ATTR_TIMEOUT, 30);
     647          39 :                 zend_long local_infile = pdo_attr_lval(driver_options, PDO_MYSQL_ATTR_LOCAL_INFILE, 0);
     648          39 :                 zend_string *init_cmd = NULL;
     649             : #ifndef PDO_USE_MYSQLND
     650             :                 zend_string *default_file = NULL, *default_group = NULL;
     651             : #endif
     652          39 :                 zend_long compress = 0;
     653          39 :                 zend_string *ssl_key = NULL, *ssl_cert = NULL, *ssl_ca = NULL, *ssl_capath = NULL, *ssl_cipher = NULL;
     654          39 :                 H->buffered = pdo_attr_lval(driver_options, PDO_MYSQL_ATTR_USE_BUFFERED_QUERY, 1);
     655             : 
     656          39 :                 H->emulate_prepare = pdo_attr_lval(driver_options,
     657          39 :                         PDO_MYSQL_ATTR_DIRECT_QUERY, H->emulate_prepare);
     658          39 :                 H->emulate_prepare = pdo_attr_lval(driver_options,
     659          39 :                         PDO_ATTR_EMULATE_PREPARES, H->emulate_prepare);
     660             : 
     661          78 :                 H->assume_national_character_set_strings = pdo_attr_lval(driver_options,
     662          39 :                         PDO_ATTR_DEFAULT_STR_PARAM, 0) == PDO_PARAM_STR_NATL ? 1 : 0;
     663             : 
     664             : #ifndef PDO_USE_MYSQLND
     665             :                 H->max_buffer_size = pdo_attr_lval(driver_options, PDO_MYSQL_ATTR_MAX_BUFFER_SIZE, H->max_buffer_size);
     666             : #endif
     667             : 
     668          39 :                 if (pdo_attr_lval(driver_options, PDO_MYSQL_ATTR_FOUND_ROWS, 0)) {
     669           1 :                         connect_opts |= CLIENT_FOUND_ROWS;
     670             :                 }
     671             : 
     672          39 :                 if (pdo_attr_lval(driver_options, PDO_MYSQL_ATTR_IGNORE_SPACE, 0)) {
     673           0 :                         connect_opts |= CLIENT_IGNORE_SPACE;
     674             :                 }
     675             : 
     676          39 :                 if (mysql_options(H->server, MYSQL_OPT_CONNECT_TIMEOUT, (const char *)&connect_timeout)) {
     677           0 :                         pdo_mysql_error(dbh);
     678           0 :                         goto cleanup;
     679             :                 }
     680             : 
     681             : #ifndef PDO_USE_MYSQLND
     682             :                 if (PG(open_basedir) && PG(open_basedir)[0] != '\0') {
     683             :                         local_infile = 0;
     684             :                 }
     685             : #endif
     686             : #if defined(MYSQL_OPT_LOCAL_INFILE) || defined(PDO_USE_MYSQLND)
     687          39 :                 if (mysql_options(H->server, MYSQL_OPT_LOCAL_INFILE, (const char *)&local_infile)) {
     688           0 :                         pdo_mysql_error(dbh);
     689           0 :                         goto cleanup;
     690             :                 }
     691             : #endif
     692             : #ifdef MYSQL_OPT_RECONNECT
     693             :                 /* since 5.0.3, the default for this option is 0 if not specified.
     694             :                  * we want the old behaviour
     695             :                  * mysqlnd doesn't support reconnect, thus we don't have "|| defined(PDO_USE_MYSQLND)"
     696             :                 */
     697             :                 {
     698             :                         zend_long reconnect = 1;
     699             :                         mysql_options(H->server, MYSQL_OPT_RECONNECT, (const char*)&reconnect);
     700             :                 }
     701             : #endif
     702          39 :                 init_cmd = pdo_attr_strval(driver_options, PDO_MYSQL_ATTR_INIT_COMMAND, NULL);
     703          39 :                 if (init_cmd) {
     704           5 :                         if (mysql_options(H->server, MYSQL_INIT_COMMAND, (const char *)ZSTR_VAL(init_cmd))) {
     705             :                                 zend_string_release(init_cmd);
     706           0 :                                 pdo_mysql_error(dbh);
     707           0 :                                 goto cleanup;
     708             :                         }
     709             :                         zend_string_release(init_cmd);
     710             :                 }
     711             : #ifndef PDO_USE_MYSQLND
     712             :                 default_file = pdo_attr_strval(driver_options, PDO_MYSQL_ATTR_READ_DEFAULT_FILE, NULL);
     713             :                 if (default_file) {
     714             :                         if (mysql_options(H->server, MYSQL_READ_DEFAULT_FILE, (const char *)ZSTR_VAL(default_file))) {
     715             :                                 zend_string_release(default_file);
     716             :                                 pdo_mysql_error(dbh);
     717             :                                 goto cleanup;
     718             :                         }
     719             :                         zend_string_release(default_file);
     720             :                 }
     721             : 
     722             :                 default_group = pdo_attr_strval(driver_options, PDO_MYSQL_ATTR_READ_DEFAULT_GROUP, NULL);
     723             :                 if (default_group) {
     724             :                         if (mysql_options(H->server, MYSQL_READ_DEFAULT_GROUP, (const char *)ZSTR_VAL(default_group))) {
     725             :                                 zend_string_release(default_group);
     726             :                                 pdo_mysql_error(dbh);
     727             :                                 goto cleanup;
     728             :                         }
     729             :                         zend_string_release(default_group);
     730             :                 }
     731             : #endif
     732          39 :                 compress = pdo_attr_lval(driver_options, PDO_MYSQL_ATTR_COMPRESS, 0);
     733          39 :                 if (compress) {
     734           0 :                         if (mysql_options(H->server, MYSQL_OPT_COMPRESS, 0)) {
     735           0 :                                 pdo_mysql_error(dbh);
     736           0 :                                 goto cleanup;
     737             :                         }
     738             :                 }
     739             : 
     740          39 :                 ssl_key = pdo_attr_strval(driver_options, PDO_MYSQL_ATTR_SSL_KEY, NULL);
     741          39 :                 ssl_cert = pdo_attr_strval(driver_options, PDO_MYSQL_ATTR_SSL_CERT, NULL);
     742          39 :                 ssl_ca = pdo_attr_strval(driver_options, PDO_MYSQL_ATTR_SSL_CA, NULL);
     743          39 :                 ssl_capath = pdo_attr_strval(driver_options, PDO_MYSQL_ATTR_SSL_CAPATH, NULL);
     744          39 :                 ssl_cipher = pdo_attr_strval(driver_options, PDO_MYSQL_ATTR_SSL_CIPHER, NULL);
     745             : 
     746          39 :                 if (ssl_key || ssl_cert || ssl_ca || ssl_capath || ssl_cipher) {
     747           0 :                         mysql_ssl_set(H->server,
     748             :                                         ssl_key? ZSTR_VAL(ssl_key) : NULL,
     749             :                                         ssl_cert? ZSTR_VAL(ssl_cert) : NULL,
     750             :                                         ssl_ca? ZSTR_VAL(ssl_ca) : NULL,
     751             :                                         ssl_capath? ZSTR_VAL(ssl_capath) : NULL,
     752             :                                         ssl_cipher? ZSTR_VAL(ssl_cipher) : NULL);
     753           0 :                         if (ssl_key) {
     754             :                                 zend_string_release(ssl_key);
     755             :                         }
     756           0 :                         if (ssl_cert) {
     757             :                                 zend_string_release(ssl_cert);
     758             :                         }
     759           0 :                         if (ssl_ca) {
     760             :                                 zend_string_release(ssl_ca);
     761             :                         }
     762           0 :                         if (ssl_capath) {
     763             :                                 zend_string_release(ssl_capath);
     764             :                         }
     765           0 :                         if (ssl_cipher) {
     766             :                                 zend_string_release(ssl_cipher);
     767             :                         }
     768             :                 }
     769             : 
     770             : #if MYSQL_VERSION_ID > 50605 || defined(PDO_USE_MYSQLND)
     771             :                 {
     772          39 :                         zend_string *public_key = pdo_attr_strval(driver_options, PDO_MYSQL_ATTR_SERVER_PUBLIC_KEY, NULL);
     773          39 :                         if (public_key) {
     774           0 :                                 if (mysql_options(H->server, MYSQL_SERVER_PUBLIC_KEY, ZSTR_VAL(public_key))) {
     775           0 :                                         pdo_mysql_error(dbh);
     776             :                                         zend_string_release(public_key);
     777           0 :                                         goto cleanup;
     778             :                                 }
     779             :                                 zend_string_release(public_key);
     780             :                         }
     781             :                 }
     782             : #endif
     783             : 
     784             : #ifdef PDO_USE_MYSQLND
     785             :                 {
     786          39 :                         zend_long ssl_verify_cert = pdo_attr_lval(driver_options,
     787             :                                         PDO_MYSQL_ATTR_SSL_VERIFY_SERVER_CERT, -1);
     788          39 :                         if (ssl_verify_cert != -1) {
     789           0 :                                 connect_opts |= ssl_verify_cert ?
     790             :                                         CLIENT_SSL_VERIFY_SERVER_CERT:
     791             :                                         CLIENT_SSL_DONT_VERIFY_SERVER_CERT;
     792             :                         }
     793             :                 }
     794             : #endif
     795             :         } else {
     796             : #if defined(MYSQL_OPT_LOCAL_INFILE) || defined(PDO_USE_MYSQLND)
     797             :                 // in case there are no driver options disable 'local infile' explicitly
     798         503 :                 zend_long local_infile = 0;
     799         503 :                 if (mysql_options(H->server, MYSQL_OPT_LOCAL_INFILE, (const char *)&local_infile)) {
     800           0 :                         pdo_mysql_error(dbh);
     801           0 :                         goto cleanup;
     802             :                 }
     803             : #endif
     804             :         }
     805             : 
     806             : #ifdef PDO_MYSQL_HAS_CHARSET
     807         542 :         if (vars[0].optval && mysql_options(H->server, MYSQL_SET_CHARSET_NAME, vars[0].optval)) {
     808           0 :                 pdo_mysql_error(dbh);
     809           0 :                 goto cleanup;
     810             :         }
     811             : #endif
     812             : 
     813         542 :         dbname = vars[1].optval;
     814         542 :         host = vars[2].optval;
     815         542 :         if(vars[3].optval) {
     816         542 :                 port = atoi(vars[3].optval);
     817             :         }
     818             : 
     819             : #ifdef PHP_WIN32
     820             :         if (vars[2].optval && !strcmp(".", vars[2].optval)) {
     821             : #else
     822         542 :         if (vars[2].optval && !strcmp("localhost", vars[2].optval)) {
     823             : #endif
     824         538 :                 unix_socket = vars[4].optval;
     825             :         }
     826             : 
     827             :         /* TODO: - Check zval cache + ZTS */
     828             : #ifdef PDO_USE_MYSQLND
     829         542 :         if (dbname) {
     830         542 :                 dbname_len = strlen(dbname);
     831             :         }
     832             : 
     833         542 :         if (dbh->password) {
     834         541 :                 password_len = strlen(dbh->password);
     835             :         }
     836             : 
     837         542 :         if (mysqlnd_connect(H->server, host, dbh->username, dbh->password, password_len, dbname, dbname_len,
     838             :                                                 port, unix_socket, connect_opts, MYSQLND_CLIENT_NO_FLAG) == NULL) {
     839             : #else
     840             :         if (mysql_real_connect(H->server, host, dbh->username, dbh->password, dbname, port, unix_socket, connect_opts) == NULL) {
     841             : #endif
     842          16 :                 pdo_mysql_error(dbh);
     843          16 :                 goto cleanup;
     844             :         }
     845             : 
     846         526 :         if (!dbh->auto_commit) {
     847           1 :                 mysql_handle_autocommit(dbh);
     848             :         }
     849             : 
     850         526 :         H->attached = 1;
     851             : 
     852         526 :         dbh->alloc_own_columns = 1;
     853         526 :         dbh->max_escaped_char_length = 2;
     854         526 :         dbh->methods = &mysql_methods;
     855             : 
     856         526 :         ret = 1;
     857             : 
     858         542 : cleanup:
     859        3252 :         for (i = 0; i < sizeof(vars)/sizeof(vars[0]); i++) {
     860        2710 :                 if (vars[i].freeme) {
     861        1083 :                         efree(vars[i].optval);
     862             :                 }
     863             :         }
     864             : 
     865         542 :         dbh->methods = &mysql_methods;
     866             : 
     867         542 :         PDO_DBG_RETURN(ret);
     868             : }
     869             : /* }}} */
     870             : 
     871             : pdo_driver_t pdo_mysql_driver = {
     872             :         PDO_DRIVER_HEADER(mysql),
     873             :         pdo_mysql_handle_factory
     874             : };
     875             : 
     876             : /*
     877             :  * Local variables:
     878             :  * tab-width: 4
     879             :  * c-basic-offset: 4
     880             :  * End:
     881             :  * vim600: noet sw=4 ts=4 fdm=marker
     882             :  * vim<600: noet sw=4 ts=4
     883             :  */

Generated by: LCOV version 1.10

Generated at Tue, 14 May 2019 02:31:49 +0000 (8 days ago)

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