root/ext/mysqli/mysqli_nonapi.c

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

DEFINITIONS

This source file includes following definitions.
  1. php_mysqli_set_error
  2. mysqli_common_connect
  3. PHP_FUNCTION
  4. PHP_FUNCTION
  5. PHP_FUNCTION
  6. PHP_FUNCTION
  7. PHP_FUNCTION
  8. PHP_FUNCTION
  9. PHP_FUNCTION
  10. PHP_FUNCTION
  11. PHP_FUNCTION
  12. PHP_FUNCTION
  13. PHP_FUNCTION
  14. PHP_FUNCTION
  15. PHP_FUNCTION
  16. PHP_FUNCTION
  17. mysqlnd_zval_array_to_mysqlnd_array
  18. mysqlnd_zval_array_from_mysqlnd_array
  19. mysqlnd_dont_poll_zval_array_from_mysqlnd_array
  20. PHP_FUNCTION
  21. PHP_FUNCTION
  22. PHP_FUNCTION
  23. PHP_FUNCTION
  24. PHP_FUNCTION
  25. PHP_FUNCTION
  26. PHP_FUNCTION
  27. mysqli_begin_transaction_libmysql
  28. PHP_FUNCTION
  29. mysqli_savepoint_libmysql
  30. PHP_FUNCTION
  31. PHP_FUNCTION
  32. PHP_FUNCTION

   1 /*
   2   +----------------------------------------------------------------------+
   3   | PHP Version 7                                                        |
   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   | Authors: Georg Richter <georg@php.net>                               |
  16   |          Andrey Hristov <andrey@php.net>                             |
  17   |          Ulf Wendel <uw@php.net>                                     |
  18   +----------------------------------------------------------------------+
  19 
  20   $Id$
  21 */
  22 
  23 #ifdef HAVE_CONFIG_H
  24 #include "config.h"
  25 #endif
  26 
  27 #include <signal.h>
  28 
  29 #include "php.h"
  30 #include "php_ini.h"
  31 #include "ext/standard/info.h"
  32 #include "zend_smart_str.h"
  33 #include "php_mysqli_structs.h"
  34 #include "mysqli_priv.h"
  35 
  36 #define SAFE_STR(a) ((a)?a:"")
  37 
  38 #ifndef zend_parse_parameters_none
  39 #define zend_parse_parameters_none()    \
  40         zend_parse_parameters(ZEND_NUM_ARGS(), "")
  41 #endif
  42 
  43 /* {{{ php_mysqli_set_error
  44  */
  45 static void php_mysqli_set_error(zend_long mysql_errno, char *mysql_err)
  46 {
  47         MyG(error_no) = mysql_errno;
  48         if (MyG(error_msg)) {
  49                 efree(MyG(error_msg));
  50         }
  51         if(mysql_err && *mysql_err) {
  52                 MyG(error_msg) = estrdup(mysql_err);
  53         } else {
  54                 MyG(error_msg) = NULL;
  55         }
  56 }
  57 /* }}} */
  58 
  59 void mysqli_common_connect(INTERNAL_FUNCTION_PARAMETERS, zend_bool is_real_connect, zend_bool in_ctor) /* {{{ */
  60 {
  61         MY_MYSQL                        *mysql = NULL;
  62         MYSQLI_RESOURCE         *mysqli_resource = NULL;
  63         zval                            *object = getThis();
  64         char                            *hostname = NULL, *username=NULL, *passwd=NULL, *dbname=NULL, *socket=NULL;
  65         size_t                                  hostname_len = 0, username_len = 0, passwd_len = 0, dbname_len = 0, socket_len = 0;
  66         zend_bool                       persistent = FALSE;
  67         zend_long                               port = 0, flags = 0;
  68         zend_string                     *hash_key = NULL;
  69         zend_bool                       new_connection = FALSE;
  70         zend_resource           *le;
  71         mysqli_plist_entry *plist = NULL;
  72         zend_bool                       self_alloced = 0;
  73 
  74 
  75 #if !defined(MYSQL_USE_MYSQLND)
  76         if ((MYSQL_VERSION_ID / 100) != (mysql_get_client_version() / 100)) {
  77                 php_error_docref(NULL, E_WARNING,
  78                                                 "Headers and client library minor version mismatch. Headers:%d Library:%ld",
  79                                                 MYSQL_VERSION_ID, mysql_get_client_version());
  80         }
  81 #endif
  82 
  83         if (getThis() && !ZEND_NUM_ARGS() && in_ctor) {
  84                 php_mysqli_init(INTERNAL_FUNCTION_PARAM_PASSTHRU, in_ctor);
  85                 return;
  86         }
  87         hostname = username = dbname = passwd = socket = NULL;
  88 
  89         if (!is_real_connect) {
  90                 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|ssssls", &hostname, &hostname_len, &username, &username_len,
  91                                                                         &passwd, &passwd_len, &dbname, &dbname_len, &port, &socket, &socket_len) == FAILURE) {
  92                         return;
  93                 }
  94 
  95                 if (object && instanceof_function(Z_OBJCE_P(object), mysqli_link_class_entry)) {
  96                         mysqli_resource = (Z_MYSQLI_P(object))->ptr;
  97                         if (mysqli_resource && mysqli_resource->ptr) {
  98                                 mysql = (MY_MYSQL*) mysqli_resource->ptr;
  99                         }
 100                 }
 101                 if (!mysql) {
 102                         mysql = (MY_MYSQL *) ecalloc(1, sizeof(MY_MYSQL));
 103                         self_alloced = 1;
 104                 }
 105                 flags |= CLIENT_MULTI_RESULTS; /* needed for mysql_multi_query() */
 106         } else {
 107                 /* We have flags too */
 108                 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|sssslsl", &object, mysqli_link_class_entry,
 109                                                                                 &hostname, &hostname_len, &username, &username_len, &passwd, &passwd_len, &dbname, &dbname_len, &port, &socket, &socket_len,
 110                                                                                 &flags) == FAILURE) {
 111                         return;
 112                 }
 113 
 114                 mysqli_resource = (Z_MYSQLI_P(object))->ptr;
 115                 MYSQLI_FETCH_RESOURCE_CONN(mysql, object, MYSQLI_STATUS_INITIALIZED);
 116 
 117                 /* set some required options */
 118                 flags |= CLIENT_MULTI_RESULTS; /* needed for mysql_multi_query() */
 119                 /* remove some insecure options */
 120                 flags &= ~CLIENT_MULTI_STATEMENTS;   /* don't allow multi_queries via connect parameter */
 121 #if !defined(MYSQLI_USE_MYSQLND)
 122                 if (PG(open_basedir) && PG(open_basedir)[0] != '\0') {
 123                         flags &= ~CLIENT_LOCAL_FILES;
 124                 }
 125 #endif
 126         }
 127 
 128         if (!socket_len || !socket) {
 129                 socket = MyG(default_socket);
 130         }
 131         if (!port){
 132                 port = MyG(default_port);
 133         }
 134         if (!passwd) {
 135                 passwd = MyG(default_pw);
 136                 passwd_len = strlen(SAFE_STR(passwd));
 137         }
 138         if (!username){
 139                 username = MyG(default_user);
 140         }
 141         if (!hostname || !hostname_len) {
 142                 hostname = MyG(default_host);
 143         }
 144 
 145         if (mysql->mysql && mysqli_resource &&
 146                 (mysqli_resource->status > MYSQLI_STATUS_INITIALIZED))
 147         {
 148                 /* already connected, we should close the connection */
 149                 php_mysqli_close(mysql, MYSQLI_CLOSE_IMPLICIT, mysqli_resource->status);
 150         }
 151 
 152         if (strlen(SAFE_STR(hostname)) > 2 && !strncasecmp(hostname, "p:", 2)) {
 153                 hostname += 2;
 154                 if (!MyG(allow_persistent)) {
 155                         php_error_docref(NULL, E_WARNING, "Persistent connections are disabled. Downgrading to normal");
 156                 } else {
 157                         mysql->persistent = persistent = TRUE;
 158 
 159                         hash_key = strpprintf(0, "mysqli_%s_%s%ld%s%s%s", SAFE_STR(hostname), SAFE_STR(socket),
 160                                                                 port, SAFE_STR(username), SAFE_STR(dbname),
 161                                                                 SAFE_STR(passwd));
 162 
 163                         mysql->hash_key = hash_key;
 164 
 165                         /* check if we can reuse exisiting connection ... */
 166                         if ((le = zend_hash_find_ptr(&EG(persistent_list), hash_key)) != NULL) {
 167                                 if (le->type == php_le_pmysqli()) {
 168                                         plist = (mysqli_plist_entry *) le->ptr;
 169 
 170                                         do {
 171                                                 if (zend_ptr_stack_num_elements(&plist->free_links)) {
 172                                                         mysql->mysql = zend_ptr_stack_pop(&plist->free_links);
 173 
 174                                                         MyG(num_inactive_persistent)--;
 175                                                         /* reset variables */
 176 
 177 #ifndef MYSQLI_NO_CHANGE_USER_ON_PCONNECT
 178                                                         if (!mysqli_change_user_silent(mysql->mysql, username, passwd, dbname, passwd_len)) {
 179 #else
 180                                                         if (!mysql_ping(mysql->mysql)) {
 181 #endif
 182 #ifdef MYSQLI_USE_MYSQLND
 183                                                                 mysqlnd_restart_psession(mysql->mysql);
 184 #endif
 185                                                                 MyG(num_active_persistent)++;
 186                                                                 goto end;
 187                                                         } else {
 188                                                                 mysqli_close(mysql->mysql, MYSQLI_CLOSE_IMPLICIT);
 189                                                                 mysql->mysql = NULL;
 190                                                         }
 191                                                 }
 192                                         } while (0);
 193                                 }
 194                         } else {
 195                                 zend_resource le;
 196                                 le.type = php_le_pmysqli();
 197                                 le.ptr = plist = calloc(1, sizeof(mysqli_plist_entry));
 198 
 199                                 zend_ptr_stack_init_ex(&plist->free_links, 1);
 200                                 zend_hash_str_update_mem(&EG(persistent_list), ZSTR_VAL(hash_key), ZSTR_LEN(hash_key), &le, sizeof(le));
 201                         }
 202                 }
 203         }
 204         if (MyG(max_links) != -1 && MyG(num_links) >= MyG(max_links)) {
 205                 php_error_docref(NULL, E_WARNING, "Too many open links (%pd)", MyG(num_links));
 206                 goto err;
 207         }
 208 
 209         if (persistent && MyG(max_persistent) != -1 &&
 210                 (MyG(num_active_persistent) + MyG(num_inactive_persistent))>= MyG(max_persistent))
 211         {
 212                 php_error_docref(NULL, E_WARNING, "Too many open persistent links (%pd)",
 213                                                                 MyG(num_active_persistent) + MyG(num_inactive_persistent));
 214                 goto err;
 215         }
 216         if (!mysql->mysql) {
 217 #if !defined(MYSQLI_USE_MYSQLND)
 218                 if (!(mysql->mysql = mysql_init(NULL))) {
 219 #else
 220                 if (!(mysql->mysql = mysqlnd_init(MYSQLND_CLIENT_KNOWS_RSET_COPY_DATA, persistent))) {
 221 #endif
 222                         goto err;
 223                 }
 224                 new_connection = TRUE;
 225         }
 226 
 227 #ifdef HAVE_EMBEDDED_MYSQLI
 228         if (hostname_len) {
 229                 unsigned int external=1;
 230                 mysql_options(mysql->mysql, MYSQL_OPT_USE_REMOTE_CONNECTION, (char *)&external);
 231         } else {
 232                 mysql_options(mysql->mysql, MYSQL_OPT_USE_EMBEDDED_CONNECTION, 0);
 233         }
 234 #endif
 235 
 236 #if !defined(MYSQLI_USE_MYSQLND)
 237         /* BC for prior to bug fix #53425 */
 238         flags |= CLIENT_MULTI_RESULTS;
 239 
 240         if (mysql_real_connect(mysql->mysql, hostname, username, passwd, dbname, port, socket, flags) == NULL)
 241 #else
 242         if (mysqlnd_connect(mysql->mysql, hostname, username, passwd, passwd_len, dbname, dbname_len,
 243                                                 port, socket, flags, MYSQLND_CLIENT_KNOWS_RSET_COPY_DATA) == NULL)
 244 #endif
 245         {
 246                 /* Save error messages - for mysqli_connect_error() & mysqli_connect_errno() */
 247                 php_mysqli_set_error(mysql_errno(mysql->mysql), (char *) mysql_error(mysql->mysql));
 248                 php_mysqli_throw_sql_exception((char *)mysql_sqlstate(mysql->mysql), mysql_errno(mysql->mysql),
 249                                                                                 "%s", mysql_error(mysql->mysql));
 250                 if (!is_real_connect) {
 251                         /* free mysql structure */
 252                         mysqli_close(mysql->mysql, MYSQLI_CLOSE_DISCONNECTED);
 253                         mysql->mysql = NULL;
 254                 }
 255                 goto err;
 256         }
 257 
 258         /* clear error */
 259         php_mysqli_set_error(mysql_errno(mysql->mysql), (char *) mysql_error(mysql->mysql));
 260 
 261 #if !defined(MYSQLI_USE_MYSQLND)
 262         mysql->mysql->reconnect = MyG(reconnect);
 263 #endif
 264 
 265         mysql_options(mysql->mysql, MYSQL_OPT_LOCAL_INFILE, (char *)&MyG(allow_local_infile));
 266 
 267 end:
 268         if (!mysqli_resource) {
 269                 mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
 270                 mysqli_resource->ptr = (void *)mysql;
 271         }
 272         mysqli_resource->status = MYSQLI_STATUS_VALID;
 273 
 274         /* store persistent connection */
 275         if (persistent && (new_connection || is_real_connect)) {
 276                 MyG(num_active_persistent)++;
 277         }
 278 
 279         MyG(num_links)++;
 280 
 281         mysql->multi_query = 0;
 282 
 283         if (!object || !instanceof_function(Z_OBJCE_P(object), mysqli_link_class_entry)) {
 284                 MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_link_class_entry);
 285         } else {
 286                 (Z_MYSQLI_P(object))->ptr = mysqli_resource;
 287         }
 288         if (!is_real_connect) {
 289                 return;
 290         } else {
 291                 RETURN_TRUE;
 292         }
 293 
 294 err:
 295         if (mysql->hash_key) {
 296                 zend_string_release(mysql->hash_key);
 297                 mysql->hash_key = NULL;
 298                 mysql->persistent = FALSE;
 299         }
 300         if (!is_real_connect && self_alloced) {
 301                 efree(mysql);
 302         }
 303         RETVAL_FALSE;
 304 } /* }}} */
 305 
 306 /* {{{ proto object mysqli_connect([string hostname [,string username [,string passwd [,string dbname [,int port [,string socket]]]]]])
 307    Open a connection to a mysql server */
 308 PHP_FUNCTION(mysqli_connect)
 309 {
 310         mysqli_common_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, FALSE, FALSE);
 311 }
 312 /* }}} */
 313 
 314 /* {{{ proto object mysqli_link_construct()
 315   */
 316 PHP_FUNCTION(mysqli_link_construct)
 317 {
 318         mysqli_common_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, FALSE, TRUE);
 319 }
 320 /* }}} */
 321 
 322 /* {{{ proto int mysqli_connect_errno(void)
 323    Returns the numerical value of the error message from last connect command */
 324 PHP_FUNCTION(mysqli_connect_errno)
 325 {
 326         RETURN_LONG(MyG(error_no));
 327 }
 328 /* }}} */
 329 
 330 /* {{{ proto string mysqli_connect_error(void)
 331    Returns the text of the error message from previous MySQL operation */
 332 PHP_FUNCTION(mysqli_connect_error)
 333 {
 334         if (MyG(error_msg)) {
 335                 RETURN_STRING(MyG(error_msg));
 336         } else {
 337                 RETURN_NULL();
 338         }
 339 }
 340 /* }}} */
 341 
 342 /* {{{ proto mixed mysqli_fetch_array (object result [,int resulttype])
 343    Fetch a result row as an associative array, a numeric array, or both */
 344 PHP_FUNCTION(mysqli_fetch_array)
 345 {
 346         php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 0);
 347 }
 348 /* }}} */
 349 
 350 /* {{{ proto mixed mysqli_fetch_assoc (object result)
 351    Fetch a result row as an associative array */
 352 PHP_FUNCTION(mysqli_fetch_assoc)
 353 {
 354         php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, MYSQLI_ASSOC, 0);
 355 }
 356 /* }}} */
 357 
 358 /* {{{ proto mixed mysqli_fetch_all (object result [,int resulttype])
 359    Fetches all result rows as an associative array, a numeric array, or both */
 360 #if defined(MYSQLI_USE_MYSQLND)
 361 PHP_FUNCTION(mysqli_fetch_all)
 362 {
 363         MYSQL_RES       *result;
 364         zval            *mysql_result;
 365         zend_long               mode = MYSQLND_FETCH_NUM;
 366 
 367         if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|l", &mysql_result, mysqli_result_class_entry, &mode) == FAILURE) {
 368                 return;
 369         }
 370         MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
 371 
 372         if (!mode || (mode & ~MYSQLND_FETCH_BOTH)) {
 373                 php_error_docref(NULL, E_WARNING, "Mode can be only MYSQLI_FETCH_NUM, "
 374                                  "MYSQLI_FETCH_ASSOC or MYSQLI_FETCH_BOTH");
 375                 RETURN_FALSE;
 376         }
 377 
 378         mysqlnd_fetch_all(result, mode, return_value);
 379 }
 380 /* }}} */
 381 
 382 /* {{{ proto array mysqli_get_client_stats(void)
 383    Returns statistics about the zval cache */
 384 PHP_FUNCTION(mysqli_get_client_stats)
 385 {
 386         if (zend_parse_parameters_none() == FAILURE) {
 387                 return;
 388         }
 389         mysqlnd_get_client_stats(return_value);
 390 }
 391 /* }}} */
 392 
 393 /* {{{ proto array mysqli_get_connection_stats(void)
 394    Returns statistics about the zval cache */
 395 PHP_FUNCTION(mysqli_get_connection_stats)
 396 {
 397         MY_MYSQL        *mysql;
 398         zval            *mysql_link;
 399 
 400         if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O",
 401                                                                          &mysql_link, mysqli_link_class_entry) == FAILURE) {
 402                 return;
 403         }
 404         MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
 405 
 406         mysqlnd_get_connection_stats(mysql->mysql, return_value);
 407 }
 408 #endif
 409 /* }}} */
 410 
 411 /* {{{ proto mixed mysqli_error_list (object connection)
 412    Fetches all client errors */
 413 PHP_FUNCTION(mysqli_error_list)
 414 {
 415         MY_MYSQL        *mysql;
 416         zval            *mysql_link;
 417 
 418         if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
 419                 return;
 420         }
 421         MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
 422         array_init(return_value);
 423 #if defined(MYSQLI_USE_MYSQLND)
 424         if (mysql->mysql->data->error_info->error_list) {
 425                 MYSQLND_ERROR_LIST_ELEMENT * message;
 426                 zend_llist_position pos;
 427                 for (message = (MYSQLND_ERROR_LIST_ELEMENT *) zend_llist_get_first_ex(mysql->mysql->data->error_info->error_list, &pos);
 428                          message;
 429                          message = (MYSQLND_ERROR_LIST_ELEMENT *) zend_llist_get_next_ex(mysql->mysql->data->error_info->error_list, &pos))
 430                 {
 431                         zval single_error;
 432                         array_init(&single_error);
 433                         add_assoc_long_ex(&single_error, "errno", sizeof("errno") - 1, message->error_no);
 434                         add_assoc_string_ex(&single_error, "sqlstate", sizeof("sqlstate") - 1, message->sqlstate);
 435                         add_assoc_string_ex(&single_error, "error", sizeof("error") - 1, message->error);
 436                         add_next_index_zval(return_value, &single_error);
 437                 }
 438         }
 439 #else
 440         if (mysql_errno(mysql->mysql)) {
 441                 zval single_error;
 442                 array_init(&single_error);
 443                 add_assoc_long_ex(&single_error, "errno", sizeof("errno") - 1, mysql_errno(mysql->mysql));
 444                 add_assoc_string_ex(&single_error, "sqlstate", sizeof("sqlstate") - 1, mysql_sqlstate(mysql->mysql));
 445                 add_assoc_string_ex(&single_error, "error", sizeof("error") - 1, mysql_error(mysql->mysql));
 446                 add_next_index_zval(return_value, &single_error);
 447         }
 448 #endif
 449 }
 450 /* }}} */
 451 
 452 /* {{{ proto string mysqli_stmt_error_list(object stmt)
 453 */
 454 PHP_FUNCTION(mysqli_stmt_error_list)
 455 {
 456         MY_STMT *stmt;
 457         zval    *mysql_stmt;
 458 
 459         if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
 460                 return;
 461         }
 462         MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_INITIALIZED);
 463         array_init(return_value);
 464 #if defined(MYSQLI_USE_MYSQLND)
 465         if (stmt->stmt && stmt->stmt->data && stmt->stmt->data->error_info->error_list) {
 466                 MYSQLND_ERROR_LIST_ELEMENT * message;
 467                 zend_llist_position pos;
 468                 for (message = (MYSQLND_ERROR_LIST_ELEMENT *) zend_llist_get_first_ex(stmt->stmt->data->error_info->error_list, &pos);
 469                          message;
 470                          message = (MYSQLND_ERROR_LIST_ELEMENT *) zend_llist_get_next_ex(stmt->stmt->data->error_info->error_list, &pos))
 471                 {
 472                         zval single_error;
 473                         array_init(&single_error);
 474                         add_assoc_long_ex(&single_error, "errno", sizeof("errno") - 1, message->error_no);
 475                         add_assoc_string_ex(&single_error, "sqlstate", sizeof("sqlstate") - 1, message->sqlstate);
 476                         add_assoc_string_ex(&single_error, "error", sizeof("error") - 1, message->error);
 477                         add_next_index_zval(return_value, &single_error);
 478                 }
 479         }
 480 #else
 481         if (mysql_stmt_errno(stmt->stmt)) {
 482                 zval single_error;
 483                 array_init(&single_error);
 484                 add_assoc_long_ex(&single_error, "errno", sizeof("errno") - 1, mysql_stmt_errno(stmt->stmt));
 485                 add_assoc_string_ex(&single_error, "sqlstate", sizeof("sqlstate") - 1, mysql_stmt_sqlstate(stmt->stmt));
 486                 add_assoc_string_ex(&single_error, "error", sizeof("error") - 1, mysql_stmt_error(stmt->stmt));
 487                 add_next_index_zval(return_value, &single_error);
 488         }
 489 #endif
 490 }
 491 /* }}} */
 492 
 493 /* {{{ proto mixed mysqli_fetch_object (object result [, string class_name [, NULL|array ctor_params]])
 494    Fetch a result row as an object */
 495 PHP_FUNCTION(mysqli_fetch_object)
 496 {
 497         php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, MYSQLI_ASSOC, 1);
 498 }
 499 /* }}} */
 500 
 501 /* {{{ proto bool mysqli_multi_query(object link, string query)
 502    allows to execute multiple queries  */
 503 PHP_FUNCTION(mysqli_multi_query)
 504 {
 505         MY_MYSQL        *mysql;
 506         zval            *mysql_link;
 507         char            *query = NULL;
 508         size_t          query_len;
 509 
 510         if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &mysql_link, mysqli_link_class_entry, &query, &query_len) == FAILURE) {
 511                 return;
 512         }
 513         MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
 514 
 515         MYSQLI_ENABLE_MQ;
 516         if (mysql_real_query(mysql->mysql, query, query_len)) {
 517 #ifndef MYSQLI_USE_MYSQLND
 518                 char s_error[MYSQL_ERRMSG_SIZE], s_sqlstate[SQLSTATE_LENGTH+1];
 519                 unsigned int s_errno;
 520                 /* we have to save error information, cause
 521                 MYSQLI_DISABLE_MQ will reset error information */
 522                 strcpy(s_error, mysql_error(mysql->mysql));
 523                 strcpy(s_sqlstate, mysql_sqlstate(mysql->mysql));
 524                 s_errno = mysql_errno(mysql->mysql);
 525 #else
 526                 MYSQLND_ERROR_INFO error_info = *mysql->mysql->data->error_info;
 527 #endif
 528                 MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
 529                 MYSQLI_DISABLE_MQ;
 530 
 531 #ifndef MYSQLI_USE_MYSQLND
 532                 /* restore error information */
 533                 strcpy(mysql->mysql->net.last_error, s_error);
 534                 strcpy(mysql->mysql->net.sqlstate, s_sqlstate);
 535                 mysql->mysql->net.last_errno = s_errno;
 536 #else
 537                 *mysql->mysql->data->error_info = error_info;
 538 #endif
 539                 RETURN_FALSE;
 540         }
 541         RETURN_TRUE;
 542 }
 543 /* }}} */
 544 
 545 /* {{{ proto mixed mysqli_query(object link, string query [,int resultmode]) */
 546 PHP_FUNCTION(mysqli_query)
 547 {
 548         MY_MYSQL                        *mysql;
 549         zval                            *mysql_link;
 550         MYSQLI_RESOURCE         *mysqli_resource;
 551         MYSQL_RES                       *result = NULL;
 552         char                            *query = NULL;
 553         size_t                          query_len;
 554         zend_long                               resultmode = MYSQLI_STORE_RESULT;
 555 
 556         if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os|l", &mysql_link, mysqli_link_class_entry, &query, &query_len, &resultmode) == FAILURE) {
 557                 return;
 558         }
 559 
 560         if (!query_len) {
 561                 php_error_docref(NULL, E_WARNING, "Empty query");
 562                 RETURN_FALSE;
 563         }
 564 #ifdef MYSQLI_USE_MYSQLND
 565         if ((resultmode & ~MYSQLI_ASYNC) != MYSQLI_USE_RESULT && (resultmode & ~(MYSQLI_ASYNC | MYSQLI_STORE_RESULT_COPY_DATA)) != MYSQLI_STORE_RESULT) {
 566 #else
 567         if ((resultmode & ~MYSQLI_ASYNC) != MYSQLI_USE_RESULT && (resultmode & ~MYSQLI_ASYNC) != MYSQLI_STORE_RESULT) {
 568 #endif
 569                 php_error_docref(NULL, E_WARNING, "Invalid value for resultmode");
 570                 RETURN_FALSE;
 571         }
 572 
 573         MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
 574 
 575         MYSQLI_DISABLE_MQ;
 576 
 577 
 578 #ifdef MYSQLI_USE_MYSQLND
 579         if (resultmode & MYSQLI_ASYNC) {
 580                 if (mysqli_async_query(mysql->mysql, query, query_len)) {
 581                         MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
 582                         RETURN_FALSE;
 583                 }
 584                 mysql->async_result_fetch_type = resultmode & ~MYSQLI_ASYNC;
 585                 RETURN_TRUE;
 586         }
 587 #endif
 588 
 589         if (mysql_real_query(mysql->mysql, query, query_len)) {
 590                 MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
 591                 RETURN_FALSE;
 592         }
 593 
 594         if (!mysql_field_count(mysql->mysql)) {
 595                 /* no result set - not a SELECT */
 596                 if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
 597                         php_mysqli_report_index(query, mysqli_server_status(mysql->mysql));
 598                 }
 599                 RETURN_TRUE;
 600         }
 601 
 602 #ifdef MYSQLI_USE_MYSQLND
 603         switch (resultmode & ~(MYSQLI_ASYNC | MYSQLI_STORE_RESULT_COPY_DATA)) {
 604 #else
 605         switch (resultmode & ~MYSQLI_ASYNC) {
 606 #endif
 607                 case MYSQLI_STORE_RESULT:
 608 #ifdef MYSQLI_USE_MYSQLND
 609                         if (resultmode & MYSQLI_STORE_RESULT_COPY_DATA) {
 610                                 result = mysqlnd_store_result_ofs(mysql->mysql);
 611                         } else
 612 #endif
 613                                 result = mysql_store_result(mysql->mysql);
 614                         break;
 615                 case MYSQLI_USE_RESULT:
 616                         result = mysql_use_result(mysql->mysql);
 617                         break;
 618         }
 619         if (!result) {
 620                 php_mysqli_throw_sql_exception((char *)mysql_sqlstate(mysql->mysql), mysql_errno(mysql->mysql),
 621                                                                                 "%s", mysql_error(mysql->mysql));
 622                 RETURN_FALSE;
 623         }
 624 
 625         if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
 626                 php_mysqli_report_index(query, mysqli_server_status(mysql->mysql));
 627         }
 628 
 629         mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
 630         mysqli_resource->ptr = (void *)result;
 631         mysqli_resource->status = MYSQLI_STATUS_VALID;
 632         MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_result_class_entry);
 633 }
 634 /* }}} */
 635 
 636 #if defined(MYSQLI_USE_MYSQLND)
 637 #include "php_network.h"
 638 /* {{{ mysqlnd_zval_array_to_mysqlnd_array functions */
 639 static int mysqlnd_zval_array_to_mysqlnd_array(zval *in_array, MYSQLND ***out_array)
 640 {
 641         zval *elem;
 642         int i = 0, current = 0;
 643 
 644         if (Z_TYPE_P(in_array) != IS_ARRAY) {
 645                 return 0;
 646         }
 647         *out_array = ecalloc(zend_hash_num_elements(Z_ARRVAL_P(in_array)) + 1, sizeof(MYSQLND *));
 648         ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(in_array), elem) {
 649                 i++;
 650                 if (Z_TYPE_P(elem) != IS_OBJECT ||
 651                         !instanceof_function(Z_OBJCE_P(elem), mysqli_link_class_entry)) {
 652                         php_error_docref(NULL, E_WARNING, "Parameter %d not a mysqli object", i);
 653                 } else {
 654                         MY_MYSQL *mysql;
 655                         MYSQLI_RESOURCE *my_res;
 656                         mysqli_object *intern = Z_MYSQLI_P(elem);
 657                         if (!(my_res = (MYSQLI_RESOURCE *)intern->ptr)) {
 658                                 php_error_docref(NULL, E_WARNING, "[%d] Couldn't fetch %s", i, ZSTR_VAL(intern->zo.ce->name));
 659                                 continue;
 660                         }
 661                         mysql = (MY_MYSQL*) my_res->ptr;
 662                         if (MYSQLI_STATUS_VALID && my_res->status < MYSQLI_STATUS_VALID) {
 663                                 php_error_docref(NULL, E_WARNING, "Invalid object %d or resource %s", i, ZSTR_VAL(intern->zo.ce->name));
 664                                 continue;
 665                         }
 666                         (*out_array)[current++] = mysql->mysql;
 667                 }
 668         } ZEND_HASH_FOREACH_END();
 669         return 0;
 670 }
 671 /* }}} */
 672 
 673 /* {{{ mysqlnd_zval_array_from_mysqlnd_array */
 674 static int mysqlnd_zval_array_from_mysqlnd_array(MYSQLND **in_array, zval *out_array)
 675 {
 676         MYSQLND **p = in_array;
 677         zval dest_array;
 678         zval *elem, *dest_elem;
 679         int ret = 0, i = 0;
 680 
 681         array_init_size(&dest_array, zend_hash_num_elements(Z_ARRVAL_P(out_array)));
 682 
 683         ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(out_array), elem) {
 684                 i++;
 685                 if (Z_TYPE_P(elem) != IS_OBJECT ||
 686                                 !instanceof_function(Z_OBJCE_P(elem), mysqli_link_class_entry)) {
 687                         continue;
 688                 }
 689                 {
 690                         MY_MYSQL *mysql;
 691                         MYSQLI_RESOURCE *my_res;
 692                         mysqli_object *intern = Z_MYSQLI_P(elem);
 693                         if (!(my_res = (MYSQLI_RESOURCE *)intern->ptr)) {
 694                                 php_error_docref(NULL, E_WARNING, "[%d] Couldn't fetch %s", i, ZSTR_VAL(intern->zo.ce->name));
 695                                 continue;
 696                         }
 697                         mysql = (MY_MYSQL *) my_res->ptr;
 698                         if (mysql->mysql == *p) {
 699                                 dest_elem = zend_hash_next_index_insert(Z_ARRVAL(dest_array), elem);
 700                                 if (dest_elem) {
 701                                         zval_add_ref(dest_elem);
 702                                 }
 703                                 ret++;
 704                                 p++;
 705                         }
 706                 }
 707         } ZEND_HASH_FOREACH_END();
 708 
 709         /* destroy old array and add new one */
 710         zval_ptr_dtor(out_array);
 711         ZVAL_COPY_VALUE(out_array, &dest_array);
 712 
 713         return 0;
 714 }
 715 /* }}} */
 716 
 717 /* {{{ mysqlnd_dont_poll_zval_array_from_mysqlnd_array */
 718 static int mysqlnd_dont_poll_zval_array_from_mysqlnd_array(MYSQLND **in_array, zval *in_zval_array, zval *out_array)
 719 {
 720         MYSQLND **p = in_array;
 721         zval proxy, *elem, *dest_elem;
 722         int ret = 0;
 723 
 724         array_init(&proxy);
 725         if (in_array) {
 726                 ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(in_zval_array), elem) {
 727                         MY_MYSQL *mysql;
 728                         mysqli_object *intern = Z_MYSQLI_P(elem);
 729                         mysql = (MY_MYSQL *)((MYSQLI_RESOURCE *)intern->ptr)->ptr;
 730                         if (mysql->mysql == *p) {
 731                                 dest_elem = zend_hash_next_index_insert(Z_ARRVAL(proxy), elem);
 732                                 if (dest_elem) {
 733                                         zval_add_ref(dest_elem);
 734                                 }
 735                                 ret++;
 736                                 p++;
 737                         }
 738                 } ZEND_HASH_FOREACH_END();
 739         }
 740 
 741         /* destroy old array and add new one */
 742         zval_ptr_dtor(out_array);
 743         ZVAL_COPY_VALUE(out_array, &proxy);
 744 
 745         return 0;
 746 }
 747 /* }}} */
 748 
 749 /* {{{ proto int mysqli_poll(array read, array write, array error, long sec [, long usec]) U
 750    Poll connections */
 751 PHP_FUNCTION(mysqli_poll)
 752 {
 753         zval                    *r_array, *e_array, *dont_poll_array;
 754         MYSQLND                 **new_r_array = NULL, **new_e_array = NULL, **new_dont_poll_array = NULL;
 755         zend_long                       sec = 0, usec = 0;
 756         enum_func_status ret;
 757         int                     desc_num;
 758 
 759         if (zend_parse_parameters(ZEND_NUM_ARGS(), "a!a!al|l", &r_array, &e_array, &dont_poll_array, &sec, &usec) == FAILURE) {
 760                 return;
 761         }
 762         if (sec < 0 || usec < 0) {
 763                 php_error_docref(NULL, E_WARNING, "Negative values passed for sec and/or usec");
 764                 RETURN_FALSE;
 765         }
 766 
 767         if (!r_array && !e_array) {
 768                 php_error_docref(NULL, E_WARNING, "No stream arrays were passed");
 769                 RETURN_FALSE;
 770         }
 771 
 772         if (r_array != NULL) {
 773                 mysqlnd_zval_array_to_mysqlnd_array(r_array, &new_r_array);
 774         }
 775         if (e_array != NULL) {
 776                 mysqlnd_zval_array_to_mysqlnd_array(e_array, &new_e_array);
 777         }
 778 
 779         ret = mysqlnd_poll(new_r_array, new_e_array, &new_dont_poll_array, sec, usec, &desc_num);
 780 
 781         mysqlnd_dont_poll_zval_array_from_mysqlnd_array(r_array != NULL ? new_dont_poll_array:NULL, r_array, dont_poll_array);
 782 
 783         if (r_array != NULL) {
 784                 mysqlnd_zval_array_from_mysqlnd_array(new_r_array, r_array);
 785         }
 786         if (e_array != NULL) {
 787                 mysqlnd_zval_array_from_mysqlnd_array(new_e_array, e_array);
 788         }
 789 
 790         if (new_dont_poll_array) {
 791                 efree(new_dont_poll_array);
 792         }
 793         if (new_r_array) {
 794                 efree(new_r_array);
 795         }
 796         if (new_e_array) {
 797                 efree(new_e_array);
 798         }
 799         if (ret == PASS) {
 800                 RETURN_LONG(desc_num);
 801         } else {
 802                 RETURN_FALSE;
 803         }
 804 }
 805 /* }}} */
 806 
 807 /* {{{ proto int mysqli_reap_async_query(object link) U
 808    Poll connections */
 809 PHP_FUNCTION(mysqli_reap_async_query)
 810 {
 811         MY_MYSQL                *mysql;
 812         zval                    *mysql_link;
 813         MYSQLI_RESOURCE         *mysqli_resource;
 814         MYSQL_RES                       *result = NULL;
 815 
 816         if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
 817                 return;
 818         }
 819 
 820         MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
 821 
 822         if (FAIL == mysqlnd_reap_async_query(mysql->mysql)) {
 823                 RETURN_FALSE;
 824         }
 825 
 826         if (!mysql_field_count(mysql->mysql)) {
 827                 /* no result set - not a SELECT */
 828                 if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
 829 /*                      php_mysqli_report_index("n/a", mysqli_server_status(mysql->mysql)); */
 830                 }
 831                 RETURN_TRUE;
 832         }
 833 
 834         switch (mysql->async_result_fetch_type) {
 835                 case MYSQLI_STORE_RESULT:
 836                         result = mysql_store_result(mysql->mysql);
 837                         break;
 838                 case MYSQLI_USE_RESULT:
 839                         result = mysql_use_result(mysql->mysql);
 840                         break;
 841         }
 842 
 843         if (!result) {
 844                 php_mysqli_throw_sql_exception((char *)mysql_sqlstate(mysql->mysql), mysql_errno(mysql->mysql),
 845                                                                                 "%s", mysql_error(mysql->mysql));
 846                 RETURN_FALSE;
 847         }
 848 
 849         if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
 850 /*              php_mysqli_report_index("n/a", mysqli_server_status(mysql->mysql)); */
 851         }
 852 
 853         mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
 854         mysqli_resource->ptr = (void *)result;
 855         mysqli_resource->status = MYSQLI_STATUS_VALID;
 856         MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_result_class_entry);
 857 }
 858 /* }}} */
 859 
 860 /* {{{ proto object mysqli_stmt_get_result(object link) U
 861    Buffer result set on client */
 862 PHP_FUNCTION(mysqli_stmt_get_result)
 863 {
 864         MYSQL_RES               *result;
 865         MYSQLI_RESOURCE *mysqli_resource;
 866         MY_STMT                 *stmt;
 867         zval                    *mysql_stmt;
 868 
 869         if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
 870                 return;
 871         }
 872         MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
 873 
 874         if (!(result = mysqlnd_stmt_get_result(stmt->stmt))) {
 875                 MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
 876                 RETURN_FALSE;
 877         }
 878 
 879         mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
 880         mysqli_resource->ptr = (void *)result;
 881         mysqli_resource->status = MYSQLI_STATUS_VALID;
 882         MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_result_class_entry);
 883 }
 884 /* }}} */
 885 #endif
 886 
 887 /* {{{ proto object mysqli_get_warnings(object link) */
 888 PHP_FUNCTION(mysqli_get_warnings)
 889 {
 890         MY_MYSQL                        *mysql;
 891         zval                            *mysql_link;
 892         MYSQLI_RESOURCE         *mysqli_resource;
 893         MYSQLI_WARNING          *w;
 894 
 895         if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
 896                 return;
 897         }
 898         MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
 899 
 900         if (mysql_warning_count(mysql->mysql)) {
 901 #ifdef MYSQLI_USE_MYSQLND
 902                 w = php_get_warnings(mysql->mysql->data);
 903 #else
 904                 w = php_get_warnings(mysql->mysql);
 905 #endif
 906         } else {
 907                 RETURN_FALSE;
 908         }
 909         mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
 910         mysqli_resource->ptr = mysqli_resource->info = (void *)w;
 911         mysqli_resource->status = MYSQLI_STATUS_VALID;
 912         MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_warning_class_entry);
 913 }
 914 /* }}} */
 915 
 916 /* {{{ proto object mysqli_stmt_get_warnings(object link) */
 917 PHP_FUNCTION(mysqli_stmt_get_warnings)
 918 {
 919         MY_STMT                         *stmt;
 920         zval                            *stmt_link;
 921         MYSQLI_RESOURCE         *mysqli_resource;
 922         MYSQLI_WARNING          *w;
 923 
 924         if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &stmt_link, mysqli_stmt_class_entry) == FAILURE) {
 925                 return;
 926         }
 927         MYSQLI_FETCH_RESOURCE_STMT(stmt, stmt_link, MYSQLI_STATUS_VALID);
 928 
 929         if (mysqli_stmt_warning_count(stmt->stmt)) {
 930                 w = php_get_warnings(mysqli_stmt_get_connection(stmt->stmt));
 931         } else {
 932                 RETURN_FALSE;
 933         }
 934         mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
 935         mysqli_resource->ptr = mysqli_resource->info = (void *)w;
 936         mysqli_resource->status = MYSQLI_STATUS_VALID;
 937         MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_warning_class_entry);
 938 }
 939 /* }}} */
 940 
 941 #ifdef HAVE_MYSQLI_SET_CHARSET
 942 /* {{{ proto bool mysqli_set_charset(object link, string csname)
 943    sets client character set */
 944 PHP_FUNCTION(mysqli_set_charset)
 945 {
 946         MY_MYSQL        *mysql;
 947         zval            *mysql_link;
 948         char            *cs_name;
 949         size_t          csname_len;
 950 
 951         if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &mysql_link, mysqli_link_class_entry, &cs_name, &csname_len) == FAILURE) {
 952                 return;
 953         }
 954         MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
 955 
 956         if (mysql_set_character_set(mysql->mysql, cs_name)) {
 957                 RETURN_FALSE;
 958         }
 959         RETURN_TRUE;
 960 }
 961 /* }}} */
 962 #endif
 963 
 964 #ifdef HAVE_MYSQLI_GET_CHARSET
 965 /* {{{ proto object mysqli_get_charset(object link) U
 966    returns a character set object */
 967 PHP_FUNCTION(mysqli_get_charset)
 968 {
 969         MY_MYSQL                                *mysql;
 970         zval                                    *mysql_link;
 971         const char                              *name = NULL, *collation = NULL, *dir = NULL, *comment = NULL;
 972         uint                                    minlength, maxlength, number, state;
 973 #if !defined(MYSQLI_USE_MYSQLND)
 974         MY_CHARSET_INFO                 cs;
 975 #else
 976         const MYSQLND_CHARSET   *cs;
 977 #endif
 978 
 979         if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
 980                 return;
 981         }
 982         MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
 983 
 984 
 985 #if !defined(MYSQLI_USE_MYSQLND)
 986         mysql_get_character_set_info(mysql->mysql, &cs);
 987         name = (char *)cs.csname;
 988         collation = (char *)cs.name;
 989         dir = (char *)cs.dir;
 990         minlength = cs.mbminlen;
 991         maxlength = cs.mbmaxlen;
 992         number = cs.number;
 993         state = cs.state;
 994         comment = cs.comment;
 995 #else
 996         cs = mysql->mysql->data->charset;
 997         if (!cs) {
 998                 php_error_docref(NULL, E_WARNING, "The connection has no charset associated");
 999                 RETURN_NULL();
1000         }
1001         name = cs->name;
1002         collation = cs->collation;
1003         minlength = cs->char_minlen;
1004         maxlength = cs->char_maxlen;
1005         number = cs->nr;
1006         comment = cs->comment;
1007         state = 1;      /* all charsets are compiled in */
1008 #endif
1009         object_init(return_value);
1010 
1011         add_property_string(return_value, "charset", (name) ? (char *)name : "");
1012         add_property_string(return_value, "collation",(collation) ? (char *)collation : "");
1013         add_property_string(return_value, "dir", (dir) ? (char *)dir : "");
1014         add_property_long(return_value, "min_length", minlength);
1015         add_property_long(return_value, "max_length", maxlength);
1016         add_property_long(return_value, "number", number);
1017         add_property_long(return_value, "state", state);
1018         add_property_string(return_value, "comment", (comment) ? (char *)comment : "");
1019 }
1020 /* }}} */
1021 #endif
1022 
1023 #if !defined(MYSQLI_USE_MYSQLND)
1024 extern char * mysqli_escape_string_for_tx_name_in_comment(const char * const name);
1025 
1026 /* {{{ proto bool mysqli_begin_transaction_libmysql */
1027 static int mysqli_begin_transaction_libmysql(MYSQL * conn, const unsigned int mode, const char * const name)
1028 {
1029         int ret;
1030         zend_bool err = FALSE;
1031         smart_str tmp_str = {0};
1032         if (mode & TRANS_START_WITH_CONSISTENT_SNAPSHOT) {
1033                 if (tmp_str.s) {
1034                         smart_str_appendl(&tmp_str, ", ", sizeof(", ") - 1);
1035                 }
1036                 smart_str_appendl(&tmp_str, "WITH CONSISTENT SNAPSHOT", sizeof("WITH CONSISTENT SNAPSHOT") - 1);
1037         }
1038         if (mode & (TRANS_START_READ_WRITE | TRANS_START_READ_ONLY)) {
1039                 if (mysql_get_server_version(conn) < 50605L) {
1040                         php_error_docref(NULL, E_WARNING, "This server version doesn't support 'READ WRITE' and 'READ ONLY'. Minimum 5.6.5 is required");
1041                         err = TRUE;
1042                 } else if (mode & TRANS_START_READ_WRITE) {
1043                         if (tmp_str.s) {
1044                                 smart_str_appendl(&tmp_str, ", ", sizeof(", ") - 1);
1045                         }
1046                         smart_str_appendl(&tmp_str, "READ WRITE", sizeof("READ WRITE") - 1);
1047                 } else if (mode & TRANS_START_READ_ONLY) {
1048                         if (tmp_str.s) {
1049                                 smart_str_appendl(&tmp_str, ", ", sizeof(", ") - 1);
1050                         }
1051                         smart_str_appendl(&tmp_str, "READ ONLY", sizeof("READ ONLY") - 1);
1052                 }
1053         }
1054         smart_str_0(&tmp_str);
1055 
1056         if (err == FALSE){
1057                 char * name_esc = mysqli_escape_string_for_tx_name_in_comment(name);
1058                 char * query;
1059                 unsigned int query_len = spprintf(&query, 0, "START TRANSACTION%s %s",
1060                                                                                   name_esc? name_esc:"", tmp_str.s? ZSTR_VAL(tmp_str.s):"");
1061 
1062                 smart_str_free(&tmp_str);
1063                 if (name_esc) {
1064                         efree(name_esc);
1065                 }
1066 
1067                 ret = mysql_real_query(conn, query, query_len);
1068                 efree(query);
1069         }
1070         return ret;
1071 }
1072 /* }}} */
1073 #endif
1074 
1075 /* {{{ proto bool mysqli_begin_transaction(object link, [int flags [, string name]])
1076    Starts a transaction */
1077 PHP_FUNCTION(mysqli_begin_transaction)
1078 {
1079         MY_MYSQL        *mysql;
1080         zval            *mysql_link;
1081         zend_long               flags = TRANS_START_NO_OPT;
1082         char *          name = NULL;
1083         size_t                  name_len = -1;
1084         zend_bool       err = FALSE;
1085 
1086         if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|ls", &mysql_link, mysqli_link_class_entry, &flags, &name, &name_len) == FAILURE) {
1087                 return;
1088         }
1089         MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1090         if (flags < 0) {
1091                 php_error_docref(NULL, E_WARNING, "Invalid value for parameter flags (%pd)", flags);
1092                 err = TRUE;
1093         }
1094         if (!name_len) {
1095                 php_error_docref(NULL, E_WARNING, "Savepoint name cannot be empty");
1096                 err = TRUE;
1097         }
1098         if (TRUE == err) {
1099                 RETURN_FALSE;
1100         }
1101 
1102 #if !defined(MYSQLI_USE_MYSQLND)
1103         if (mysqli_begin_transaction_libmysql(mysql->mysql, flags, name)) {
1104                 RETURN_FALSE;
1105         }
1106 #else
1107         if (FAIL == mysqlnd_begin_transaction(mysql->mysql, flags, name)) {
1108                 RETURN_FALSE;
1109         }
1110 #endif
1111         RETURN_TRUE;
1112 }
1113 /* }}} */
1114 
1115 #if !defined(MYSQLI_USE_MYSQLND)
1116 /* {{{ proto bool mysqli_savepoint_libmysql */
1117 static int mysqli_savepoint_libmysql(MYSQL * conn, const char * const name, zend_bool release)
1118 {
1119         int ret;
1120         char * query;
1121         unsigned int query_len = spprintf(&query, 0, release? "RELEASE SAVEPOINT `%s`":"SAVEPOINT `%s`", name);
1122         ret = mysql_real_query(conn, query, query_len);
1123         efree(query);
1124         return ret;
1125 }
1126 /* }}} */
1127 #endif
1128 
1129 /* {{{ proto bool mysqli_savepoint(object link, string name)
1130    Starts a transaction */
1131 PHP_FUNCTION(mysqli_savepoint)
1132 {
1133         MY_MYSQL        *mysql;
1134         zval            *mysql_link;
1135         char *          name = NULL;
1136         size_t                  name_len = -1;
1137 
1138         if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &mysql_link, mysqli_link_class_entry, &name, &name_len) == FAILURE) {
1139                 return;
1140         }
1141         MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1142         if (!name || !name_len) {
1143                 php_error_docref(NULL, E_WARNING, "Savepoint name cannot be empty");
1144                 RETURN_FALSE;
1145         }
1146 
1147 #if !defined(MYSQLI_USE_MYSQLND)
1148         if (mysqli_savepoint_libmysql(mysql->mysql, name, FALSE)) {
1149 #else
1150         if (FAIL == mysqlnd_savepoint(mysql->mysql, name)) {
1151 #endif
1152                 RETURN_FALSE;
1153         }
1154         RETURN_TRUE;
1155 }
1156 /* }}} */
1157 
1158 /* {{{ proto bool mysqli_release_savepoint(object link, string name)
1159    Starts a transaction */
1160 PHP_FUNCTION(mysqli_release_savepoint)
1161 {
1162         MY_MYSQL        *mysql;
1163         zval            *mysql_link;
1164         char *          name = NULL;
1165         size_t                  name_len = -1;
1166 
1167         if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &mysql_link, mysqli_link_class_entry, &name, &name_len) == FAILURE) {
1168                 return;
1169         }
1170         MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1171         if (!name || !name_len) {
1172                 php_error_docref(NULL, E_WARNING, "Savepoint name cannot be empty");
1173                 RETURN_FALSE;
1174         }
1175 #if !defined(MYSQLI_USE_MYSQLND)
1176         if (mysqli_savepoint_libmysql(mysql->mysql, name, TRUE)) {
1177 #else
1178         if (FAIL == mysqlnd_savepoint(mysql->mysql, name)) {
1179 #endif
1180                 RETURN_FALSE;
1181         }
1182         RETURN_TRUE;
1183 }
1184 /* }}} */
1185 
1186 /* {{{ proto bool mysqli_get_links_stats()
1187    Returns information about open and cached links */
1188 PHP_FUNCTION(mysqli_get_links_stats)
1189 {
1190         if (ZEND_NUM_ARGS()) {
1191                 php_error_docref(NULL, E_WARNING, "no parameters expected");
1192                 return;
1193         }
1194         array_init(return_value);
1195         add_assoc_long_ex(return_value, "total", sizeof("total") - 1, MyG(num_links));
1196         add_assoc_long_ex(return_value, "active_plinks", sizeof("active_plinks") - 1, MyG(num_active_persistent));
1197         add_assoc_long_ex(return_value, "cached_plinks", sizeof("cached_plinks") - 1, MyG(num_inactive_persistent));
1198 }
1199 /* }}} */
1200 
1201 
1202 /*
1203  * Local variables:
1204  * tab-width: 4
1205  * c-basic-offset: 4
1206  * End:
1207  * vim600: noet sw=4 ts=4 fdm=marker
1208  * vim<600: noet sw=4 ts=4
1209  */

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