PageRenderTime 110ms CodeModel.GetById 17ms app.highlight 80ms RepoModel.GetById 1ms app.codeStats 1ms

/php5/ext/mysqli/mysqli_api.c

http://github.com/vpj/PHP-Extension-API
C | 2421 lines | 1709 code | 352 blank | 360 comment | 359 complexity | f2fd859e37d1ce473d21251f50f58529 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/*
   2  +----------------------------------------------------------------------+
   3  | PHP Version 5                                                        |
   4  +----------------------------------------------------------------------+
   5  | Copyright (c) 1997-2009 The PHP Group                                |
   6  +----------------------------------------------------------------------+
   7  | This source file is subject to version 3.01 of the PHP license,      |
   8  | that is bundled with this package in the file LICENSE, and is        |
   9  | available through the world-wide-web at the following url:           |
  10  | http://www.php.net/license/3_01.txt                                  |
  11  | If you did not receive a copy of the PHP license and are unable to   |
  12  | obtain it through the world-wide-web, please send a note to          |
  13  | license@php.net so we can mail you a copy immediately.               |
  14  +----------------------------------------------------------------------+
  15  | Authors: Georg Richter <georg@php.net>                               |
  16  |          Andrey Hristov <andrey@php.net>                             |
  17  |          Ulf Wendel <uw@php.net>                                     |
  18  +----------------------------------------------------------------------+
  19
  20  $Id: mysqli_api.c,v 1.118.2.22.2.16.2.24 2009/01/22 21:01:56 johannes Exp $ 
  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 "php_globals.h"
  32#include "ext/standard/info.h"
  33#include "php_mysqli_structs.h"
  34
  35/* {{{ proto mixed mysqli_affected_rows(object link)
  36   Get number of affected rows in previous MySQL operation */
  37PHP_FUNCTION(mysqli_affected_rows)
  38{
  39	MY_MYSQL 		*mysql;
  40	zval  			*mysql_link;
  41	my_ulonglong	rc;
  42
  43	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
  44		return;
  45	}
  46
  47	MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link", MYSQLI_STATUS_VALID);
  48
  49	rc = mysql_affected_rows(mysql->mysql);
  50	if (rc == (my_ulonglong) -1) {
  51		RETURN_LONG(-1);
  52	}
  53	MYSQLI_RETURN_LONG_LONG(rc);
  54}
  55/* }}} */
  56
  57
  58/* {{{ proto bool mysqli_autocommit(object link, bool mode)
  59   Turn auto commit on or of */
  60PHP_FUNCTION(mysqli_autocommit)
  61{
  62	MY_MYSQL	*mysql;
  63	zval		*mysql_link;
  64	zend_bool	automode;
  65
  66	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ob", &mysql_link, mysqli_link_class_entry, &automode) == FAILURE) {
  67		return;
  68	}
  69	MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link", MYSQLI_STATUS_VALID);
  70
  71	if (mysql_autocommit(mysql->mysql, (my_bool)automode)) {
  72		RETURN_FALSE;
  73	}
  74	RETURN_TRUE;
  75}
  76/* }}} */
  77
  78/* {{{ mysqli_stmt_bind_param_do_bind */
  79#ifndef MYSQLI_USE_MYSQLND
  80static
  81int mysqli_stmt_bind_param_do_bind(MY_STMT *stmt, unsigned int argc, unsigned int num_vars,
  82								   zval ***args, unsigned int start, const char * const types TSRMLS_DC)
  83{
  84	int				i, ofs;
  85	MYSQL_BIND		*bind;
  86	unsigned long	rc;
  87
  88	/* prevent leak if variables are already bound */
  89	if (stmt->param.var_cnt) {
  90		php_free_stmt_bind_buffer(stmt->param, FETCH_SIMPLE);
  91	}
  92
  93	stmt->param.is_null = ecalloc(num_vars, sizeof(char));
  94	bind = (MYSQL_BIND *) ecalloc(num_vars, sizeof(MYSQL_BIND));
  95
  96	ofs = 0;
  97	for (i = start; i < argc; i++) {
  98
  99		/* set specified type */
 100		switch (types[ofs]) {
 101			case 'd': /* Double */
 102				bind[ofs].buffer_type = MYSQL_TYPE_DOUBLE;
 103				bind[ofs].buffer = &Z_DVAL_PP(args[i]);
 104				bind[ofs].is_null = &stmt->param.is_null[ofs];
 105				break;
 106
 107			case 'i': /* Integer */
 108#if SIZEOF_LONG==8
 109				bind[ofs].buffer_type = MYSQL_TYPE_LONGLONG;
 110#elif SIZEOF_LONG==4
 111				bind[ofs].buffer_type = MYSQL_TYPE_LONG;
 112#endif
 113				bind[ofs].buffer = &Z_LVAL_PP(args[i]);
 114				bind[ofs].is_null = &stmt->param.is_null[ofs];
 115				break;
 116
 117			case 'b': /* Blob (send data) */
 118				bind[ofs].buffer_type = MYSQL_TYPE_LONG_BLOB;
 119				/* don't initialize is_null and length to 0 because we use ecalloc */
 120				break;
 121
 122			case 's': /* string */
 123				bind[ofs].buffer_type = MYSQL_TYPE_VAR_STRING;
 124				/* don't initialize buffer and buffer_length because we use ecalloc */
 125				bind[ofs].is_null = &stmt->param.is_null[ofs];
 126				break;
 127
 128			default:
 129				php_error_docref(NULL TSRMLS_CC, E_WARNING, "Undefined fieldtype %c (parameter %d)", types[ofs], i+1);
 130				rc = 1;
 131				goto end_1;
 132		}
 133		ofs++;
 134	}
 135	rc = mysql_stmt_bind_param(stmt->stmt, bind);
 136
 137end_1:
 138	if (rc) {
 139		efree(stmt->param.is_null);
 140	} else {
 141		stmt->param.var_cnt = num_vars;
 142		stmt->param.vars = (zval **)safe_emalloc(num_vars, sizeof(zval), 0);
 143		for (i = 0; i < num_vars; i++) {
 144			if (bind[i].buffer_type  != MYSQL_TYPE_LONG_BLOB) {
 145				Z_ADDREF_P(*args[i+start]);
 146				stmt->param.vars[i] = *args[i+start];
 147			} else {
 148				stmt->param.vars[i] = NULL;
 149			}
 150		}
 151	}
 152	efree(bind);
 153
 154	return rc;
 155}
 156#else
 157static
 158int mysqli_stmt_bind_param_do_bind(MY_STMT *stmt, unsigned int argc, unsigned int num_vars,
 159								   zval ***args, unsigned int start, const char * const types TSRMLS_DC)
 160{
 161	int					i;
 162	MYSQLND_PARAM_BIND	*params;
 163	enum_func_status	ret = FAIL;
 164
 165	/* If no params -> skip binding and return directly */
 166	if (argc == start) {
 167		return PASS;
 168	}
 169	params = safe_emalloc(argc - start, sizeof(MYSQLND_PARAM_BIND), 0);
 170	for (i = 0; i < (argc - start); i++) {
 171		zend_uchar type;
 172		switch (types[i]) {
 173			case 'd': /* Double */
 174				type = MYSQL_TYPE_DOUBLE;
 175				break;
 176			case 'i': /* Integer */
 177#if SIZEOF_LONG==8
 178				type = MYSQL_TYPE_LONGLONG;
 179#elif SIZEOF_LONG==4
 180				type = MYSQL_TYPE_LONG;
 181#endif
 182				break;
 183			case 'b': /* Blob (send data) */
 184				type = MYSQL_TYPE_LONG_BLOB;
 185				break;
 186			case 's': /* string */
 187				type = MYSQL_TYPE_VAR_STRING;
 188				break;
 189			default:
 190				/* We count parameters from 1 */
 191				php_error_docref(NULL TSRMLS_CC, E_WARNING, "Undefined fieldtype %c (parameter %d)", types[i], i + start + 1);
 192				ret = FAIL;
 193				efree(params);
 194				goto end;
 195		}
 196		params[i].zv = *(args[i + start]);
 197		params[i].type = type;
 198	}
 199	ret = mysqlnd_stmt_bind_param(stmt->stmt, params);
 200
 201end:
 202	return ret;
 203}
 204#endif
 205/* }}} */
 206
 207/* {{{ proto bool mysqli_stmt_bind_param(object stmt, string types, mixed variable [,mixed,....]) U
 208   Bind variables to a prepared statement as parameters */
 209PHP_FUNCTION(mysqli_stmt_bind_param)
 210{
 211	zval			***args;
 212	int				argc = ZEND_NUM_ARGS();
 213	int				num_vars;
 214	int				start = 2;
 215	MY_STMT			*stmt;
 216	zval			*mysql_stmt;
 217	char			*types;
 218	int				types_len;
 219	unsigned long	rc;
 220
 221	/* calculate and check number of parameters */
 222	if (argc < 2) {
 223		/* there has to be at least one pair */
 224		WRONG_PARAM_COUNT;
 225	}
 226
 227	if (zend_parse_method_parameters((getThis()) ? 1:2 TSRMLS_CC, getThis(), "Os", &mysql_stmt, mysqli_stmt_class_entry,
 228									&types, &types_len) == FAILURE) {
 229		return;	
 230	}
 231
 232	MYSQLI_FETCH_RESOURCE(stmt, MY_STMT *, &mysql_stmt, "mysqli_stmt", MYSQLI_STATUS_VALID);
 233
 234	num_vars = argc - 1;
 235	if (getThis()) {
 236		start = 1;
 237	} else {
 238		/* ignore handle parameter in procedural interface*/
 239		--num_vars;
 240	}
 241	if (!types_len) {
 242		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid type or no types specified");
 243		RETURN_FALSE;
 244	}
 245
 246	if (types_len != argc - start) {
 247		/* number of bind variables doesn't match number of elements in type definition string */
 248		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number of elements in type definition string doesn't match number of bind variables");
 249		RETURN_FALSE;
 250	}
 251
 252	if (types_len != mysql_stmt_param_count(stmt->stmt)) {
 253		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number of variables doesn't match number of parameters in prepared statement");
 254		RETURN_FALSE;
 255	}
 256
 257	args = (zval ***)safe_emalloc(argc, sizeof(zval **), 0);
 258
 259	if (zend_get_parameters_array_ex(argc, args) == FAILURE) {
 260		zend_wrong_param_count(TSRMLS_C); 
 261		rc = 1;
 262	} else {
 263		rc = mysqli_stmt_bind_param_do_bind(stmt, argc, num_vars, args, start, types TSRMLS_CC);
 264		MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
 265	}
 266
 267	efree(args);
 268
 269	RETURN_BOOL(!rc);
 270}
 271/* }}} */
 272
 273/* {{{ mysqli_stmt_bind_result_do_bind */
 274#ifndef MYSQLI_USE_MYSQLND
 275/* TODO:
 276   do_alloca, free_alloca
 277*/
 278static int
 279mysqli_stmt_bind_result_do_bind(MY_STMT *stmt, zval ***args, unsigned int argc, unsigned int start TSRMLS_DC)
 280{
 281	MYSQL_BIND	*bind;
 282	int			i, ofs;
 283	int			var_cnt = argc - start;
 284	long		col_type;
 285	ulong		rc;
 286
 287	/* prevent leak if variables are already bound */
 288	if (stmt->result.var_cnt) {
 289		php_free_stmt_bind_buffer(stmt->result, FETCH_RESULT);
 290	}
 291
 292	bind = (MYSQL_BIND *)ecalloc(var_cnt, sizeof(MYSQL_BIND));
 293	{
 294		int size;
 295		char *p= emalloc(size= var_cnt * (sizeof(char) + sizeof(VAR_BUFFER)));
 296		stmt->result.buf = (VAR_BUFFER *) p;
 297		stmt->result.is_null = p + var_cnt * sizeof(VAR_BUFFER);
 298		memset(p, 0, size);
 299	}
 300
 301	for (i=start; i < var_cnt + start ; i++) {
 302		ofs = i - start;
 303		col_type = (stmt->stmt->fields) ? stmt->stmt->fields[ofs].type : MYSQL_TYPE_STRING;
 304
 305		switch (col_type) {
 306			case MYSQL_TYPE_DOUBLE:
 307			case MYSQL_TYPE_FLOAT:
 308				convert_to_double_ex(args[i]);
 309				stmt->result.buf[ofs].type = IS_DOUBLE;
 310				stmt->result.buf[ofs].buflen = sizeof(double);
 311
 312				/* allocate buffer for double */
 313				stmt->result.buf[ofs].val = (char *)emalloc(sizeof(double));
 314				bind[ofs].buffer_type = MYSQL_TYPE_DOUBLE;
 315				bind[ofs].buffer = stmt->result.buf[ofs].val;
 316				bind[ofs].is_null = &stmt->result.is_null[ofs];
 317				break;
 318
 319			case MYSQL_TYPE_NULL:
 320				stmt->result.buf[ofs].type = IS_NULL;
 321				/*
 322				  don't initialize to 0 :
 323				  1. stmt->result.buf[ofs].buflen
 324				  2. bind[ofs].buffer
 325				  3. bind[ofs].buffer_length
 326				  because memory was allocated with ecalloc
 327				*/
 328				bind[ofs].buffer_type = MYSQL_TYPE_NULL;
 329				bind[ofs].is_null = &stmt->result.is_null[ofs];
 330				break;
 331
 332			case MYSQL_TYPE_SHORT:
 333			case MYSQL_TYPE_TINY:
 334			case MYSQL_TYPE_LONG:
 335			case MYSQL_TYPE_INT24:
 336			case MYSQL_TYPE_YEAR:
 337				convert_to_long_ex(args[i]);
 338				stmt->result.buf[ofs].type = IS_LONG;
 339				/* don't set stmt->result.buf[ofs].buflen to 0, we used ecalloc */
 340				stmt->result.buf[ofs].val = (char *)emalloc(sizeof(int));
 341				bind[ofs].buffer_type = MYSQL_TYPE_LONG;
 342				bind[ofs].buffer = stmt->result.buf[ofs].val;
 343				bind[ofs].is_null = &stmt->result.is_null[ofs];
 344				bind[ofs].is_unsigned = (stmt->stmt->fields[ofs].flags & UNSIGNED_FLAG) ? 1 : 0;
 345				break;
 346
 347			case MYSQL_TYPE_LONGLONG:
 348#if MYSQL_VERSION_ID > 50002 || defined(MYSQLI_USE_MYSQLND)
 349			case MYSQL_TYPE_BIT:
 350#endif
 351				stmt->result.buf[ofs].type = IS_STRING; 
 352				stmt->result.buf[ofs].buflen = sizeof(my_ulonglong); 
 353				stmt->result.buf[ofs].val = (char *)emalloc(stmt->result.buf[ofs].buflen);
 354				bind[ofs].buffer_type = col_type;
 355				bind[ofs].buffer = stmt->result.buf[ofs].val;
 356				bind[ofs].is_null = &stmt->result.is_null[ofs];
 357				bind[ofs].buffer_length = stmt->result.buf[ofs].buflen;
 358				bind[ofs].is_unsigned = (stmt->stmt->fields[ofs].flags & UNSIGNED_FLAG) ? 1 : 0;
 359				break;
 360
 361			case MYSQL_TYPE_DATE:
 362			case MYSQL_TYPE_TIME:
 363			case MYSQL_TYPE_DATETIME:
 364			case MYSQL_TYPE_NEWDATE:
 365			case MYSQL_TYPE_VAR_STRING:
 366			case MYSQL_TYPE_STRING:
 367			case MYSQL_TYPE_TINY_BLOB:
 368			case MYSQL_TYPE_BLOB:
 369			case MYSQL_TYPE_MEDIUM_BLOB:
 370			case MYSQL_TYPE_LONG_BLOB:
 371			case MYSQL_TYPE_TIMESTAMP:
 372			case MYSQL_TYPE_DECIMAL:
 373#ifdef FIELD_TYPE_NEWDECIMAL
 374			case MYSQL_TYPE_NEWDECIMAL:
 375#endif
 376			{
 377#if MYSQL_VERSION_ID > 50099
 378				/* Changed to my_bool in MySQL 5.1. See MySQL Bug #16144 */
 379				my_bool tmp;
 380#else
 381				ulong tmp = 0;
 382#endif
 383				stmt->result.buf[ofs].type = IS_STRING;
 384				/*
 385					If the user has called $stmt->store_result() then we have asked
 386					max_length to be updated. this is done only for BLOBS because we don't want to allocate
 387					big chunkgs of memory 2^16 or 2^24 
 388				*/
 389				if (stmt->stmt->fields[ofs].max_length == 0 &&
 390					!mysql_stmt_attr_get(stmt->stmt, STMT_ATTR_UPDATE_MAX_LENGTH, &tmp) && !tmp)
 391				{
 392					/*
 393					  Allocate directly 256 because it's easier to allocate a bit more
 394					  than update max length even for text columns. Try SELECT UNION SELECT UNION with
 395					  different lengths and you will see that we get different lengths in stmt->stmt->fields[ofs].length
 396					  The just take 256 and saves us from realloc-ing.
 397					*/
 398					stmt->result.buf[ofs].buflen = 256;
 399				} else {
 400					/*
 401						the user has called store_result(). if he does not there is no way to determine the
 402						libmysql does not allow us to allocate 0 bytes for a buffer so we try 1
 403					*/
 404					if (!(stmt->result.buf[ofs].buflen = stmt->stmt->fields[ofs].max_length))
 405						++stmt->result.buf[ofs].buflen;
 406				}
 407				stmt->result.buf[ofs].val = (char *)emalloc(stmt->result.buf[ofs].buflen);
 408				bind[ofs].buffer_type = MYSQL_TYPE_STRING;
 409				bind[ofs].buffer = stmt->result.buf[ofs].val;
 410				bind[ofs].is_null = &stmt->result.is_null[ofs];
 411				bind[ofs].buffer_length = stmt->result.buf[ofs].buflen;
 412				bind[ofs].length = &stmt->result.buf[ofs].buflen;
 413				break;
 414			}
 415			default:
 416				php_error_docref(NULL TSRMLS_CC, E_WARNING, "Server returned unknown type %ld. Probably your client library is incompatible with the server version you use!", col_type);
 417				break;
 418		}
 419	}
 420
 421	rc = mysql_stmt_bind_result(stmt->stmt, bind);
 422	MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
 423
 424	if (rc) {
 425		/* dont close the statement or subsequent usage (for example ->execute()) will lead to crash */
 426		for (i=0; i < var_cnt ; i++) {
 427			if (stmt->result.buf[i].val) {
 428				efree(stmt->result.buf[i].val);
 429			}
 430		}
 431		/* Don't free stmt->result.is_null because is_null & buf are one block of memory  */
 432		efree(stmt->result.buf);
 433	} else {
 434		stmt->result.var_cnt = var_cnt;
 435		stmt->result.vars = (zval **)safe_emalloc((var_cnt), sizeof(zval), 0);
 436		for (i = start; i < var_cnt+start; i++) {
 437			ofs = i-start;
 438			Z_ADDREF_PP(args[i]);
 439			stmt->result.vars[ofs] = *args[i];
 440		}
 441	}
 442	efree(bind);
 443
 444	return rc;
 445}
 446#else
 447static int
 448mysqli_stmt_bind_result_do_bind(MY_STMT *stmt, zval ***args, unsigned int argc, unsigned int start TSRMLS_DC)
 449{
 450	unsigned int i;
 451	MYSQLND_RESULT_BIND *params;
 452
 453	params = safe_emalloc(argc - start, sizeof(MYSQLND_RESULT_BIND), 0);
 454	for (i = 0; i < (argc - start); i++) {
 455		params[i].zv = *(args[i + start]);
 456	}
 457	return mysqlnd_stmt_bind_result(stmt->stmt, params);
 458}
 459#endif
 460/* }}} */
 461
 462/* {{{ proto bool mysqli_stmt_bind_result(object stmt, mixed var, [,mixed, ...]) U
 463   Bind variables to a prepared statement for result storage */
 464PHP_FUNCTION(mysqli_stmt_bind_result)
 465{
 466	zval		***args;
 467	int			argc = ZEND_NUM_ARGS();
 468	int			start = 1;
 469	ulong		rc;
 470	MY_STMT		*stmt;
 471	zval		*mysql_stmt;
 472
 473	if (getThis()) {
 474		start = 0;
 475	}
 476
 477	if (zend_parse_method_parameters((getThis()) ? 0:1 TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
 478		return;	
 479	}
 480
 481	MYSQLI_FETCH_RESOURCE(stmt, MY_STMT *, &mysql_stmt, "mysqli_stmt", MYSQLI_STATUS_VALID);
 482
 483	if (argc < (getThis() ? 1 : 2)) {
 484		WRONG_PARAM_COUNT;
 485	}
 486
 487	if ((argc - start) != mysql_stmt_field_count(stmt->stmt)) {
 488		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number of bind variables doesn't match number of fields in prepared statement");
 489		RETURN_FALSE;
 490	}
 491
 492	args = (zval ***)safe_emalloc(argc, sizeof(zval **), 0);
 493
 494	if (zend_get_parameters_array_ex(argc, args) == FAILURE) {
 495		efree(args);
 496		WRONG_PARAM_COUNT;
 497	}
 498
 499	rc = mysqli_stmt_bind_result_do_bind(stmt, args, argc, start TSRMLS_CC);
 500
 501	efree(args);
 502
 503	RETURN_BOOL(!rc);
 504}
 505/* }}} */
 506
 507/* {{{ proto bool mysqli_change_user(object link, string user, string password, string database)
 508   Change logged-in user of the active connection */
 509PHP_FUNCTION(mysqli_change_user)
 510{
 511	MY_MYSQL	*mysql;
 512	zval		*mysql_link = NULL;
 513	char		*user, *password, *dbname;
 514	int			user_len, password_len, dbname_len;
 515	ulong		rc;
 516
 517	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Osss", &mysql_link, mysqli_link_class_entry, &user, &user_len, &password, &password_len, &dbname, &dbname_len) == FAILURE) {
 518		return;
 519	}
 520	MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link", MYSQLI_STATUS_VALID);
 521
 522	rc = mysql_change_user(mysql->mysql, user, password, dbname);
 523	MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
 524
 525	if (rc) {
 526		RETURN_FALSE;
 527	}
 528
 529	RETURN_TRUE;
 530}
 531/* }}} */
 532
 533/* {{{ proto string mysqli_character_set_name(object link)
 534   Returns the name of the character set used for this connection */
 535PHP_FUNCTION(mysqli_character_set_name)
 536{
 537	MY_MYSQL	*mysql;
 538	zval		*mysql_link;
 539
 540	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
 541		return;
 542	}
 543
 544	MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link", MYSQLI_STATUS_VALID);
 545
 546	RETURN_STRING((char *)mysql_character_set_name(mysql->mysql), 1);
 547}
 548/* }}} */
 549
 550/* {{{ proto bool mysqli_close(object link)
 551   Close connection */
 552PHP_FUNCTION(mysqli_close)
 553{
 554	zval		*mysql_link;
 555	MY_MYSQL	*mysql;
 556	
 557	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
 558		return;
 559	}
 560
 561	MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link", MYSQLI_STATUS_INITIALIZED);
 562
 563	if (!mysql->persistent) {
 564		mysqli_close(mysql->mysql, MYSQLI_CLOSE_EXPLICIT);
 565		mysql->mysql = NULL;
 566	} else {
 567		zend_rsrc_list_entry *le;
 568		if (zend_hash_find(&EG(persistent_list), mysql->hash_key, strlen(mysql->hash_key) + 1, (void **)&le) == SUCCESS) {
 569			if (Z_TYPE_P(le) == php_le_pmysqli()) {
 570				mysqli_plist_entry *plist = (mysqli_plist_entry *) le->ptr;
 571				zend_ptr_stack_push(&plist->free_links, mysql->mysql);
 572
 573				MyG(num_links)--;
 574				MyG(num_active_persistent)--;
 575				MyG(num_inactive_persistent)++;
 576			}
 577		}
 578	}
 579
 580	php_clear_mysql(mysql);
 581
 582	MYSQLI_CLEAR_RESOURCE(&mysql_link);
 583	efree(mysql);
 584	RETURN_TRUE;
 585}
 586/* }}} */
 587
 588/* {{{ proto bool mysqli_commit(object link)
 589   Commit outstanding actions and close transaction */
 590PHP_FUNCTION(mysqli_commit)
 591{
 592	MY_MYSQL	*mysql;
 593	zval		*mysql_link;
 594
 595	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
 596		return;
 597	}
 598	MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link", MYSQLI_STATUS_VALID);
 599	if (mysql_commit(mysql->mysql)) {
 600		RETURN_FALSE;
 601	}
 602	RETURN_TRUE;
 603}
 604/* }}} */
 605
 606/* {{{ proto bool mysqli_data_seek(object result, int offset)
 607   Move internal result pointer */
 608PHP_FUNCTION(mysqli_data_seek)
 609{
 610	MYSQL_RES	*result;
 611	zval		*mysql_result;
 612	long		offset;
 613
 614	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol", &mysql_result, mysqli_result_class_entry, &offset) == FAILURE) {
 615		return;
 616	}
 617
 618	MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, &mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
 619
 620	if (mysqli_result_is_unbuffered(result)) {
 621		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Function cannot be used with MYSQL_USE_RESULT");
 622		RETURN_FALSE;
 623	}
 624
 625	if (offset < 0 || offset >= mysql_num_rows(result)) {
 626		RETURN_FALSE;
 627	}
 628
 629	mysql_data_seek(result, offset);
 630	RETURN_TRUE;
 631}
 632/* }}} */
 633
 634/* {{{ proto void mysqli_debug(string debug) U
 635*/
 636PHP_FUNCTION(mysqli_debug)
 637{
 638	char	*debug;
 639	int		debug_len;
 640
 641	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &debug, &debug_len) == FAILURE) {
 642		return;
 643	}
 644	
 645	mysql_debug(debug);
 646	RETURN_TRUE;
 647}
 648/* }}} */
 649
 650
 651/* {{{ proto bool mysqli_dump_debug_info(object link)
 652*/
 653PHP_FUNCTION(mysqli_dump_debug_info)
 654{
 655	MY_MYSQL	*mysql;
 656	zval		*mysql_link;
 657
 658	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
 659		return;
 660	}
 661	MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link", MYSQLI_STATUS_VALID);
 662
 663	RETURN_BOOL(!mysql_dump_debug_info(mysql->mysql))
 664}
 665/* }}} */
 666
 667/* {{{ proto int mysqli_errno(object link)
 668   Returns the numerical value of the error message from previous MySQL operation */
 669PHP_FUNCTION(mysqli_errno)
 670{
 671	MY_MYSQL	*mysql;
 672	zval		*mysql_link;
 673
 674	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
 675		return;
 676	}
 677	MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link", MYSQLI_STATUS_VALID);
 678	RETURN_LONG(mysql_errno(mysql->mysql));
 679}
 680/* }}} */
 681
 682/* {{{ proto string mysqli_error(object link)
 683   Returns the text of the error message from previous MySQL operation */
 684PHP_FUNCTION(mysqli_error) 
 685{
 686	MY_MYSQL	*mysql;
 687	zval		*mysql_link;
 688
 689	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
 690		return;
 691	}
 692	MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link", MYSQLI_STATUS_VALID);
 693	RETURN_STRING((char *)mysql_error(mysql->mysql),1);
 694}
 695/* }}} */
 696
 697#ifndef MYSQLI_USE_MYSQLND
 698/* {{{ php_mysqli_stmt_copy_it */
 699static void
 700php_mysqli_stmt_copy_it(zval *** copies, zval *original, uint param_count, uint current)
 701{
 702	if (!*copies) {
 703		*copies = ecalloc(param_count, sizeof(zval *));					
 704	}
 705	MAKE_STD_ZVAL((*copies)[current]);
 706	*(*copies)[current] = *original;
 707	Z_SET_REFCOUNT_P((*copies)[current], 1);
 708	zval_copy_ctor((*copies)[current]);
 709}
 710/* }}} */
 711#endif
 712
 713/* {{{ proto bool mysqli_stmt_execute(object stmt)
 714   Execute a prepared statement */
 715PHP_FUNCTION(mysqli_stmt_execute)
 716{
 717	MY_STMT		*stmt;
 718	zval		*mysql_stmt;
 719#ifndef MYSQLI_USE_MYSQLND
 720	unsigned int	i;
 721	zval		**copies = NULL;
 722#endif
 723
 724	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
 725		return;
 726	}
 727	MYSQLI_FETCH_RESOURCE(stmt, MY_STMT *, &mysql_stmt, "mysqli_stmt", MYSQLI_STATUS_VALID);
 728
 729#ifndef MYSQLI_USE_MYSQLND
 730	if (stmt->param.var_cnt) {
 731		int j;
 732		for (i = 0; i < stmt->param.var_cnt; i++) {
 733			for (j = i + 1; j < stmt->param.var_cnt; j++) {
 734				/* Oops, someone binding the same variable - clone */
 735				if (stmt->param.vars[j] == stmt->param.vars[i]) {
 736					php_mysqli_stmt_copy_it(&copies, stmt->param.vars[i], stmt->param.var_cnt, i);
 737					break;
 738				}
 739			}
 740		}
 741	}
 742	for (i = 0; i < stmt->param.var_cnt; i++) {
 743		if (stmt->param.vars[i]) {
 744			if ( !(stmt->param.is_null[i] = (stmt->param.vars[i]->type == IS_NULL)) ) {
 745				zval *the_var = copies && copies[i]? copies[i]:stmt->param.vars[i];
 746				switch (stmt->stmt->params[i].buffer_type) {
 747					case MYSQL_TYPE_VAR_STRING:
 748						if (the_var == stmt->param.vars[i] && Z_TYPE_P(stmt->param.vars[i]) != IS_STRING) {
 749							php_mysqli_stmt_copy_it(&copies, stmt->param.vars[i], stmt->param.var_cnt, i);
 750							the_var = copies[i];
 751						}
 752						convert_to_string_ex(&the_var);
 753						stmt->stmt->params[i].buffer = Z_STRVAL_P(the_var);
 754						stmt->stmt->params[i].buffer_length = Z_STRLEN_P(the_var);
 755						break;
 756					case MYSQL_TYPE_DOUBLE:
 757						if (the_var == stmt->param.vars[i] && Z_TYPE_P(stmt->param.vars[i]) != IS_DOUBLE) {
 758							php_mysqli_stmt_copy_it(&copies, stmt->param.vars[i], stmt->param.var_cnt, i);
 759							the_var = copies[i];
 760						}
 761						convert_to_double_ex(&the_var);
 762						stmt->stmt->params[i].buffer = &Z_DVAL_P(the_var);
 763						break;
 764					case MYSQL_TYPE_LONGLONG:
 765					case MYSQL_TYPE_LONG:
 766						if (the_var == stmt->param.vars[i] && Z_TYPE_P(stmt->param.vars[i]) != IS_LONG) {
 767							php_mysqli_stmt_copy_it(&copies, stmt->param.vars[i], stmt->param.var_cnt, i);
 768							the_var = copies[i];
 769						}
 770						convert_to_long_ex(&the_var);
 771						stmt->stmt->params[i].buffer = &Z_LVAL_P(the_var);
 772						break;
 773					default:
 774						break;
 775				}
 776			}
 777		}
 778	}
 779#endif
 780
 781	if (mysql_stmt_execute(stmt->stmt)) {
 782		MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
 783		RETVAL_FALSE;
 784	} else {
 785		RETVAL_TRUE;
 786	}
 787
 788#ifndef MYSQLI_USE_MYSQLND
 789	if (copies) {
 790		for (i = 0; i < stmt->param.var_cnt; i++) {
 791			if (copies[i]) {
 792				zval_ptr_dtor(&copies[i]);
 793			}
 794		}
 795		efree(copies);
 796	}
 797#endif
 798
 799	if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
 800		php_mysqli_report_index(stmt->query, mysqli_stmt_server_status(stmt->stmt) TSRMLS_CC);
 801	}
 802}
 803/* }}} */
 804
 805#ifndef MYSQLI_USE_MYSQLND
 806/* {{{ void mysqli_stmt_fetch_libmysql
 807   Fetch results from a prepared statement into the bound variables */
 808void mysqli_stmt_fetch_libmysql(INTERNAL_FUNCTION_PARAMETERS)
 809{
 810	MY_STMT		*stmt;
 811	zval			*mysql_stmt;
 812	unsigned int	i;
 813	ulong			ret;
 814	unsigned int	uval;
 815	my_ulonglong	llval;
 816	
 817
 818	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
 819		return;
 820	}
 821	MYSQLI_FETCH_RESOURCE(stmt, MY_STMT *, &mysql_stmt, "mysqli_stmt", MYSQLI_STATUS_VALID);
 822	
 823	/* reset buffers */
 824	for (i = 0; i < stmt->result.var_cnt; i++) {
 825		if (stmt->result.buf[i].type == IS_STRING) {
 826			memset(stmt->result.buf[i].val, 0, stmt->result.buf[i].buflen);
 827		}
 828	}
 829	ret = mysql_stmt_fetch(stmt->stmt);
 830#ifdef MYSQL_DATA_TRUNCATED
 831	if (!ret || ret == MYSQL_DATA_TRUNCATED) {
 832#else
 833	if (!ret) {
 834#endif
 835		for (i = 0; i < stmt->result.var_cnt; i++) {
 836			/*
 837			  QQ: Isn't it quite better to call zval_dtor(). What if the user has
 838			  assigned a resource, or an array to the bound variable? We are going
 839			  to leak probably. zval_dtor() will handle also Unicode/Non-unicode mode.
 840			*/
 841			/* Even if the string is of length zero there is one byte alloced so efree() in all cases */
 842			if (Z_TYPE_P(stmt->result.vars[i]) == IS_STRING) {
 843				efree(stmt->result.vars[i]->value.str.val);
 844			}
 845			if (!stmt->result.is_null[i]) {
 846				switch (stmt->result.buf[i].type) {
 847					case IS_LONG:
 848						if ((stmt->stmt->fields[i].type == MYSQL_TYPE_LONG) 
 849						    && (stmt->stmt->fields[i].flags & UNSIGNED_FLAG))
 850						{
 851							/* unsigned int (11) */
 852							uval= *(unsigned int *) stmt->result.buf[i].val;
 853#if SIZEOF_LONG==4
 854							if (uval > INT_MAX) {
 855								char *tmp, *p;
 856								int j=10;
 857								tmp= emalloc(11);
 858								p= &tmp[9];
 859								do { 
 860									*p-- = (uval % 10) + 48;
 861									uval = uval / 10;
 862								} while (--j > 0);
 863								tmp[10]= '\0';
 864								/* unsigned int > INT_MAX is 10 digits - ALWAYS */
 865								ZVAL_STRINGL(stmt->result.vars[i], tmp, 10, 0);
 866								break;
 867							}
 868#endif
 869						}
 870						if (stmt->stmt->fields[i].flags & UNSIGNED_FLAG) { 
 871							ZVAL_LONG(stmt->result.vars[i], *(unsigned int *)stmt->result.buf[i].val);
 872						} else {
 873							ZVAL_LONG(stmt->result.vars[i], *(int *)stmt->result.buf[i].val);
 874						}
 875						break;
 876					case IS_DOUBLE:
 877						ZVAL_DOUBLE(stmt->result.vars[i], *(double *)stmt->result.buf[i].val);
 878						break;
 879					case IS_STRING:
 880						if (stmt->stmt->bind[i].buffer_type == MYSQL_TYPE_LONGLONG) {
 881							my_bool uns= (stmt->stmt->fields[i].flags & UNSIGNED_FLAG)? 1:0;
 882							llval= *(my_ulonglong *) stmt->result.buf[i].val;
 883#if SIZEOF_LONG==8
 884							if (uns && llval > 9223372036854775807L) {
 885#elif SIZEOF_LONG==4
 886							if ((uns && llval > L64(2147483647)) || 
 887								(!uns && (( L64(2147483647) < (my_longlong) llval) ||
 888								(L64(-2147483648) > (my_longlong) llval))))
 889							{
 890#endif
 891								char tmp[22];
 892								/* even though lval is declared as unsigned, the value
 893								 * may be negative. Therefor we cannot use MYSQLI_LLU_SPEC and must
 894								 * use MYSQLI_LL_SPEC.
 895								 */
 896								snprintf(tmp, sizeof(tmp), (stmt->stmt->fields[i].flags & UNSIGNED_FLAG)? MYSQLI_LLU_SPEC : MYSQLI_LL_SPEC, llval);
 897								ZVAL_STRING(stmt->result.vars[i], tmp, 1);
 898							} else {
 899								ZVAL_LONG(stmt->result.vars[i], llval);
 900							}
 901						}
 902#if MYSQL_VERSION_ID > 50002
 903						else if (stmt->stmt->bind[i].buffer_type == MYSQL_TYPE_BIT) {
 904							llval = *(my_ulonglong *)stmt->result.buf[i].val;
 905							ZVAL_LONG(stmt->result.vars[i], llval);
 906						}
 907#endif
 908						else {
 909#if defined(MYSQL_DATA_TRUNCATED) && MYSQL_VERSION_ID > 50002
 910							if (ret == MYSQL_DATA_TRUNCATED && *(stmt->stmt->bind[i].error) != 0) {
 911								/* result was truncated */
 912								ZVAL_STRINGL(stmt->result.vars[i], stmt->result.buf[i].val,
 913											 stmt->stmt->bind[i].buffer_length, 1);
 914							} else {
 915#else
 916							{
 917#endif
 918								ZVAL_STRINGL(stmt->result.vars[i], stmt->result.buf[i].val,
 919											 stmt->result.buf[i].buflen, 1);
 920							}
 921						}
 922						break;
 923					default:
 924						break;
 925				}
 926			} else {
 927				ZVAL_NULL(stmt->result.vars[i]);
 928			}
 929		}
 930	} else {
 931		MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
 932	}
 933
 934	switch (ret) {
 935		case 0:
 936#ifdef MYSQL_DATA_TRUNCATED
 937		/* according to SQL standard truncation (e.g. loss of precision is
 938		   not an error) - for detecting possible truncation you have to 
 939		   check mysqli_stmt_warning
 940		*/
 941		case MYSQL_DATA_TRUNCATED:
 942#endif
 943			RETURN_TRUE;
 944		break;
 945		case 1:
 946			RETURN_FALSE;
 947		break;
 948		default:
 949			RETURN_NULL();
 950		break;
 951	}
 952}
 953/* }}} */
 954#else
 955/* {{{ mixed mysqli_stmt_fetch_mysqlnd */
 956void mysqli_stmt_fetch_mysqlnd(INTERNAL_FUNCTION_PARAMETERS)
 957{
 958	MY_STMT		*stmt;
 959	zval		*mysql_stmt;
 960	zend_bool	fetched_anything;
 961
 962	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
 963		return;
 964	}
 965	MYSQLI_FETCH_RESOURCE(stmt, MY_STMT *, &mysql_stmt, "mysqli_stmt", MYSQLI_STATUS_VALID);
 966
 967	if (FAIL  == mysqlnd_stmt_fetch(stmt->stmt, &fetched_anything)) {
 968		RETURN_BOOL(FALSE);
 969	} else if (fetched_anything == TRUE) {
 970		RETURN_BOOL(TRUE);
 971	} else {
 972		RETURN_NULL();
 973	}
 974}
 975#endif
 976/* }}} */
 977
 978
 979/* {{{ proto mixed mysqli_stmt_fetch(object stmt) U
 980   Fetch results from a prepared statement into the bound variables */
 981PHP_FUNCTION(mysqli_stmt_fetch)
 982{
 983#if !defined(MYSQLI_USE_MYSQLND)
 984	mysqli_stmt_fetch_libmysql(INTERNAL_FUNCTION_PARAM_PASSTHRU);
 985#else
 986	mysqli_stmt_fetch_mysqlnd(INTERNAL_FUNCTION_PARAM_PASSTHRU);
 987#endif
 988}
 989/* }}} */
 990
 991/* {{{  php_add_field_properties */
 992static void php_add_field_properties(zval *value, const MYSQL_FIELD *field TSRMLS_DC)
 993{
 994	add_property_string(value, "name",(field->name ? field->name : ""), 1);
 995	add_property_string(value, "orgname",(field->org_name ? field->org_name : ""), 1);
 996	add_property_string(value, "table",(field->table ? field->table : ""), 1);
 997	add_property_string(value, "orgtable",(field->org_table ? field->org_table : ""), 1);
 998	add_property_string(value, "def",(field->def ? field->def : ""), 1);
 999
1000	add_property_long(value, "max_length", field->max_length);
1001	add_property_long(value, "length", field->length);
1002	add_property_long(value, "charsetnr", field->charsetnr);
1003	add_property_long(value, "flags", field->flags);
1004	add_property_long(value, "type", field->type);
1005	add_property_long(value, "decimals", field->decimals);
1006}
1007/* }}} */
1008
1009/* {{{ proto mixed mysqli_fetch_field (object result)
1010   Get column information from a result and return as an object */
1011PHP_FUNCTION(mysqli_fetch_field) 
1012{
1013	MYSQL_RES	*result;
1014	zval		*mysql_result;
1015	const MYSQL_FIELD	*field;
1016
1017	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
1018		return;
1019	}
1020
1021	MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, &mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1022
1023	if (!(field = mysql_fetch_field(result))) {
1024		RETURN_FALSE;
1025	}
1026
1027	object_init(return_value);
1028	php_add_field_properties(return_value, field TSRMLS_CC);
1029}
1030/* }}} */
1031
1032/* {{{ proto mixed mysqli_fetch_fields (object result)
1033   Return array of objects containing field meta-data */
1034PHP_FUNCTION(mysqli_fetch_fields) 
1035{
1036	MYSQL_RES	*result;
1037	zval		*mysql_result;
1038	zval		*obj;
1039
1040	unsigned int i;
1041
1042	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
1043		return;
1044	}
1045
1046	MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, &mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1047
1048	array_init(return_value);
1049
1050	for (i = 0; i < mysql_num_fields(result); i++) {
1051		const MYSQL_FIELD *field = mysql_fetch_field_direct(result, i);
1052
1053		MAKE_STD_ZVAL(obj);
1054		object_init(obj);
1055
1056		php_add_field_properties(obj, field TSRMLS_CC);
1057		add_index_zval(return_value, i, obj);
1058	}
1059}
1060/* }}} */
1061
1062/* {{{ proto mixed mysqli_fetch_field_direct (object result, int offset)
1063   Fetch meta-data for a single field */
1064PHP_FUNCTION(mysqli_fetch_field_direct) 
1065{
1066	MYSQL_RES	*result;
1067	zval		*mysql_result;
1068	const MYSQL_FIELD	*field;
1069	long		offset;
1070
1071	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol", &mysql_result, mysqli_result_class_entry, &offset) == FAILURE) {
1072		return;
1073	}
1074
1075	MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, &mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1076	
1077	if (offset < 0 || offset >= mysql_num_fields(result)) {
1078		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Field offset is invalid for resultset");
1079		RETURN_FALSE; 
1080	}
1081
1082	if (!(field = mysql_fetch_field_direct(result,offset))) {
1083		RETURN_FALSE;
1084	}
1085
1086	object_init(return_value);
1087	php_add_field_properties(return_value, field TSRMLS_CC);
1088}
1089/* }}} */
1090
1091/* {{{ proto mixed mysqli_fetch_lengths (object result)
1092   Get the length of each output in a result */
1093PHP_FUNCTION(mysqli_fetch_lengths) 
1094{
1095	MYSQL_RES		*result;
1096	zval			*mysql_result;
1097	unsigned int	i;
1098	unsigned long	*ret;
1099
1100	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
1101		return;
1102	}
1103
1104	MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, &mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1105
1106	if (!(ret = mysql_fetch_lengths(result))) {
1107		RETURN_FALSE;
1108	}
1109
1110	array_init(return_value);
1111
1112	for (i = 0; i < mysql_num_fields(result); i++) {
1113		add_index_long(return_value, i, ret[i]);
1114	}
1115}
1116/* }}} */
1117
1118/* {{{ proto array mysqli_fetch_row (object result)
1119   Get a result row as an enumerated array */
1120PHP_FUNCTION(mysqli_fetch_row) 
1121{
1122#if !defined(MYSQLI_USE_MYSQLND)
1123	php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, MYSQLI_NUM, 0);
1124#else
1125	MYSQL_RES	*result;
1126	zval		*mysql_result;
1127
1128	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
1129		return;
1130	}
1131	MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, &mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1132	mysqlnd_fetch_into(result, MYSQLND_FETCH_NUM, return_value, MYSQLND_MYSQLI); 
1133#endif
1134}
1135/* }}} */
1136
1137/* {{{ proto int mysqli_field_count(object link)
1138   Fetch the number of fields returned by the last query for the given link
1139*/
1140PHP_FUNCTION(mysqli_field_count)
1141{
1142	MY_MYSQL	*mysql;
1143	zval		*mysql_link;
1144
1145	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1146		return;
1147	}
1148	MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link", MYSQLI_STATUS_VALID);
1149
1150	RETURN_LONG(mysql_field_count(mysql->mysql));
1151}
1152/* }}} */
1153
1154/* {{{ proto int mysqli_field_seek(object result, int fieldnr)
1155   Set result pointer to a specified field offset
1156*/
1157PHP_FUNCTION(mysqli_field_seek)
1158{
1159	MYSQL_RES		*result;
1160	zval			*mysql_result;
1161	unsigned long	fieldnr;
1162
1163	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol", &mysql_result, mysqli_result_class_entry, &fieldnr) == FAILURE) {
1164		return;
1165	}
1166	MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, &mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1167
1168	if (fieldnr < 0 || fieldnr >= mysql_num_fields(result)) {
1169		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid field offset");
1170		RETURN_FALSE; 
1171	}
1172
1173	mysql_field_seek(result, fieldnr);
1174	RETURN_TRUE;
1175}
1176/* }}} */
1177
1178/* {{{ proto int mysqli_field_tell(object result)
1179   Get current field offset of result pointer */
1180PHP_FUNCTION(mysqli_field_tell)
1181{
1182	MYSQL_RES	*result;
1183	zval		*mysql_result;
1184
1185	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
1186		return;
1187	}
1188	MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, &mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1189
1190	RETURN_LONG(mysql_field_tell(result));
1191}
1192/* }}} */
1193
1194/* {{{ proto void mysqli_free_result(object result)
1195   Free query result memory for the given result handle */
1196PHP_FUNCTION(mysqli_free_result) 
1197{
1198	MYSQL_RES	*result;
1199	zval		*mysql_result;
1200
1201	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
1202		return;
1203	}
1204	MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, &mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1205
1206	mysqli_free_result(result, FALSE);
1207	MYSQLI_CLEAR_RESOURCE(&mysql_result);
1208}
1209/* }}} */
1210
1211/* {{{ proto string mysqli_get_client_info(void)
1212   Get MySQL client info */
1213PHP_FUNCTION(mysqli_get_client_info)
1214{
1215	RETURN_STRING((char *)mysql_get_client_info(), 1);
1216}
1217/* }}} */
1218
1219/* {{{ proto int mysqli_get_client_version(void)
1220   Get MySQL client info */
1221PHP_FUNCTION(mysqli_get_client_version)
1222{
1223	RETURN_LONG((long)mysql_get_client_version());
1224}
1225/* }}} */
1226
1227/* {{{ proto string mysqli_get_host_info (object link) 
1228   Get MySQL host info */
1229PHP_FUNCTION(mysqli_get_host_info)
1230{
1231	MY_MYSQL	*mysql;
1232	zval		*mysql_link = NULL;
1233
1234	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1235		return;
1236	}
1237	MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link", MYSQLI_STATUS_VALID);
1238
1239	RETURN_STRING((mysql->mysql->host_info) ? mysql->mysql->host_info : "", 1);
1240}
1241/* }}} */
1242
1243/* {{{ proto int mysqli_get_proto_info(object link)
1244   Get MySQL protocol information */
1245PHP_FUNCTION(mysqli_get_proto_info)
1246{
1247	MY_MYSQL	*mysql;
1248	zval		*mysql_link = NULL;
1249
1250	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1251		return;
1252	}
1253	MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link", MYSQLI_STATUS_VALID);
1254	RETURN_LONG(mysql_get_proto_info(mysql->mysql));
1255}
1256/* }}} */
1257
1258/* {{{ proto string mysqli_get_server_info(object link)
1259   Get MySQL server info */
1260PHP_FUNCTION(mysqli_get_server_info)
1261{
1262	MY_MYSQL	*mysql;
1263	zval		*mysql_link = NULL;
1264
1265	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1266		return;
1267	}
1268	MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link", MYSQLI_STATUS_VALID);
1269
1270	RETURN_STRING((char *)mysql_get_server_info(mysql->mysql), 1);
1271}
1272
1273/* }}} */
1274
1275/* {{{ proto int mysqli_get_server_version(object link) 
1276   Return the MySQL version for the server referenced by the given link */
1277PHP_FUNCTION(mysqli_get_server_version)
1278{
1279	MY_MYSQL	*mysql;
1280	zval		*mysql_link = NULL;
1281
1282	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1283		return;
1284	}
1285	MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link", MYSQLI_STATUS_VALID);
1286
1287	RETURN_LONG(mysql_get_server_version(mysql->mysql));
1288}
1289/* }}} */
1290
1291/* {{{ proto string mysqli_info(object link)
1292   Get information about the most recent query */
1293PHP_FUNCTION(mysqli_info)
1294{
1295	MY_MYSQL	*mysql;
1296	zval		*mysql_link = NULL;
1297	const char	*info;
1298
1299	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1300		return;
1301	}
1302	MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link", MYSQLI_STATUS_VALID);
1303
1304	info = mysql_info(mysql->mysql);
1305	RETURN_STRING((info) ? (char *)info : "", 1);
1306}
1307/* }}} */
1308
1309/* {{{ proto resource mysqli_init(void)
1310   Initialize mysqli and return a resource for use with mysql_real_connect */
1311PHP_FUNCTION(mysqli_init)
1312{
1313	MYSQLI_RESOURCE *mysqli_resource;
1314	MY_MYSQL *mysql;
1315
1316	if (getThis() && ((mysqli_object *) zend_object_store_get_object(getThis() TSRMLS_CC))->ptr) {
1317		return;
1318	}
1319
1320	mysql = (MY_MYSQL *)ecalloc(1, sizeof(MY_MYSQL));
1321
1322#if !defined(MYSQLI_USE_MYSQLND)
1323	if (!(mysql->mysql = mysql_init(NULL)))
1324#else
1325	/*
1326	  We create always persistent, as if the user want to connecto
1327	  to p:somehost, we can't convert the handle then
1328	*/
1329	if (!(mysql->mysql = mysql_init(TRUE)))
1330#endif
1331	{
1332		efree(mysql);
1333		RETURN_FALSE;
1334	}
1335
1336	mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
1337	mysqli_resource->ptr = (void *)mysql;
1338	mysqli_resource->status = MYSQLI_STATUS_INITIALIZED;
1339
1340	if (!getThis() || !instanceof_function(Z_OBJCE_P(getThis()), mysqli_link_class_entry TSRMLS_CC)) {
1341		MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_link_class_entry);	
1342	} else {
1343		((mysqli_object *) zend_object_store_get_object(getThis() TSRMLS_CC))->ptr = mysqli_resource;
1344	}
1345}
1346/* }}} */
1347
1348/* {{{ proto mixed mysqli_insert_id(object link)
1349   Get the ID generated from the previous INSERT operation */
1350PHP_FUNCTION(mysqli_insert_id)
1351{
1352	MY_MYSQL		*mysql;
1353	my_ulonglong	rc;
1354	zval			*mysql_link;
1355
1356	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1357		return;
1358	}
1359	MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link", MYSQLI_STATUS_VALID);
1360	rc = mysql_insert_id(mysql->mysql);
1361	MYSQLI_RETURN_LONG_LONG(rc)
1362}
1363/* }}} */
1364
1365/* {{{ proto bool mysqli_kill(object link, int processid)
1366   Kill a mysql process on the server */
1367PHP_FUNCTION(mysqli_kill)
1368{
1369	MY_MYSQL	*mysql;
1370	zval		*mysql_link;
1371	long		processid;
1372
1373	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol", &mysql_link, mysqli_link_class_entry, &processid) == FAILURE) {
1374		return;
1375	}
1376	MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link", MYSQLI_STATUS_VALID);
1377
1378	if (processid <= 0) {
1379		php_error_docref(NULL TSRMLS_CC, E_WARNING, "processid should have positive value");
1380		RETURN_FALSE;
1381	}
1382
1383	if (mysql_kill(mysql->mysql, processid)) {
1384		MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
1385		RETURN_FALSE;
1386	}
1387	RETURN_TRUE;
1388}
1389/* }}} */
1390
1391/* {{{ proto void mysqli_set_local_infile_default(object link)
1392   unsets user defined handler for load local infile command */
1393#if !defined(MYSQLI_USE_MYSQLND)
1394PHP_FUNCTION(mysqli_set_local_infile_default)
1395{
1396	MY_MYSQL	*mysql;
1397	zval		*mysql_link;
1398
1399	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1400		return;
1401	}
1402
1403	MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link", MYSQLI_STATUS_VALID);
1404
1405	if (mysql->li_read) {
1406		zval_ptr_dtor(&(mysql->li_read));
1407		mysql->li_read = NULL;
1408	}
1409}
1410/* }}} */
1411
1412/* {{{ proto bool mysqli_set_local_infile_handler(object link, callback read_func)
1413   Set callback functions for LOAD DATA LOCAL INFILE */
1414PHP_FUNCTION(mysqli_set_local_infile_handler)
1415{
1416	MY_MYSQL	*mysql;
1417	zval		*mysql_link;
1418	char		*callback_name;
1419	zval		*callback_func;
1420
1421	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oz", &mysql_link, mysqli_link_class_entry,
1422			&callback_func) == FAILURE) {
1423		return;
1424	}
1425
1426	MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link", MYSQLI_STATUS_VALID);
1427
1428	/* check callback function */
1429	if (!zend_is_callable(callback_func, 0, &callback_name TSRMLS_CC)) {
1430		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Not a valid callback function %s", callback_name);
1431		efree(callback_name);
1432		RETURN_FALSE;
1433	}
1434	efree(callback_name);
1435
1436	/* save callback function */
1437	if (!mysql->li_read) {
1438		MAKE_STD_ZVAL(mysql->li_read);
1439	} else {
1440		zval_dtor(mysql->li_read);
1441	}
1442	ZVAL_ZVAL(mysql->li_read, callback_func, 1, 0);
1443
1444	RETURN_TRUE;
1445}
1446#endif
1447/* }}} */
1448
1449/* {{{ proto bool mysqli_more_results(object link)
1450   check if there any more query results from a multi query */
1451PHP_FUNCTION(mysqli_more_results)
1452{
1453	MY_MYSQL	*mysql;
1454	zval		*mysql_link;
1455
1456	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1457		return;
1458	}
1459	MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link", MYSQLI_STATUS_VALID);
1460
1461	RETURN_BOOL(mysql_more_results(mysql->mysql));
1462}
1463/* }}} */
1464
1465/* {{{ proto bool mysqli_next_result(object link)
1466   read next result from multi_query */
1467PHP_FUNCTION(mysqli_next_result) {
1468	MY_MYSQL	*mysql;
1469	zval		*mysql_link;
1470
1471	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1472		return;
1473	}
1474	MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link", MYSQLI_STATUS_VALID);
1475
1476	if (!mysql_more_results(mysql->mysql)) {
1477		php_error_docref(NULL TSRMLS_CC, E_STRICT, "There is no next result set. "
1478						"Please, call mysqli_more_results()/mysqli::more_results() to check "
1479						"whether to call this function/method");
1480	}
1481
1482	RETURN_BOOL(!mysql_next_result(mysql->mysql));
1483}
1484/* }}} */
1485
1486
1487#ifdef MYSQLI_USE_MYSQLND
1488/* {{{ proto bool mysqli_stmt_next_result(object link)
1489   check if there any more query results from a multi query */
1490PHP_FUNCTION(mysqli_stmt_more_results)
1491{
1492	MY_STMT		*stmt;
1493	zval		*mysql_stmt;
1494
1495	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
1496		return;
1497	}
1498	MYSQLI_FETCH_RESOURCE(stmt, MY_STMT *, &mysql_stmt, "mysqli_stmt", MYSQLI_STATUS_VALID);
1499
1500	RETURN_BOOL(mysqlnd_stmt_more_results(stmt->stmt));
1501}
1502/* }}} */
1503
1504
1505/* {{{ proto bool mysqli_stmt_next_result(object link)
1506   read next result from multi_query */
1507PHP_FUNCTION(mysqli_stmt_next_result) {
1508	MY_STMT		*stmt;
1509	zval		*mysql_stmt;
1510
1511	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
1512		return;
1513	}
1514	MYSQLI_FETCH_RESOURCE(stmt, MY_STMT *, &mysql_stmt, "mysqli_stmt", MYSQLI_STATUS_VALID);
1515
1516	if (!mysqlnd_stmt_more_results(stmt->stmt)) {
1517		php_error_docref(NULL TSRMLS_CC, E_STRICT, "There is no next result set. "
1518						"Please, call mysqli_stmt_more_results()/mysqli_stmt::more_results() to check "
1519						"whether to call this function/method");
1520	}
1521
1522	RETURN_BOOL(!mysqlnd_stmt_next_result(stmt->stmt));
1523}
1524/* }}} */
1525#endif
1526
1527
1528/* {{{ proto int mysqli_num_fields(object result)
1529   Get number of fields in result */
1530PHP_FUNCTION(mysqli_num_fields)
1531{
1532	MYSQL_RES	*result;
1533	zval		*mysql_result;
1534
1535	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
1536		return;
1537	}
1538	MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, &mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1539
1540	RETURN_LONG(mysql_num_fields(result));
1541}
1542/* }}} */
1543
1544/* {{{ proto mixed mysqli_num_rows(object result)
1545   Get number of rows in result */
1546PHP_FUNCTION(mysqli_num_rows)
1547{
1548	MYSQL_RES	*result;
1549	zval		*mysql_result;
1550
1551	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
1552		return;
1553	}
1554	MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, &mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1555
1556	if (mysqli_result_is_unbuffered(result)) {
1557		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Function cannot be used with MYSQL_USE_RESULT");
1558		RETURN_LONG(0);
1559	}
1560
1561	MYSQLI_RETURN_LONG_LONG(mysql_num_rows(result));
1562}
1563/* }}} */
1564
1565/* {{{ proto bool mysqli_options(object link, int flags, mixed values)
1566   Set options */
1567PHP_FUNCTION(mysqli_options)
1568{
1569	MY_MYSQL		*mysql;
1570	zval			*mysql_link = NULL;
1571	zval			*mysql_value;
1572	long			mysql_option;
1573	unsigned int	l_value;
1574	long			ret;
1575
1576	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Olz", &mysql_link, mysqli_link_class_entry, &mysql_option, &mysql_value) == FAILURE) {
1577		return;
1578	}
1579	MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link", MYSQLI_STATUS_INITIALIZED);
1580
1581	if ((PG(open_basedir) && PG(open_basedir)[0] != '\0') || PG(safe_mode)) {
1582		if(mysql_option == MYSQL_OPT_LOCAL_INFILE) {
1583			RETURN_FALSE;
1584		}
1585	}
1586
1587	switch (Z_TYPE_PP(&mysql_value)) {
1588		case IS_STRING:
1589			ret = mysql_options(mysql->mysql, mysql_option, Z_STRVAL_PP(&mysql_value));
1590			break;
1591		default:
1592			convert_to_long_ex(&mysql_value);
1593			l_value = Z_LVAL_PP(&mysql_value);
1594			ret = mysql_options(mysql->mysql, mysql_option, (char *)&l_value);
1595			break;
1596	}
1597
1598	RETURN_BOOL(!ret);
1599}
1600/* }}} */
1601
1602
1603/* {{{ proto bool mysqli_ping(object link)
1604   Ping a server connection or reconnect if there is no connection */
1605PHP_FUNCTION(mysqli_ping)
1606{
1607	MY_MYSQL	*mysql;
1608	zval		*mysql_link;
1609	long		rc;
1610
1611	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1612		return;
1613	}
1614	MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link", MYSQLI_STATUS_VALID);
1615	rc = mysql_ping(mysql->mysql);
1616	MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
1617
1618	RETURN_BOOL(!rc);
1619}
1620/* }}} */
1621
1622/* {{{ proto mixed mysqli_prepare(object link, string query)
1623   Prepare a SQL statement for execution */
1624PHP_FUNCTION(mysqli_prepare)
1625{
1626	MY_MYSQL		*mysql;
1627	MY_STMT			*stmt;
1628	char			*query = NULL;
1629	unsigned int	query_len;
1630	zval			*mysql_link;
1631	MYSQLI_RESOURCE	*mysqli_resource;
1632
1633	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os",&mysql_link, mysqli_link_class_entry, &query, &query_len) == FAILURE) {
1634		return;
1635	}
1636	MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link", MYSQLI_STATUS_VALID);
1637
1638#if !defined(MYSQLI_USE_MYSQLND)
1639	if (mysql->mysql->status == MYSQL_STATUS_GET_RESULT) {
1640		php_error_docref(NULL TSRMLS_CC, E_WARNING, "All data must be fetched before a new statement prepare takes place");
1641		RETURN_FALSE;
1642	}
1643#endif
1644
1645	stmt = (MY_STMT *)ecalloc(1,sizeof(MY_STMT));
1646
1647	if ((stmt->stmt = mysql_stmt_init(mysql->mysql))) {
1648		if (mysql_stmt_prepare(stmt->stmt, query, query_len)) {
1649			/* mysql_stmt_close() clears errors, so we have to store them temporarily */
1650#if !defined(MYSQLI_USE_MYSQLND)
1651			char  last_error[MYSQL_ERRMSG_SIZE];
1652			char  sqlstate[SQLSTATE_LENGTH+1];
1653			unsigned int last_errno;
1654
1655			last_errno = stmt->stmt->last_errno;
1656			memcpy(last_error, stmt->stmt->last_error, MYSQL_ERRMSG_SIZE);
1657			memcpy(sqlstate, mysql->mysql->net.sqlstate, SQLSTATE_LENGTH+1);
1658#else
1659			mysqlnd_error_info error_info = mysql->mysql->error_info;
1660#endif
1661			mysqli_stmt_close(stmt->stmt, FALSE);
1662			stmt->stmt = NULL;
1663
1664			/* restore error messages */
1665#if !defined(MYSQLI_USE_MYSQLND)
1666			mysql->mysql->net.last_errno = last_errno;
1667			memcpy(mysql->mysql->net.last_error, last_error, MYSQL_ERRMSG_SIZE);
1668			memcpy(mysql->mysql->net.sqlstate, sqlstate, SQLSTATE_LENGTH+1);
1669#else
1670			mysql->mysql->error_info = error_info;
1671#endif
1672		}
1673	}
1674
1675	/* don't initialize stmt->query with NULL, we ecalloc()-ed the memory */
1676	/* Get performance boost if reporting is switched off */
1677	if (stmt->stmt && query_len && (MyG(report_mode) & MYSQLI_REPORT_INDEX)) {
1678		stmt->query = (char *)emalloc(query_len + 1);
1679		memcpy(stmt->query, query, query_len);
1680		stmt->query[query_len] = '\0';
1681	}
1682
1683	/* don't join to the previous if because it won't work if mysql_stmt_prepare_fails */
1684	if (!stmt->stmt) {
1685		MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
1686		efree(stmt);
1687		RETURN_FALSE;
1688	}
1689
1690	mysqli_resource = (MYSQLI_R

Large files files are truncated, but you can click here to view the full file