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