root/ext/pdo_mysql/mysql_driver.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. _pdo_mysql_error
  2. pdo_mysql_fetch_error_func
  3. mysql_handle_closer
  4. mysql_handle_preparer
  5. mysql_handle_doer
  6. pdo_mysql_last_insert_id
  7. mysql_handle_quoter
  8. mysql_handle_begin
  9. mysql_handle_commit
  10. mysql_handle_rollback
  11. mysql_handle_autocommit
  12. pdo_mysql_set_attribute
  13. pdo_mysql_get_attribute
  14. pdo_mysql_check_liveness
  15. pdo_mysql_handle_factory

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

/* [<][>][^][v][top][bottom][index][help] */