1 /*
2   +----------------------------------------------------------------------+
3   | PHP Version 7                                                        |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 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 
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24 
25 #include <signal.h>
26 
27 #include "php.h"
28 #include "php_ini.h"
29 #include "php_globals.h"
30 #include "ext/standard/info.h"
31 #include "zend_smart_str.h"
32 #include "php_mysqli_structs.h"
33 #include "mysqli_priv.h"
34 #if defined(MYSQLI_USE_MYSQLND)
35 #include "ext/mysqlnd/mysql_float_to_double.h"
36 #endif
37 
38 #if !defined(MYSQLI_USE_MYSQLND)
39 /* {{{ mysqli_tx_cor_options_to_string */
mysqli_tx_cor_options_to_string(const MYSQL * const conn,smart_str * str,const uint32_t mode)40 static void mysqli_tx_cor_options_to_string(const MYSQL * const conn, smart_str * str, const uint32_t mode)
41 {
42 	if (mode & TRANS_COR_AND_CHAIN && !(mode & TRANS_COR_AND_NO_CHAIN)) {
43 		if (str->s && ZSTR_LEN(str->s)) {
44 			smart_str_appendl(str, " ", sizeof(" ") - 1);
45 		}
46 		smart_str_appendl(str, "AND CHAIN", sizeof("AND CHAIN") - 1);
47 	} else if (mode & TRANS_COR_AND_NO_CHAIN && !(mode & TRANS_COR_AND_CHAIN)) {
48 		if (str->s && ZSTR_LEN(str->s)) {
49 			smart_str_appendl(str, " ", sizeof(" ") - 1);
50 		}
51 		smart_str_appendl(str, "AND NO CHAIN", sizeof("AND NO CHAIN") - 1);
52 	}
53 
54 	if (mode & TRANS_COR_RELEASE && !(mode & TRANS_COR_NO_RELEASE)) {
55 		if (str->s && ZSTR_LEN(str->s)) {
56 			smart_str_appendl(str, " ", sizeof(" ") - 1);
57 		}
58 		smart_str_appendl(str, "RELEASE", sizeof("RELEASE") - 1);
59 	} else if (mode & TRANS_COR_NO_RELEASE && !(mode & TRANS_COR_RELEASE)) {
60 		if (str->s && ZSTR_LEN(str->s)) {
61 			smart_str_appendl(str, " ", sizeof(" ") - 1);
62 		}
63 		smart_str_appendl(str, "NO RELEASE", sizeof("NO RELEASE") - 1);
64 	}
65 	smart_str_0(str);
66 }
67 /* }}} */
68 
69 /* {{{ mysqlnd_escape_string_for_tx_name_in_comment */
70 char *
mysqli_escape_string_for_tx_name_in_comment(const char * const name)71 mysqli_escape_string_for_tx_name_in_comment(const char * const name)
72 {
73 	char * ret = NULL;
74 	if (name) {
75 		zend_bool warned = FALSE;
76 		const char * p_orig = name;
77 		char * p_copy;
78 		p_copy = ret = emalloc(strlen(name) + 1 + 2 + 2 + 1); /* space, open, close, NullS */
79 		*p_copy++ = ' ';
80 		*p_copy++ = '/';
81 		*p_copy++ = '*';
82 		while (1) {
83 			register char v = *p_orig;
84 			if (v == 0) {
85 				break;
86 			}
87 			if ((v >= '0' && v <= '9') ||
88 				(v >= 'a' && v <= 'z') ||
89 				(v >= 'A' && v <= 'Z') ||
90 				v == '-' ||
91 				v == '_' ||
92 				v == ' ' ||
93 				v == '=')
94 			{
95 				*p_copy++ = v;
96 			} else if (warned == FALSE) {
97 				php_error_docref(NULL, E_WARNING, "Transaction name truncated. Must be only [0-9A-Za-z\\-_=]+");
98 				warned = TRUE;
99 			}
100 			++p_orig;
101 		}
102 		*p_copy++ = '*';
103 		*p_copy++ = '/';
104 		*p_copy++ = 0;
105 	}
106 	return ret;
107 }
108 /* }}} */
109 
110 /* {{{ mysqli_commit_or_rollback_libmysql */
mysqli_commit_or_rollback_libmysql(MYSQL * conn,zend_bool commit,const uint32_t mode,const char * const name)111 static int mysqli_commit_or_rollback_libmysql(MYSQL * conn, zend_bool commit, const uint32_t mode, const char * const name)
112 {
113 	int ret;
114 	smart_str tmp_str = {0};
115 	mysqli_tx_cor_options_to_string(conn, &tmp_str, mode);
116 	smart_str_0(&tmp_str);
117 
118 	{
119 		char *query;
120 		char *name_esc = mysqli_escape_string_for_tx_name_in_comment(name);
121 		size_t query_len;
122 
123 		query_len = spprintf(&query, 0,
124 				(commit? "COMMIT%s %s":"ROLLBACK%s %s"), name_esc? name_esc:"", tmp_str.s? ZSTR_VAL(tmp_str.s):"");
125 		smart_str_free(&tmp_str);
126 		if (name_esc) {
127 			efree(name_esc);
128 			name_esc = NULL;
129 		}
130 
131 		ret = mysql_real_query(conn, query, query_len);
132 		efree(query);
133 	}
134 	return ret;
135 }
136 /* }}} */
137 #endif
138 
139 /* {{{ proto mixed mysqli_affected_rows(object link)
140    Get number of affected rows in previous MySQL operation */
PHP_FUNCTION(mysqli_affected_rows)141 PHP_FUNCTION(mysqli_affected_rows)
142 {
143 	MY_MYSQL 		*mysql;
144 	zval  			*mysql_link;
145 	my_ulonglong	rc;
146 
147 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
148 		return;
149 	}
150 
151 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
152 
153 	rc = mysql_affected_rows(mysql->mysql);
154 	if (rc == (my_ulonglong) -1) {
155 		RETURN_LONG(-1);
156 	}
157 	MYSQLI_RETURN_LONG_INT(rc);
158 }
159 /* }}} */
160 
161 /* {{{ proto bool mysqli_autocommit(object link, bool mode)
162    Turn auto commit on or of */
PHP_FUNCTION(mysqli_autocommit)163 PHP_FUNCTION(mysqli_autocommit)
164 {
165 	MY_MYSQL	*mysql;
166 	zval		*mysql_link;
167 	zend_bool	automode;
168 
169 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ob", &mysql_link, mysqli_link_class_entry, &automode) == FAILURE) {
170 		return;
171 	}
172 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
173 
174 	if (mysql_autocommit(mysql->mysql, (my_bool)automode)) {
175 		MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
176 		RETURN_FALSE;
177 	}
178 	RETURN_TRUE;
179 }
180 /* }}} */
181 
182 /* {{{ mysqli_stmt_bind_param_do_bind */
183 #ifndef MYSQLI_USE_MYSQLND
184 static
mysqli_stmt_bind_param_do_bind(MY_STMT * stmt,unsigned int argc,unsigned int num_vars,zval * args,unsigned int start,const char * const types)185 int mysqli_stmt_bind_param_do_bind(MY_STMT *stmt, unsigned int argc, unsigned int num_vars,
186 								   zval *args, unsigned int start, const char * const types)
187 {
188 	int				i, ofs;
189 	MYSQL_BIND		*bind;
190 	unsigned long	rc;
191 
192 	/* prevent leak if variables are already bound */
193 	if (stmt->param.var_cnt) {
194 		php_free_stmt_bind_buffer(stmt->param, FETCH_SIMPLE);
195 	}
196 
197 	stmt->param.is_null = ecalloc(num_vars, sizeof(char));
198 	bind = (MYSQL_BIND *) ecalloc(num_vars, sizeof(MYSQL_BIND));
199 
200 	ofs = 0;
201 	for (i = start; i < argc; i++) {
202 		zval *param;
203 		if (Z_ISREF(args[i])) {
204 			param = Z_REFVAL(args[i]);
205 		} else {
206 			param = &args[i];
207 		}
208 		/* set specified type */
209 		switch (types[ofs]) {
210 			case 'd': /* Double */
211 				bind[ofs].buffer_type = MYSQL_TYPE_DOUBLE;
212 				bind[ofs].buffer = &Z_DVAL_P(param);
213 				bind[ofs].is_null = &stmt->param.is_null[ofs];
214 				break;
215 
216 			case 'i': /* Integer */
217 #if SIZEOF_ZEND_LONG==8
218 				bind[ofs].buffer_type = MYSQL_TYPE_LONGLONG;
219 #elif SIZEOF_ZEND_LONG==4
220 				bind[ofs].buffer_type = MYSQL_TYPE_LONG;
221 #endif
222 				bind[ofs].buffer = &Z_LVAL_P(param);
223 				bind[ofs].is_null = &stmt->param.is_null[ofs];
224 				break;
225 
226 			case 'b': /* Blob (send data) */
227 				bind[ofs].buffer_type = MYSQL_TYPE_LONG_BLOB;
228 				/* don't initialize is_null and length to 0 because we use ecalloc */
229 				break;
230 
231 			case 's': /* string */
232 				bind[ofs].buffer_type = MYSQL_TYPE_VAR_STRING;
233 				/* don't initialize buffer and buffer_length because we use ecalloc */
234 				bind[ofs].is_null = &stmt->param.is_null[ofs];
235 				break;
236 
237 			default:
238 				php_error_docref(NULL, E_WARNING, "Undefined fieldtype %c (parameter %d)", types[ofs], i+1);
239 				rc = 1;
240 				goto end_1;
241 		}
242 		ofs++;
243 	}
244 	rc = mysql_stmt_bind_param(stmt->stmt, bind);
245 
246 end_1:
247 	if (rc) {
248 		efree(stmt->param.is_null);
249 	} else {
250 		stmt->param.var_cnt = num_vars;
251 		stmt->param.vars = safe_emalloc(num_vars, sizeof(zval), 0);
252 		for (i = 0; i < num_vars; i++) {
253 			if (bind[i].buffer_type != MYSQL_TYPE_LONG_BLOB) {
254 				ZVAL_COPY(&stmt->param.vars[i], &args[i+start]);
255 			} else {
256 				ZVAL_UNDEF(&stmt->param.vars[i]);
257 			}
258 		}
259 	}
260 	efree(bind);
261 
262 	return rc;
263 }
264 #else
265 static
mysqli_stmt_bind_param_do_bind(MY_STMT * stmt,unsigned int argc,unsigned int num_vars,zval * args,unsigned int start,const char * const types)266 int mysqli_stmt_bind_param_do_bind(MY_STMT *stmt, unsigned int argc, unsigned int num_vars,
267 								   zval *args, unsigned int start, const char * const types)
268 {
269 	unsigned int i;
270 	MYSQLND_PARAM_BIND	*params;
271 	enum_func_status	ret = FAIL;
272 
273 	/* If no params -> skip binding and return directly */
274 	if (argc == start) {
275 		return PASS;
276 	}
277 	params = mysqlnd_stmt_alloc_param_bind(stmt->stmt);
278 	if (!params) {
279 		goto end;
280 	}
281 	for (i = 0; i < (argc - start); i++) {
282 		zend_uchar type;
283 		switch (types[i]) {
284 			case 'd': /* Double */
285 				type = MYSQL_TYPE_DOUBLE;
286 				break;
287 			case 'i': /* Integer */
288 #if SIZEOF_ZEND_LONG==8
289 				type = MYSQL_TYPE_LONGLONG;
290 #elif SIZEOF_ZEND_LONG==4
291 				type = MYSQL_TYPE_LONG;
292 #endif
293 				break;
294 			case 'b': /* Blob (send data) */
295 				type = MYSQL_TYPE_LONG_BLOB;
296 				break;
297 			case 's': /* string */
298 				type = MYSQL_TYPE_VAR_STRING;
299 				break;
300 			default:
301 				/* We count parameters from 1 */
302 				php_error_docref(NULL, E_WARNING, "Undefined fieldtype %c (parameter %d)", types[i], i + start + 1);
303 				ret = FAIL;
304 				mysqlnd_stmt_free_param_bind(stmt->stmt, params);
305 				goto end;
306 		}
307 		ZVAL_COPY_VALUE(&params[i].zv, &args[i + start]);
308 		params[i].type = type;
309 	}
310 	ret = mysqlnd_stmt_bind_param(stmt->stmt, params);
311 
312 end:
313 	return ret;
314 }
315 #endif
316 /* }}} */
317 
318 /* {{{ proto bool mysqli_stmt_bind_param(object stmt, string types, mixed variable [,mixed ...])
319    Bind variables to a prepared statement as parameters */
PHP_FUNCTION(mysqli_stmt_bind_param)320 PHP_FUNCTION(mysqli_stmt_bind_param)
321 {
322 	zval			*args;
323 	int				argc = ZEND_NUM_ARGS();
324 	int				num_vars;
325 	int				start = 2;
326 	MY_STMT			*stmt;
327 	zval			*mysql_stmt;
328 	char			*types;
329 	size_t			types_len;
330 	zend_ulong	rc;
331 
332 	/* calculate and check number of parameters */
333 	if (argc < 2) {
334 		/* there has to be at least one pair */
335 		WRONG_PARAM_COUNT;
336 	}
337 
338 	if (zend_parse_method_parameters((getThis()) ? 1:2, getThis(), "Os", &mysql_stmt, mysqli_stmt_class_entry,
339 									&types, &types_len) == FAILURE) {
340 		return;
341 	}
342 
343 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
344 
345 	num_vars = argc - 1;
346 	if (getThis()) {
347 		start = 1;
348 	} else {
349 		/* ignore handle parameter in procedural interface*/
350 		--num_vars;
351 	}
352 	if (!types_len) {
353 		php_error_docref(NULL, E_WARNING, "Invalid type or no types specified");
354 		RETURN_FALSE;
355 	}
356 
357 	if (types_len != (size_t)(argc - start)) {
358 		/* number of bind variables doesn't match number of elements in type definition string */
359 		php_error_docref(NULL, E_WARNING, "Number of elements in type definition string doesn't match number of bind variables");
360 		RETURN_FALSE;
361 	}
362 
363 	if (types_len != mysql_stmt_param_count(stmt->stmt)) {
364 		php_error_docref(NULL, E_WARNING, "Number of variables doesn't match number of parameters in prepared statement");
365 		RETURN_FALSE;
366 	}
367 
368 	args = safe_emalloc(argc, sizeof(zval), 0);
369 
370 	if (zend_get_parameters_array_ex(argc, args) == FAILURE) {
371 		zend_wrong_param_count();
372 		rc = 1;
373 	} else {
374 		rc = mysqli_stmt_bind_param_do_bind(stmt, argc, num_vars, args, start, types);
375 		MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
376 	}
377 
378 	efree(args);
379 
380 	RETURN_BOOL(!rc);
381 }
382 /* }}} */
383 
384 /* {{{ mysqli_stmt_bind_result_do_bind */
385 #ifndef MYSQLI_USE_MYSQLND
386 /* TODO:
387    do_alloca, free_alloca
388 */
389 static int
mysqli_stmt_bind_result_do_bind(MY_STMT * stmt,zval * args,unsigned int argc)390 mysqli_stmt_bind_result_do_bind(MY_STMT *stmt, zval *args, unsigned int argc)
391 {
392 	MYSQL_BIND	*bind;
393 	int			i, ofs;
394 	int			var_cnt = argc;
395 	zend_long		col_type;
396 	zend_ulong		rc;
397 
398 	/* prevent leak if variables are already bound */
399 	if (stmt->result.var_cnt) {
400 		php_free_stmt_bind_buffer(stmt->result, FETCH_RESULT);
401 	}
402 
403 	bind = (MYSQL_BIND *)ecalloc(var_cnt, sizeof(MYSQL_BIND));
404 	{
405 		int size;
406 		char *p = emalloc(size= var_cnt * (sizeof(char) + sizeof(VAR_BUFFER)));
407 		stmt->result.buf = (VAR_BUFFER *) p;
408 		stmt->result.is_null = p + var_cnt * sizeof(VAR_BUFFER);
409 		memset(p, 0, size);
410 	}
411 
412 	for (i = 0; i < var_cnt; i++) {
413 		ofs = i;
414 		col_type = (stmt->stmt->fields) ? stmt->stmt->fields[ofs].type : MYSQL_TYPE_STRING;
415 
416 		switch (col_type) {
417 			case MYSQL_TYPE_FLOAT:
418 				stmt->result.buf[ofs].type = IS_DOUBLE;
419 				stmt->result.buf[ofs].buflen = sizeof(float);
420 
421 				stmt->result.buf[ofs].val = (char *)emalloc(sizeof(float));
422 				bind[ofs].buffer_type = MYSQL_TYPE_FLOAT;
423 				bind[ofs].buffer = stmt->result.buf[ofs].val;
424 				bind[ofs].is_null = &stmt->result.is_null[ofs];
425 				break;
426 
427 			case MYSQL_TYPE_DOUBLE:
428 				stmt->result.buf[ofs].type = IS_DOUBLE;
429 				stmt->result.buf[ofs].buflen = sizeof(double);
430 
431 				/* allocate buffer for double */
432 				stmt->result.buf[ofs].val = (char *)emalloc(sizeof(double));
433 				bind[ofs].buffer_type = MYSQL_TYPE_DOUBLE;
434 				bind[ofs].buffer = stmt->result.buf[ofs].val;
435 				bind[ofs].is_null = &stmt->result.is_null[ofs];
436 				break;
437 
438 			case MYSQL_TYPE_NULL:
439 				stmt->result.buf[ofs].type = IS_NULL;
440 				/*
441 				  don't initialize to 0 :
442 				  1. stmt->result.buf[ofs].buflen
443 				  2. bind[ofs].buffer
444 				  3. bind[ofs].buffer_length
445 				  because memory was allocated with ecalloc
446 				*/
447 				bind[ofs].buffer_type = MYSQL_TYPE_NULL;
448 				bind[ofs].is_null = &stmt->result.is_null[ofs];
449 				break;
450 
451 			case MYSQL_TYPE_SHORT:
452 			case MYSQL_TYPE_TINY:
453 			case MYSQL_TYPE_LONG:
454 			case MYSQL_TYPE_INT24:
455 			case MYSQL_TYPE_YEAR:
456 				stmt->result.buf[ofs].type = IS_LONG;
457 				/* don't set stmt->result.buf[ofs].buflen to 0, we used ecalloc */
458 				stmt->result.buf[ofs].val = (char *)emalloc(sizeof(int));
459 				bind[ofs].buffer_type = MYSQL_TYPE_LONG;
460 				bind[ofs].buffer = stmt->result.buf[ofs].val;
461 				bind[ofs].is_null = &stmt->result.is_null[ofs];
462 				bind[ofs].is_unsigned = (stmt->stmt->fields[ofs].flags & UNSIGNED_FLAG) ? 1 : 0;
463 				break;
464 
465 			case MYSQL_TYPE_LONGLONG:
466 #if MYSQL_VERSION_ID > 50002 || defined(MYSQLI_USE_MYSQLND)
467 			case MYSQL_TYPE_BIT:
468 #endif
469 				stmt->result.buf[ofs].type = IS_STRING;
470 				stmt->result.buf[ofs].buflen = sizeof(my_ulonglong);
471 				stmt->result.buf[ofs].val = (char *)emalloc(stmt->result.buf[ofs].buflen);
472 				bind[ofs].buffer_type = col_type;
473 				bind[ofs].buffer = stmt->result.buf[ofs].val;
474 				bind[ofs].is_null = &stmt->result.is_null[ofs];
475 				bind[ofs].buffer_length = stmt->result.buf[ofs].buflen;
476 				bind[ofs].is_unsigned = (stmt->stmt->fields[ofs].flags & UNSIGNED_FLAG) ? 1 : 0;
477 				bind[ofs].length = &stmt->result.buf[ofs].output_len;
478 				break;
479 
480 			case MYSQL_TYPE_DATE:
481 			case MYSQL_TYPE_TIME:
482 			case MYSQL_TYPE_DATETIME:
483 			case MYSQL_TYPE_NEWDATE:
484 			case MYSQL_TYPE_VAR_STRING:
485 			case MYSQL_TYPE_STRING:
486 			case MYSQL_TYPE_TINY_BLOB:
487 			case MYSQL_TYPE_BLOB:
488 			case MYSQL_TYPE_MEDIUM_BLOB:
489 			case MYSQL_TYPE_LONG_BLOB:
490 			case MYSQL_TYPE_TIMESTAMP:
491 			case MYSQL_TYPE_DECIMAL:
492 			case MYSQL_TYPE_GEOMETRY:
493 #ifdef FIELD_TYPE_NEWDECIMAL
494 			case MYSQL_TYPE_NEWDECIMAL:
495 #endif
496 			{
497 #if MYSQL_VERSION_ID >= 50107
498 				/* Changed to my_bool in MySQL 5.1. See MySQL Bug #16144 */
499 				my_bool tmp;
500 #else
501 				zend_ulong tmp = 0;
502 #endif
503 				stmt->result.buf[ofs].type = IS_STRING;
504 				/*
505 					If the user has called $stmt->store_result() then we have asked
506 					max_length to be updated. this is done only for BLOBS because we don't want to allocate
507 					big chunkgs of memory 2^16 or 2^24
508 				*/
509 				if (stmt->stmt->fields[ofs].max_length == 0 &&
510 					!mysql_stmt_attr_get(stmt->stmt, STMT_ATTR_UPDATE_MAX_LENGTH, &tmp) && !tmp)
511 				{
512 					/*
513 					  Allocate directly 256 because it's easier to allocate a bit more
514 					  than update max length even for text columns. Try SELECT UNION SELECT UNION with
515 					  different lengths and you will see that we get different lengths in stmt->stmt->fields[ofs].length
516 					  The just take 256 and saves us from realloc-ing.
517 					*/
518 					stmt->result.buf[ofs].buflen =
519 						(stmt->stmt->fields) ? (stmt->stmt->fields[ofs].length) ? stmt->stmt->fields[ofs].length + 1: 256: 256;
520 
521 				} else {
522 					/*
523 						the user has called store_result(). if he does not there is no way to determine the
524 						libmysql does not allow us to allocate 0 bytes for a buffer so we try 1
525 					*/
526 					if (!(stmt->result.buf[ofs].buflen = stmt->stmt->fields[ofs].max_length))
527 						++stmt->result.buf[ofs].buflen;
528 				}
529 				stmt->result.buf[ofs].val = (char *)emalloc(stmt->result.buf[ofs].buflen);
530 				bind[ofs].buffer_type = MYSQL_TYPE_STRING;
531 				bind[ofs].buffer = stmt->result.buf[ofs].val;
532 				bind[ofs].is_null = &stmt->result.is_null[ofs];
533 				bind[ofs].buffer_length = stmt->result.buf[ofs].buflen;
534 				bind[ofs].length = &stmt->result.buf[ofs].output_len;
535 				break;
536 			}
537 			default:
538 				php_error_docref(NULL, E_WARNING, "Server returned unknown type %ld. Probably your client library is incompatible with the server version you use!", col_type);
539 				break;
540 		}
541 	}
542 
543 	rc = mysql_stmt_bind_result(stmt->stmt, bind);
544 	MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
545 
546 	if (rc) {
547 		/* don't close the statement or subsequent usage (for example ->execute()) will lead to crash */
548 		for (i=0; i < var_cnt ; i++) {
549 			if (stmt->result.buf[i].val) {
550 				efree(stmt->result.buf[i].val);
551 			}
552 		}
553 		/* Don't free stmt->result.is_null because is_null & buf are one block of memory  */
554 		efree(stmt->result.buf);
555 	} else {
556 		stmt->result.var_cnt = var_cnt;
557 		stmt->result.vars = safe_emalloc((var_cnt), sizeof(zval), 0);
558 		for (i = 0; i < var_cnt; i++) {
559 			ZVAL_COPY(&stmt->result.vars[i], &args[i]);
560 		}
561 	}
562 	efree(bind);
563 
564 	return rc;
565 }
566 #else
567 static int
mysqli_stmt_bind_result_do_bind(MY_STMT * stmt,zval * args,unsigned int argc)568 mysqli_stmt_bind_result_do_bind(MY_STMT *stmt, zval *args, unsigned int argc)
569 {
570 	unsigned int i;
571 	MYSQLND_RESULT_BIND *params = mysqlnd_stmt_alloc_result_bind(stmt->stmt);
572 	if (params) {
573 		for (i = 0; i < argc; i++) {
574 			ZVAL_COPY_VALUE(&params[i].zv, &args[i]);
575 		}
576 		return mysqlnd_stmt_bind_result(stmt->stmt, params);
577 	}
578 	return FAIL;
579 }
580 #endif
581 /* }}} */
582 
583 /* {{{ proto bool mysqli_stmt_bind_result(object stmt, mixed var [,mixed ...])
584    Bind variables to a prepared statement for result storage */
PHP_FUNCTION(mysqli_stmt_bind_result)585 PHP_FUNCTION(mysqli_stmt_bind_result)
586 {
587 	zval		*args;
588 	int			argc;
589 	zend_ulong		rc;
590 	MY_STMT		*stmt;
591 	zval		*mysql_stmt;
592 
593 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O+", &mysql_stmt, mysqli_stmt_class_entry, &args, &argc) == FAILURE) {
594 		return;
595 	}
596 
597 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
598 
599 	if ((uint32_t)argc != mysql_stmt_field_count(stmt->stmt)) {
600 		php_error_docref(NULL, E_WARNING, "Number of bind variables doesn't match number of fields in prepared statement");
601 		RETURN_FALSE;
602 	}
603 
604 	rc = mysqli_stmt_bind_result_do_bind(stmt, args, argc);
605 	RETURN_BOOL(!rc);
606 }
607 /* }}} */
608 
609 /* {{{ proto bool mysqli_change_user(object link, string user, string password, string database)
610    Change logged-in user of the active connection */
PHP_FUNCTION(mysqli_change_user)611 PHP_FUNCTION(mysqli_change_user)
612 {
613 	MY_MYSQL	*mysql;
614 	zval		*mysql_link = NULL;
615 	char		*user, *password, *dbname;
616 	size_t			user_len, password_len, dbname_len;
617 	zend_ulong		rc;
618 #if !defined(MYSQLI_USE_MYSQLND) && defined(HAVE_MYSQLI_SET_CHARSET)
619 	MY_CHARSET_INFO old_charset;
620 #endif
621 
622 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Osss!", &mysql_link, mysqli_link_class_entry, &user, &user_len, &password, &password_len, &dbname, &dbname_len) == FAILURE) {
623 		return;
624 	}
625 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
626 
627 #if !defined(MYSQLI_USE_MYSQLND) && defined(HAVE_MYSQLI_SET_CHARSET)
628 	mysql_get_character_set_info(mysql->mysql, &old_charset);
629 #endif
630 
631 #if defined(MYSQLI_USE_MYSQLND)
632 	rc = mysqlnd_change_user_ex(mysql->mysql, user, password, dbname, FALSE, (size_t) password_len);
633 #else
634 	rc = mysql_change_user(mysql->mysql, user, password, dbname);
635 #endif
636 	MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
637 
638 	if (rc) {
639 		RETURN_FALSE;
640 	}
641 #if !defined(MYSQLI_USE_MYSQLND) && defined(HAVE_MYSQLI_SET_CHARSET)
642 	if (mysql_get_server_version(mysql->mysql) < 50123L) {
643 		/*
644 		  Request the current charset, or it will be reset to the system one.
645 		  5.0 doesn't support it. Support added in 5.1.23 by fixing the following bug :
646 		  Bug #30472 libmysql doesn't reset charset, insert_id after succ. mysql_change_user() call
647 		*/
648 		rc = mysql_set_character_set(mysql->mysql, old_charset.csname);
649 	}
650 #endif
651 
652 	RETURN_TRUE;
653 }
654 /* }}} */
655 
656 /* {{{ proto string mysqli_character_set_name(object link)
657    Returns the name of the character set used for this connection */
PHP_FUNCTION(mysqli_character_set_name)658 PHP_FUNCTION(mysqli_character_set_name)
659 {
660 	MY_MYSQL	*mysql;
661 	zval		*mysql_link;
662 	const char	*cs_name;
663 
664 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
665 		return;
666 	}
667 
668 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
669 	cs_name = mysql_character_set_name(mysql->mysql);
670 	if (cs_name) {
671 		RETURN_STRING(cs_name);
672 	}
673 }
674 /* }}} */
675 
676 /* {{{ php_mysqli_close */
php_mysqli_close(MY_MYSQL * mysql,int close_type,int resource_status)677 void php_mysqli_close(MY_MYSQL * mysql, int close_type, int resource_status)
678 {
679 	if (resource_status > MYSQLI_STATUS_INITIALIZED) {
680 		MyG(num_links)--;
681 	}
682 
683 	if (!mysql->persistent) {
684 		mysqli_close(mysql->mysql, close_type);
685 	} else {
686 		zend_resource *le;
687 		if ((le = zend_hash_find_ptr(&EG(persistent_list), mysql->hash_key)) != NULL) {
688 			if (le->type == php_le_pmysqli()) {
689 				mysqli_plist_entry *plist = (mysqli_plist_entry *) le->ptr;
690 #if defined(MYSQLI_USE_MYSQLND)
691 				mysqlnd_end_psession(mysql->mysql);
692 #endif
693 
694 				if (MyG(rollback_on_cached_plink) &&
695 #if !defined(MYSQLI_USE_MYSQLND)
696 					mysqli_commit_or_rollback_libmysql(mysql->mysql, FALSE, TRANS_COR_NO_OPT, NULL))
697 #else
698 					FAIL == mysqlnd_rollback(mysql->mysql, TRANS_COR_NO_OPT, NULL))
699 #endif
700 				{
701 					mysqli_close(mysql->mysql, close_type);
702 				} else {
703 					zend_ptr_stack_push(&plist->free_links, mysql->mysql);
704 					MyG(num_inactive_persistent)++;
705 				}
706 				MyG(num_active_persistent)--;
707 			}
708 		}
709 		mysql->persistent = FALSE;
710 	}
711 	mysql->mysql = NULL;
712 
713 	php_clear_mysql(mysql);
714 }
715 /* }}} */
716 
717 /* {{{ proto bool mysqli_close(object link)
718    Close connection */
PHP_FUNCTION(mysqli_close)719 PHP_FUNCTION(mysqli_close)
720 {
721 	zval		*mysql_link;
722 	MY_MYSQL	*mysql;
723 
724 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
725 		return;
726 	}
727 
728 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_INITIALIZED);
729 
730 	php_mysqli_close(mysql, MYSQLI_CLOSE_EXPLICIT, ((MYSQLI_RESOURCE *)(Z_MYSQLI_P(mysql_link))->ptr)->status);
731 	((MYSQLI_RESOURCE *)(Z_MYSQLI_P(mysql_link))->ptr)->status = MYSQLI_STATUS_UNKNOWN;
732 
733 	MYSQLI_CLEAR_RESOURCE(mysql_link);
734 	efree(mysql);
735 	RETURN_TRUE;
736 }
737 /* }}} */
738 
739 /* {{{ proto bool mysqli_commit(object link[, int flags [, string name ]])
740    Commit outstanding actions and close transaction */
PHP_FUNCTION(mysqli_commit)741 PHP_FUNCTION(mysqli_commit)
742 {
743 	MY_MYSQL	*mysql;
744 	zval		*mysql_link;
745 	zend_long		flags = TRANS_COR_NO_OPT;
746 	char *		name = NULL;
747 	size_t			name_len = 0;
748 
749 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|ls", &mysql_link, mysqli_link_class_entry, &flags, &name, &name_len) == FAILURE) {
750 		return;
751 	}
752 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
753 
754 #if !defined(MYSQLI_USE_MYSQLND)
755 	if (mysqli_commit_or_rollback_libmysql(mysql->mysql, TRUE, flags, name)) {
756 #else
757 	if (FAIL == mysqlnd_commit(mysql->mysql, flags, name)) {
758 #endif
759 		MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
760 		RETURN_FALSE;
761 	}
762 	RETURN_TRUE;
763 }
764 /* }}} */
765 
766 /* {{{ proto bool mysqli_data_seek(object result, int offset)
767    Move internal result pointer */
768 PHP_FUNCTION(mysqli_data_seek)
769 {
770 	MYSQL_RES	*result;
771 	zval		*mysql_result;
772 	zend_long		offset;
773 
774 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &mysql_result, mysqli_result_class_entry, &offset) == FAILURE) {
775 		return;
776 	}
777 
778 	MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
779 
780 	if (mysqli_result_is_unbuffered(result)) {
781 		php_error_docref(NULL, E_WARNING, "Function cannot be used with MYSQL_USE_RESULT");
782 		RETURN_FALSE;
783 	}
784 
785 	if (offset < 0 || (uint64_t)offset >= mysql_num_rows(result)) {
786 		RETURN_FALSE;
787 	}
788 
789 	mysql_data_seek(result, offset);
790 	RETURN_TRUE;
791 }
792 /* }}} */
793 
794 /* {{{ proto void mysqli_debug(string debug)
795 */
796 PHP_FUNCTION(mysqli_debug)
797 {
798 	char	*debug;
799 	size_t		debug_len;
800 
801 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &debug, &debug_len) == FAILURE) {
802 		return;
803 	}
804 
805 	mysql_debug(debug);
806 	RETURN_TRUE;
807 }
808 /* }}} */
809 
810 /* {{{ proto bool mysqli_dump_debug_info(object link)
811 */
812 PHP_FUNCTION(mysqli_dump_debug_info)
813 {
814 	MY_MYSQL	*mysql;
815 	zval		*mysql_link;
816 
817 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
818 		return;
819 	}
820 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
821 
822 	RETURN_BOOL(!mysql_dump_debug_info(mysql->mysql))
823 }
824 /* }}} */
825 
826 /* {{{ proto int mysqli_errno(object link)
827    Returns the numerical value of the error message from previous MySQL operation */
828 PHP_FUNCTION(mysqli_errno)
829 {
830 	MY_MYSQL	*mysql;
831 	zval		*mysql_link;
832 
833 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
834 		return;
835 	}
836 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
837 	RETURN_LONG(mysql_errno(mysql->mysql));
838 }
839 /* }}} */
840 
841 /* {{{ proto string mysqli_error(object link)
842    Returns the text of the error message from previous MySQL operation */
843 PHP_FUNCTION(mysqli_error)
844 {
845 	MY_MYSQL	*mysql;
846 	zval		*mysql_link;
847 	const char	*err;
848 
849 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
850 		return;
851 	}
852 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
853 	err = mysql_error(mysql->mysql);
854 	if (err) {
855 		RETURN_STRING(err);
856 	}
857 }
858 /* }}} */
859 
860 /* {{{ proto bool mysqli_stmt_execute(object stmt)
861    Execute a prepared statement */
862 PHP_FUNCTION(mysqli_stmt_execute)
863 {
864 	MY_STMT		*stmt;
865 	zval		*mysql_stmt;
866 #ifndef MYSQLI_USE_MYSQLND
867 	unsigned int	i;
868 #endif
869 
870 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
871 		return;
872 	}
873 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
874 
875 #ifndef MYSQLI_USE_MYSQLND
876 	if (stmt->param.var_cnt) {
877 		int j;
878 		for (i = 0; i < stmt->param.var_cnt; i++) {
879 			if (!Z_ISREF(stmt->param.vars[i])) {
880 				continue;
881 			}
882 			for (j = i + 1; j < stmt->param.var_cnt; j++) {
883 				/* Oops, someone binding the same variable - clone */
884 				if (Z_ISREF(stmt->param.vars[j]) &&
885 					   	Z_REFVAL(stmt->param.vars[j]) == Z_REFVAL(stmt->param.vars[i])) {
886 					/*SEPARATE_ZVAL(&stmt->param.vars[j]);*/
887 					Z_DELREF_P(&stmt->param.vars[j]);
888 					ZVAL_COPY(&stmt->param.vars[j], Z_REFVAL(stmt->param.vars[j]));
889 					break;
890 				}
891 			}
892 		}
893 	}
894 	for (i = 0; i < stmt->param.var_cnt; i++) {
895 		if (!Z_ISUNDEF(stmt->param.vars[i])) {
896 			zval *param;
897 			if (Z_ISREF(stmt->param.vars[i])) {
898 				param = Z_REFVAL(stmt->param.vars[i]);
899 			} else {
900 				param = &stmt->param.vars[i];
901 			}
902 			if (!(stmt->param.is_null[i] = (Z_ISNULL_P(param)))) {
903 				switch (stmt->stmt->params[i].buffer_type) {
904 					case MYSQL_TYPE_VAR_STRING:
905 						if (!try_convert_to_string(param)) {
906 							return;
907 						}
908 
909 						stmt->stmt->params[i].buffer = Z_STRVAL_P(param);
910 						stmt->stmt->params[i].buffer_length = Z_STRLEN_P(param);
911 						break;
912 					case MYSQL_TYPE_DOUBLE:
913 						convert_to_double_ex(param);
914 						stmt->stmt->params[i].buffer = &Z_DVAL_P(param);
915 						break;
916 					case MYSQL_TYPE_LONGLONG:
917 					case MYSQL_TYPE_LONG:
918 						convert_to_long_ex(param);
919 						stmt->stmt->params[i].buffer = &Z_LVAL_P(param);
920 						break;
921 					default:
922 						break;
923 				}
924 			}
925 		}
926 	}
927 #endif
928 
929 	if (mysql_stmt_execute(stmt->stmt)) {
930 		MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
931 		RETVAL_FALSE;
932 	} else {
933 		RETVAL_TRUE;
934 	}
935 
936 	if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
937 		php_mysqli_report_index(stmt->query, mysqli_stmt_server_status(stmt->stmt));
938 	}
939 }
940 /* }}} */
941 
942 #ifndef MYSQLI_USE_MYSQLND
943 /* {{{ void mysqli_stmt_fetch_libmysql
944    Fetch results from a prepared statement into the bound variables */
945 void mysqli_stmt_fetch_libmysql(INTERNAL_FUNCTION_PARAMETERS)
946 {
947 	MY_STMT		*stmt;
948 	zval			*mysql_stmt;
949 	unsigned int	i;
950 	zend_ulong			ret;
951 	unsigned int	uval;
952 	my_ulonglong	llval;
953 
954 
955 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
956 		return;
957 	}
958 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
959 
960 	/* reset buffers */
961 	for (i = 0; i < stmt->result.var_cnt; i++) {
962 		if (stmt->result.buf[i].type == IS_STRING) {
963 			memset(stmt->result.buf[i].val, 0, stmt->result.buf[i].buflen);
964 		}
965 	}
966 	ret = mysql_stmt_fetch(stmt->stmt);
967 #ifdef MYSQL_DATA_TRUNCATED
968 	if (!ret || ret == MYSQL_DATA_TRUNCATED) {
969 #else
970 	if (!ret) {
971 #endif
972 		for (i = 0; i < stmt->result.var_cnt; i++) {
973 			zval *result;
974 			/* it must be a reference, isn't it? */
975 			if (Z_ISREF(stmt->result.vars[i])) {
976 				result = &stmt->result.vars[i];
977 			} else {
978 				continue; // but be safe ...
979 			}
980 			/* Even if the string is of length zero there is one byte alloced so efree() in all cases */
981 			if (!stmt->result.is_null[i]) {
982 				switch (stmt->result.buf[i].type) {
983 					case IS_LONG:
984 						if ((stmt->stmt->fields[i].type == MYSQL_TYPE_LONG)
985 						    && (stmt->stmt->fields[i].flags & UNSIGNED_FLAG))
986 						{
987 							/* unsigned int (11) */
988 							uval= *(unsigned int *) stmt->result.buf[i].val;
989 #if SIZEOF_ZEND_LONG==4
990 							if (uval > INT_MAX) {
991 								char *tmp, *p;
992 								int j = 10;
993 								tmp = emalloc(11);
994 								p= &tmp[9];
995 								do {
996 									*p-- = (uval % 10) + 48;
997 									uval = uval / 10;
998 								} while (--j > 0);
999 								tmp[10]= '\0';
1000 								/* unsigned int > INT_MAX is 10 digits - ALWAYS */
1001 								ZEND_TRY_ASSIGN_REF_STRINGL(result, tmp, 10);
1002 								efree(tmp);
1003 								break;
1004 							}
1005 #endif
1006 						}
1007 						if (stmt->stmt->fields[i].flags & UNSIGNED_FLAG) {
1008 							ZEND_TRY_ASSIGN_REF_LONG(result, *(unsigned int *)stmt->result.buf[i].val);
1009 						} else {
1010 							ZEND_TRY_ASSIGN_REF_LONG(result, *(int *)stmt->result.buf[i].val);
1011 						}
1012 						break;
1013 					case IS_DOUBLE:
1014 					{
1015 						double dval;
1016 						if (stmt->stmt->bind[i].buffer_type == MYSQL_TYPE_FLOAT) {
1017 #ifndef NOT_FIXED_DEC
1018 # define NOT_FIXED_DEC 31
1019 #endif
1020 							dval = mysql_float_to_double(*(float *)stmt->result.buf[i].val,
1021 										(stmt->stmt->fields[i].decimals >= NOT_FIXED_DEC) ? -1 :
1022 										stmt->stmt->fields[i].decimals);
1023 						} else {
1024 							dval = *((double *)stmt->result.buf[i].val);
1025 						}
1026 
1027 						ZEND_TRY_ASSIGN_REF_DOUBLE(result, dval);
1028 						break;
1029 					}
1030 					case IS_STRING:
1031 						if (stmt->stmt->bind[i].buffer_type == MYSQL_TYPE_LONGLONG
1032 #if MYSQL_VERSION_ID > 50002
1033 						 || stmt->stmt->bind[i].buffer_type == MYSQL_TYPE_BIT
1034 #endif
1035 						 ) {
1036 							my_bool uns = (stmt->stmt->fields[i].flags & UNSIGNED_FLAG)? 1:0;
1037 #if MYSQL_VERSION_ID > 50002
1038 							if (stmt->stmt->bind[i].buffer_type == MYSQL_TYPE_BIT) {
1039 								switch (stmt->result.buf[i].output_len) {
1040 									case 8:llval = (my_ulonglong)  bit_uint8korr(stmt->result.buf[i].val);break;
1041 									case 7:llval = (my_ulonglong)  bit_uint7korr(stmt->result.buf[i].val);break;
1042 									case 6:llval = (my_ulonglong)  bit_uint6korr(stmt->result.buf[i].val);break;
1043 									case 5:llval = (my_ulonglong)  bit_uint5korr(stmt->result.buf[i].val);break;
1044 									case 4:llval = (my_ulonglong)  bit_uint4korr(stmt->result.buf[i].val);break;
1045 									case 3:llval = (my_ulonglong)  bit_uint3korr(stmt->result.buf[i].val);break;
1046 									case 2:llval = (my_ulonglong)  bit_uint2korr(stmt->result.buf[i].val);break;
1047 									case 1:llval = (my_ulonglong)  uint1korr(stmt->result.buf[i].val);break;
1048 								}
1049 							} else
1050 #endif
1051 							{
1052 								llval= *(my_ulonglong *) stmt->result.buf[i].val;
1053 							}
1054 #if SIZEOF_ZEND_LONG==8
1055 							if (uns && llval > 9223372036854775807L) {
1056 #elif SIZEOF_ZEND_LONG==4
1057 							if ((uns && llval > L64(2147483647)) ||
1058 								(!uns && (( L64(2147483647) < (my_longlong) llval) ||
1059 								(L64(-2147483648) > (my_longlong) llval))))
1060 							{
1061 #endif
1062 								char tmp[22];
1063 								/* even though lval is declared as unsigned, the value
1064 								 * may be negative. Therefor we cannot use MYSQLI_LLU_SPEC and must
1065 								 * use MYSQLI_LL_SPEC.
1066 								 */
1067 								snprintf(tmp, sizeof(tmp), (stmt->stmt->fields[i].flags & UNSIGNED_FLAG)? MYSQLI_LLU_SPEC : MYSQLI_LL_SPEC, llval);
1068 								ZEND_TRY_ASSIGN_REF_STRING(result, tmp);
1069 							} else {
1070 								ZEND_TRY_ASSIGN_REF_LONG(result, llval);
1071 							}
1072 						} else {
1073 #if defined(MYSQL_DATA_TRUNCATED) && MYSQL_VERSION_ID > 50002
1074 							if (ret == MYSQL_DATA_TRUNCATED && *(stmt->stmt->bind[i].error) != 0) {
1075 								/* result was truncated */
1076 								ZEND_TRY_ASSIGN_REF_STRINGL(result, stmt->result.buf[i].val, stmt->stmt->bind[i].buffer_length);
1077 							} else {
1078 #else
1079 							{
1080 #endif
1081 								ZEND_TRY_ASSIGN_REF_STRINGL(result, stmt->result.buf[i].val, stmt->result.buf[i].output_len);
1082 							}
1083 						}
1084 						break;
1085 					default:
1086 						break;
1087 				}
1088 			} else {
1089 				ZEND_TRY_ASSIGN_REF_NULL(result);
1090 			}
1091 		}
1092 	} else {
1093 		MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
1094 	}
1095 
1096 	switch (ret) {
1097 		case 0:
1098 #ifdef MYSQL_DATA_TRUNCATED
1099 		/* according to SQL standard truncation (e.g. loss of precision is
1100 		   not an error) - for detecting possible truncation you have to
1101 		   check mysqli_stmt_warning
1102 		*/
1103 		case MYSQL_DATA_TRUNCATED:
1104 #endif
1105 			RETURN_TRUE;
1106 		break;
1107 		case 1:
1108 			RETURN_FALSE;
1109 		break;
1110 		default:
1111 			RETURN_NULL();
1112 		break;
1113 	}
1114 }
1115 /* }}} */
1116 #else
1117 /* {{{ mixed mysqli_stmt_fetch_mysqlnd */
1118 void mysqli_stmt_fetch_mysqlnd(INTERNAL_FUNCTION_PARAMETERS)
1119 {
1120 	MY_STMT		*stmt;
1121 	zval		*mysql_stmt;
1122 	zend_bool	fetched_anything;
1123 
1124 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
1125 		return;
1126 	}
1127 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
1128 
1129 	if (FAIL == mysqlnd_stmt_fetch(stmt->stmt, &fetched_anything)) {
1130 		MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
1131 		RETURN_BOOL(FALSE);
1132 	} else if (fetched_anything == TRUE) {
1133 		RETURN_BOOL(TRUE);
1134 	} else {
1135 		RETURN_NULL();
1136 	}
1137 }
1138 #endif
1139 /* }}} */
1140 
1141 /* {{{ proto mixed mysqli_stmt_fetch(object stmt)
1142    Fetch results from a prepared statement into the bound variables */
1143 PHP_FUNCTION(mysqli_stmt_fetch)
1144 {
1145 #if !defined(MYSQLI_USE_MYSQLND)
1146 	mysqli_stmt_fetch_libmysql(INTERNAL_FUNCTION_PARAM_PASSTHRU);
1147 #else
1148 	mysqli_stmt_fetch_mysqlnd(INTERNAL_FUNCTION_PARAM_PASSTHRU);
1149 #endif
1150 }
1151 /* }}} */
1152 
1153 /* {{{  php_add_field_properties */
1154 static void php_add_field_properties(zval *value, const MYSQL_FIELD *field)
1155 {
1156 #ifdef MYSQLI_USE_MYSQLND
1157 	add_property_str(value, "name", zend_string_copy(field->sname));
1158 #else
1159 	add_property_stringl(value, "name",(field->name ? field->name : ""), field->name_length);
1160 #endif
1161 
1162 	add_property_stringl(value, "orgname", (field->org_name ? field->org_name : ""), field->org_name_length);
1163 	add_property_stringl(value, "table", (field->table ? field->table : ""), field->table_length);
1164 	add_property_stringl(value, "orgtable", (field->org_table ? field->org_table : ""), field->org_table_length);
1165 	add_property_stringl(value, "def", (field->def ? field->def : ""), field->def_length);
1166 	add_property_stringl(value, "db", (field->db ? field->db : ""), field->db_length);
1167 
1168 	/* FIXME: manually set the catalog to "def" due to bug in
1169 	 * libmysqlclient which does not initialize field->catalog
1170 	 * and in addition, the catalog is always be "def"
1171 	 */
1172 	add_property_string(value, "catalog", "def");
1173 
1174 	add_property_long(value, "max_length", field->max_length);
1175 	add_property_long(value, "length", field->length);
1176 	add_property_long(value, "charsetnr", field->charsetnr);
1177 	add_property_long(value, "flags", field->flags);
1178 	add_property_long(value, "type", field->type);
1179 	add_property_long(value, "decimals", field->decimals);
1180 }
1181 /* }}} */
1182 
1183 /* {{{ proto mixed mysqli_fetch_field(object result)
1184    Get column information from a result and return as an object */
1185 PHP_FUNCTION(mysqli_fetch_field)
1186 {
1187 	MYSQL_RES	*result;
1188 	zval		*mysql_result;
1189 	const MYSQL_FIELD	*field;
1190 
1191 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
1192 		return;
1193 	}
1194 
1195 	MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1196 
1197 	if (!(field = mysql_fetch_field(result))) {
1198 		RETURN_FALSE;
1199 	}
1200 
1201 	object_init(return_value);
1202 	php_add_field_properties(return_value, field);
1203 }
1204 /* }}} */
1205 
1206 /* {{{ proto mixed mysqli_fetch_fields(object result)
1207    Return array of objects containing field meta-data */
1208 PHP_FUNCTION(mysqli_fetch_fields)
1209 {
1210 	MYSQL_RES	*result;
1211 	zval		*mysql_result;
1212 	zval		obj;
1213 
1214 	unsigned int i, num_fields;
1215 
1216 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
1217 		return;
1218 	}
1219 
1220 	MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1221 
1222 	array_init(return_value);
1223 	num_fields = mysql_num_fields(result);
1224 
1225 	for (i = 0; i < num_fields; i++) {
1226 		const MYSQL_FIELD *field = mysql_fetch_field_direct(result, i);
1227 
1228 		object_init(&obj);
1229 
1230 		php_add_field_properties(&obj, field);
1231 		add_index_zval(return_value, i, &obj);
1232 	}
1233 }
1234 /* }}} */
1235 
1236 /* {{{ proto mixed mysqli_fetch_field_direct(object result, int offset)
1237    Fetch meta-data for a single field */
1238 PHP_FUNCTION(mysqli_fetch_field_direct)
1239 {
1240 	MYSQL_RES	*result;
1241 	zval		*mysql_result;
1242 	const MYSQL_FIELD	*field;
1243 	zend_long		offset;
1244 
1245 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &mysql_result, mysqli_result_class_entry, &offset) == FAILURE) {
1246 		return;
1247 	}
1248 
1249 	MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1250 
1251 	if (offset < 0 || offset >= (zend_long) mysql_num_fields(result)) {
1252 		php_error_docref(NULL, E_WARNING, "Field offset is invalid for resultset");
1253 		RETURN_FALSE;
1254 	}
1255 
1256 	if (!(field = mysql_fetch_field_direct(result,offset))) {
1257 		RETURN_FALSE;
1258 	}
1259 
1260 	object_init(return_value);
1261 	php_add_field_properties(return_value, field);
1262 }
1263 /* }}} */
1264 
1265 /* {{{ proto mixed mysqli_fetch_lengths(object result)
1266    Get the length of each output in a result */
1267 PHP_FUNCTION(mysqli_fetch_lengths)
1268 {
1269 	MYSQL_RES		*result;
1270 	zval			*mysql_result;
1271 	unsigned int	i, num_fields;
1272 #if defined(MYSQLI_USE_MYSQLND)
1273 	const size_t	*ret;
1274 #else
1275 	const zend_ulong *ret;
1276 #endif
1277 
1278 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
1279 		return;
1280 	}
1281 
1282 	MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1283 
1284 	if (!(ret = mysql_fetch_lengths(result))) {
1285 		RETURN_FALSE;
1286 	}
1287 
1288 	array_init(return_value);
1289 	num_fields = mysql_num_fields(result);
1290 
1291 	for (i = 0; i < num_fields; i++) {
1292 		add_index_long(return_value, i, ret[i]);
1293 	}
1294 }
1295 /* }}} */
1296 
1297 /* {{{ proto array mysqli_fetch_row(object result)
1298    Get a result row as an enumerated array */
1299 PHP_FUNCTION(mysqli_fetch_row)
1300 {
1301 	php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, MYSQLI_NUM, 0);
1302 }
1303 /* }}} */
1304 
1305 /* {{{ proto int mysqli_field_count(object link)
1306    Fetch the number of fields returned by the last query for the given link
1307 */
1308 PHP_FUNCTION(mysqli_field_count)
1309 {
1310 	MY_MYSQL	*mysql;
1311 	zval		*mysql_link;
1312 
1313 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1314 		return;
1315 	}
1316 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1317 
1318 	RETURN_LONG(mysql_field_count(mysql->mysql));
1319 }
1320 /* }}} */
1321 
1322 /* {{{ proto int mysqli_field_seek(object result, int fieldnr)
1323    Set result pointer to a specified field offset
1324 */
1325 PHP_FUNCTION(mysqli_field_seek)
1326 {
1327 	MYSQL_RES		*result;
1328 	zval			*mysql_result;
1329 	zend_long	fieldnr;
1330 
1331 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &mysql_result, mysqli_result_class_entry, &fieldnr) == FAILURE) {
1332 		return;
1333 	}
1334 	MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1335 
1336 	if (fieldnr < 0 || (uint32_t)fieldnr >= mysql_num_fields(result)) {
1337 		php_error_docref(NULL, E_WARNING, "Invalid field offset");
1338 		RETURN_FALSE;
1339 	}
1340 
1341 	mysql_field_seek(result, fieldnr);
1342 	RETURN_TRUE;
1343 }
1344 /* }}} */
1345 
1346 /* {{{ proto int mysqli_field_tell(object result)
1347    Get current field offset of result pointer */
1348 PHP_FUNCTION(mysqli_field_tell)
1349 {
1350 	MYSQL_RES	*result;
1351 	zval		*mysql_result;
1352 
1353 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
1354 		return;
1355 	}
1356 	MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1357 
1358 	RETURN_LONG(mysql_field_tell(result));
1359 }
1360 /* }}} */
1361 
1362 /* {{{ proto void mysqli_free_result(object result)
1363    Free query result memory for the given result handle */
1364 PHP_FUNCTION(mysqli_free_result)
1365 {
1366 	MYSQL_RES	*result;
1367 	zval		*mysql_result;
1368 
1369 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
1370 		return;
1371 	}
1372 	MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1373 
1374 	mysqli_free_result(result, FALSE);
1375 	MYSQLI_CLEAR_RESOURCE(mysql_result);
1376 }
1377 /* }}} */
1378 
1379 /* {{{ proto string mysqli_get_client_info(void)
1380    Get MySQL client info */
1381 PHP_FUNCTION(mysqli_get_client_info)
1382 {
1383 	const char * info = mysql_get_client_info();
1384 	if (info) {
1385 		RETURN_STRING(info);
1386 	}
1387 }
1388 /* }}} */
1389 
1390 /* {{{ proto int mysqli_get_client_version(void)
1391    Get MySQL client info */
1392 PHP_FUNCTION(mysqli_get_client_version)
1393 {
1394 	RETURN_LONG((zend_long)mysql_get_client_version());
1395 }
1396 /* }}} */
1397 
1398 /* {{{ proto string mysqli_get_host_info(object link)
1399    Get MySQL host info */
1400 PHP_FUNCTION(mysqli_get_host_info)
1401 {
1402 	MY_MYSQL	*mysql;
1403 	zval		*mysql_link = NULL;
1404 
1405 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1406 		return;
1407 	}
1408 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1409 #if !defined(MYSQLI_USE_MYSQLND)
1410 	RETURN_STRING((mysql->mysql->host_info) ? mysql->mysql->host_info : "");
1411 #else
1412 	RETURN_STRING((mysql->mysql->data->host_info) ? mysql->mysql->data->host_info : "");
1413 #endif
1414 }
1415 /* }}} */
1416 
1417 /* {{{ proto int mysqli_get_proto_info(object link)
1418    Get MySQL protocol information */
1419 PHP_FUNCTION(mysqli_get_proto_info)
1420 {
1421 	MY_MYSQL	*mysql;
1422 	zval		*mysql_link = NULL;
1423 
1424 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1425 		return;
1426 	}
1427 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1428 	RETURN_LONG(mysql_get_proto_info(mysql->mysql));
1429 }
1430 /* }}} */
1431 
1432 /* {{{ proto string mysqli_get_server_info(object link)
1433    Get MySQL server info */
1434 PHP_FUNCTION(mysqli_get_server_info)
1435 {
1436 	MY_MYSQL	*mysql;
1437 	zval		*mysql_link = NULL;
1438 	const char	*info;
1439 
1440 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1441 		return;
1442 	}
1443 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1444 
1445 	info = mysql_get_server_info(mysql->mysql);
1446 	if (info) {
1447 		RETURN_STRING(info);
1448 	}
1449 }
1450 /* }}} */
1451 
1452 /* {{{ proto int mysqli_get_server_version(object link)
1453    Return the MySQL version for the server referenced by the given link */
1454 PHP_FUNCTION(mysqli_get_server_version)
1455 {
1456 	MY_MYSQL	*mysql;
1457 	zval		*mysql_link = NULL;
1458 
1459 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1460 		return;
1461 	}
1462 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1463 
1464 	RETURN_LONG(mysql_get_server_version(mysql->mysql));
1465 }
1466 /* }}} */
1467 
1468 /* {{{ proto string mysqli_info(object link)
1469    Get information about the most recent query */
1470 PHP_FUNCTION(mysqli_info)
1471 {
1472 	MY_MYSQL	*mysql;
1473 	zval		*mysql_link = NULL;
1474 	const char	*info;
1475 
1476 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1477 		return;
1478 	}
1479 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1480 
1481 	info = mysql_info(mysql->mysql);
1482 	if (info) {
1483 		RETURN_STRING(info);
1484 	}
1485 }
1486 /* }}} */
1487 
1488 /* {{{ php_mysqli_init() */
1489 void php_mysqli_init(INTERNAL_FUNCTION_PARAMETERS, zend_bool is_method)
1490 {
1491 	MYSQLI_RESOURCE *mysqli_resource;
1492 	MY_MYSQL *mysql;
1493 
1494 	if (is_method && (Z_MYSQLI_P(getThis()))->ptr) {
1495 		return;
1496 	}
1497 
1498 	mysql = (MY_MYSQL *)ecalloc(1, sizeof(MY_MYSQL));
1499 
1500 #if !defined(MYSQLI_USE_MYSQLND)
1501 	if (!(mysql->mysql = mysql_init(NULL)))
1502 #else
1503 	/*
1504 	  We create always persistent, as if the user want to connecto
1505 	  to p:somehost, we can't convert the handle then
1506 	*/
1507 	if (!(mysql->mysql = mysqlnd_init(MYSQLND_CLIENT_KNOWS_RSET_COPY_DATA, TRUE)))
1508 #endif
1509 	{
1510 		efree(mysql);
1511 		RETURN_FALSE;
1512 	}
1513 
1514 	mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
1515 	mysqli_resource->ptr = (void *)mysql;
1516 	mysqli_resource->status = MYSQLI_STATUS_INITIALIZED;
1517 
1518 	if (!is_method) {
1519 		MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_link_class_entry);
1520 	} else {
1521 		(Z_MYSQLI_P(getThis()))->ptr = mysqli_resource;
1522 	}
1523 }
1524 /* }}} */
1525 
1526 /* {{{ proto resource mysqli_init(void)
1527    Initialize mysqli and return a resource for use with mysql_real_connect */
1528 PHP_FUNCTION(mysqli_init)
1529 {
1530 	php_mysqli_init(INTERNAL_FUNCTION_PARAM_PASSTHRU, FALSE);
1531 }
1532 /* }}} */
1533 
1534 /* {{{ proto resource mysqli::init(void)
1535    Initialize mysqli and return a resource for use with mysql_real_connect */
1536 PHP_FUNCTION(mysqli_init_method)
1537 {
1538 	php_mysqli_init(INTERNAL_FUNCTION_PARAM_PASSTHRU, TRUE);
1539 }
1540 /* }}} */
1541 
1542 /* {{{ proto mixed mysqli_insert_id(object link)
1543    Get the ID generated from the previous INSERT operation */
1544 PHP_FUNCTION(mysqli_insert_id)
1545 {
1546 	MY_MYSQL		*mysql;
1547 	my_ulonglong	rc;
1548 	zval			*mysql_link;
1549 
1550 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1551 		return;
1552 	}
1553 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1554 	rc = mysql_insert_id(mysql->mysql);
1555 	MYSQLI_RETURN_LONG_INT(rc)
1556 }
1557 /* }}} */
1558 
1559 /* {{{ proto bool mysqli_kill(object link, int processid)
1560    Kill a mysql process on the server */
1561 PHP_FUNCTION(mysqli_kill)
1562 {
1563 	MY_MYSQL	*mysql;
1564 	zval		*mysql_link;
1565 	zend_long		processid;
1566 
1567 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &mysql_link, mysqli_link_class_entry, &processid) == FAILURE) {
1568 		return;
1569 	}
1570 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1571 
1572 	if (processid <= 0) {
1573 		php_error_docref(NULL, E_WARNING, "processid should have positive value");
1574 		RETURN_FALSE;
1575 	}
1576 
1577 	if (mysql_kill(mysql->mysql, processid)) {
1578 		MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
1579 		RETURN_FALSE;
1580 	}
1581 	RETURN_TRUE;
1582 }
1583 /* }}} */
1584 
1585 /* {{{ proto bool mysqli_more_results(object link)
1586    check if there any more query results from a multi query */
1587 PHP_FUNCTION(mysqli_more_results)
1588 {
1589 	MY_MYSQL	*mysql;
1590 	zval		*mysql_link;
1591 
1592 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1593 		return;
1594 	}
1595 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1596 
1597 	RETURN_BOOL(mysql_more_results(mysql->mysql));
1598 }
1599 /* }}} */
1600 
1601 /* {{{ proto bool mysqli_next_result(object link)
1602    read next result from multi_query */
1603 PHP_FUNCTION(mysqli_next_result) {
1604 	MY_MYSQL	*mysql;
1605 	zval		*mysql_link;
1606 
1607 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1608 		return;
1609 	}
1610 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1611 
1612 	if (mysql_next_result(mysql->mysql)) {
1613 		MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
1614 		RETURN_FALSE;
1615 	}
1616 	RETURN_TRUE;
1617 }
1618 /* }}} */
1619 
1620 #if defined(HAVE_STMT_NEXT_RESULT) && defined(MYSQLI_USE_MYSQLND)
1621 /* {{{ proto bool mysqli_stmt_more_results(object link)
1622    check if there any more query results from a multi query */
1623 PHP_FUNCTION(mysqli_stmt_more_results)
1624 {
1625 	MY_STMT		*stmt;
1626 	zval		*mysql_stmt;
1627 
1628 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
1629 		return;
1630 	}
1631 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
1632 
1633 	RETURN_BOOL(mysqlnd_stmt_more_results(stmt->stmt));
1634 }
1635 /* }}} */
1636 
1637 /* {{{ proto bool mysqli_stmt_next_result(object link)
1638    read next result from multi_query */
1639 PHP_FUNCTION(mysqli_stmt_next_result) {
1640 	MY_STMT		*stmt;
1641 	zval		*mysql_stmt;
1642 
1643 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
1644 		return;
1645 	}
1646 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
1647 
1648 	if (mysql_stmt_next_result(stmt->stmt)) {
1649 		MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
1650 		RETURN_FALSE;
1651 	}
1652 	RETURN_TRUE;
1653 }
1654 /* }}} */
1655 #endif
1656 
1657 /* {{{ proto int mysqli_num_fields(object result)
1658    Get number of fields in result */
1659 PHP_FUNCTION(mysqli_num_fields)
1660 {
1661 	MYSQL_RES	*result;
1662 	zval		*mysql_result;
1663 
1664 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
1665 		return;
1666 	}
1667 	MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1668 
1669 	RETURN_LONG(mysql_num_fields(result));
1670 }
1671 /* }}} */
1672 
1673 /* {{{ proto mixed mysqli_num_rows(object result)
1674    Get number of rows in result */
1675 PHP_FUNCTION(mysqli_num_rows)
1676 {
1677 	MYSQL_RES	*result;
1678 	zval		*mysql_result;
1679 
1680 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
1681 		return;
1682 	}
1683 	MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1684 
1685 	if (mysqli_result_is_unbuffered_and_not_everything_is_fetched(result)) {
1686 		php_error_docref(NULL, E_WARNING, "Function cannot be used with MYSQL_USE_RESULT");
1687 		RETURN_LONG(0);
1688 	}
1689 
1690 	MYSQLI_RETURN_LONG_INT(mysql_num_rows(result));
1691 }
1692 /* }}} */
1693 
1694 /* {{{ mysqli_options_get_option_zval_type */
1695 static int mysqli_options_get_option_zval_type(int option)
1696 {
1697 	switch (option) {
1698 #ifdef MYSQLI_USE_MYSQLND
1699 		case MYSQLND_OPT_NET_CMD_BUFFER_SIZE:
1700 		case MYSQLND_OPT_NET_READ_BUFFER_SIZE:
1701 #ifdef MYSQLND_STRING_TO_INT_CONVERSION
1702 		case MYSQLND_OPT_INT_AND_FLOAT_NATIVE:
1703 #endif
1704 #endif /* MYSQLI_USE_MYSQLND */
1705 		case MYSQL_OPT_CONNECT_TIMEOUT:
1706 #ifdef MYSQL_REPORT_DATA_TRUNCATION
1707 		case MYSQL_REPORT_DATA_TRUNCATION:
1708 #endif
1709 		case MYSQL_OPT_LOCAL_INFILE:
1710 		case MYSQL_OPT_NAMED_PIPE:
1711 #ifdef MYSQL_OPT_PROTOCOL
1712                 case MYSQL_OPT_PROTOCOL:
1713 #endif /* MySQL 4.1.0 */
1714 		case MYSQL_OPT_READ_TIMEOUT:
1715 		case MYSQL_OPT_WRITE_TIMEOUT:
1716 #ifdef MYSQL_OPT_GUESS_CONNECTION /* removed in MySQL-8.0 */
1717 		case MYSQL_OPT_GUESS_CONNECTION:
1718 		case MYSQL_OPT_USE_EMBEDDED_CONNECTION:
1719 		case MYSQL_OPT_USE_REMOTE_CONNECTION:
1720 		case MYSQL_SECURE_AUTH:
1721 #endif
1722 #ifdef MYSQL_OPT_RECONNECT
1723 		case MYSQL_OPT_RECONNECT:
1724 #endif /* MySQL 5.0.13 */
1725 #ifdef MYSQL_OPT_SSL_VERIFY_SERVER_CERT
1726 		case MYSQL_OPT_SSL_VERIFY_SERVER_CERT:
1727 #endif /* MySQL 5.0.23 */
1728 #ifdef MYSQL_OPT_COMPRESS
1729 		case MYSQL_OPT_COMPRESS:
1730 #endif /* mysqlnd @ PHP 5.3.2 */
1731 #if (MYSQL_VERSION_ID >= 50611 && defined(CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS)) || defined(MYSQLI_USE_MYSQLND)
1732 		case MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS:
1733 #endif
1734 			return IS_LONG;
1735 
1736 #ifdef MYSQL_SHARED_MEMORY_BASE_NAME
1737 		case MYSQL_SHARED_MEMORY_BASE_NAME:
1738 #endif /* MySQL 4.1.0 */
1739 #ifdef MYSQL_SET_CLIENT_IP
1740 		case MYSQL_SET_CLIENT_IP:
1741 #endif /* MySQL 4.1.1 */
1742 		case MYSQL_READ_DEFAULT_FILE:
1743 		case MYSQL_READ_DEFAULT_GROUP:
1744 		case MYSQL_INIT_COMMAND:
1745 		case MYSQL_SET_CHARSET_NAME:
1746 		case MYSQL_SET_CHARSET_DIR:
1747 #if MYSQL_VERSION_ID > 50605 || defined(MYSQLI_USE_MYSQLND)
1748 		case MYSQL_SERVER_PUBLIC_KEY:
1749 #endif
1750 			return IS_STRING;
1751 
1752 		default:
1753 			return IS_NULL;
1754 	}
1755 }
1756 /* }}} */
1757 
1758 /* {{{ proto bool mysqli_options(object link, int flags, mixed values)
1759    Set options */
1760 PHP_FUNCTION(mysqli_options)
1761 {
1762 	MY_MYSQL		*mysql;
1763 	zval			*mysql_link = NULL;
1764 	zval			*mysql_value;
1765 	zend_long			mysql_option;
1766 	unsigned int	l_value;
1767 	zend_long			ret;
1768 	int				expected_type;
1769 
1770 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Olz", &mysql_link, mysqli_link_class_entry, &mysql_option, &mysql_value) == FAILURE) {
1771 		return;
1772 	}
1773 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_INITIALIZED);
1774 
1775 #if !defined(MYSQLI_USE_MYSQLND)
1776 	if (PG(open_basedir) && PG(open_basedir)[0] != '\0') {
1777 		if(mysql_option == MYSQL_OPT_LOCAL_INFILE) {
1778 			RETURN_FALSE;
1779 		}
1780 	}
1781 #endif
1782 	expected_type = mysqli_options_get_option_zval_type(mysql_option);
1783 	if (expected_type != Z_TYPE_P(mysql_value)) {
1784 		switch (expected_type) {
1785 			case IS_STRING:
1786 				if (!try_convert_to_string(mysql_value)) {
1787 					return;
1788 				}
1789 				break;
1790 			case IS_LONG:
1791 				convert_to_long_ex(mysql_value);
1792 				break;
1793 			default:
1794 				break;
1795 		}
1796 	}
1797 	switch (expected_type) {
1798 		case IS_STRING:
1799 			ret = mysql_options(mysql->mysql, mysql_option, Z_STRVAL_P(mysql_value));
1800 			break;
1801 		case IS_LONG:
1802 			l_value = Z_LVAL_P(mysql_value);
1803 			ret = mysql_options(mysql->mysql, mysql_option, (char *)&l_value);
1804 			break;
1805 		default:
1806 			ret = 1;
1807 			break;
1808 	}
1809 
1810 	RETURN_BOOL(!ret);
1811 }
1812 /* }}} */
1813 
1814 /* {{{ proto bool mysqli_ping(object link)
1815    Ping a server connection or reconnect if there is no connection */
1816 PHP_FUNCTION(mysqli_ping)
1817 {
1818 	MY_MYSQL	*mysql;
1819 	zval		*mysql_link;
1820 	zend_long		rc;
1821 
1822 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1823 		return;
1824 	}
1825 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1826 	rc = mysql_ping(mysql->mysql);
1827 	MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
1828 
1829 	RETURN_BOOL(!rc);
1830 }
1831 /* }}} */
1832 
1833 /* {{{ proto mixed mysqli_prepare(object link, string query)
1834    Prepare a SQL statement for execution */
1835 PHP_FUNCTION(mysqli_prepare)
1836 {
1837 	MY_MYSQL		*mysql;
1838 	MY_STMT			*stmt;
1839 	char			*query = NULL;
1840 	size_t				query_len;
1841 	zval			*mysql_link;
1842 	MYSQLI_RESOURCE	*mysqli_resource;
1843 
1844 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os",&mysql_link, mysqli_link_class_entry, &query, &query_len) == FAILURE) {
1845 		return;
1846 	}
1847 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1848 
1849 #if !defined(MYSQLI_USE_MYSQLND)
1850 	if (mysql->mysql->status == MYSQL_STATUS_GET_RESULT) {
1851 		php_error_docref(NULL, E_WARNING, "All data must be fetched before a new statement prepare takes place");
1852 		RETURN_FALSE;
1853 	}
1854 #endif
1855 
1856 	stmt = (MY_STMT *)ecalloc(1,sizeof(MY_STMT));
1857 
1858 	if ((stmt->stmt = mysql_stmt_init(mysql->mysql))) {
1859 		if (mysql_stmt_prepare(stmt->stmt, query, query_len)) {
1860 			/* mysql_stmt_close() clears errors, so we have to store them temporarily */
1861 #if !defined(MYSQLI_USE_MYSQLND)
1862 			char  last_error[MYSQL_ERRMSG_SIZE];
1863 			char  sqlstate[SQLSTATE_LENGTH+1];
1864 			unsigned int last_errno;
1865 
1866 			last_errno = stmt->stmt->last_errno;
1867 			memcpy(last_error, stmt->stmt->last_error, MYSQL_ERRMSG_SIZE);
1868 			memcpy(sqlstate, mysql->mysql->net.sqlstate, SQLSTATE_LENGTH+1);
1869 #else
1870 			MYSQLND_ERROR_INFO error_info = *mysql->mysql->data->error_info;
1871 			mysql->mysql->data->error_info->error_list.head = NULL;
1872 			mysql->mysql->data->error_info->error_list.tail = NULL;
1873 			mysql->mysql->data->error_info->error_list.count = 0;
1874 #endif
1875 			mysqli_stmt_close(stmt->stmt, FALSE);
1876 			stmt->stmt = NULL;
1877 
1878 			/* restore error messages */
1879 #if !defined(MYSQLI_USE_MYSQLND)
1880 			mysql->mysql->net.last_errno = last_errno;
1881 			memcpy(mysql->mysql->net.last_error, last_error, MYSQL_ERRMSG_SIZE);
1882 			memcpy(mysql->mysql->net.sqlstate, sqlstate, SQLSTATE_LENGTH+1);
1883 #else
1884 			zend_llist_clean(&mysql->mysql->data->error_info->error_list);
1885 			*mysql->mysql->data->error_info = error_info;
1886 #endif
1887 		}
1888 	}
1889 
1890 	/* don't initialize stmt->query with NULL, we ecalloc()-ed the memory */
1891 	/* Get performance boost if reporting is switched off */
1892 	if (stmt->stmt && query_len && (MyG(report_mode) & MYSQLI_REPORT_INDEX)) {
1893 		stmt->query = (char *)emalloc(query_len + 1);
1894 		memcpy(stmt->query, query, query_len);
1895 		stmt->query[query_len] = '\0';
1896 	}
1897 
1898 	/* don't join to the previous if because it won't work if mysql_stmt_prepare_fails */
1899 	if (!stmt->stmt) {
1900 		MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
1901 		efree(stmt);
1902 		RETURN_FALSE;
1903 	}
1904 #ifndef MYSQLI_USE_MYSQLND
1905 	ZVAL_COPY(&stmt->link_handle, mysql_link);
1906 #endif
1907 
1908 	mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
1909 	mysqli_resource->ptr = (void *)stmt;
1910 
1911 	/* change status */
1912 	mysqli_resource->status = MYSQLI_STATUS_VALID;
1913 	MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_stmt_class_entry);
1914 }
1915 /* }}} */
1916 
1917 /* {{{ proto bool mysqli_real_connect(object link [,string hostname [,string username [,string passwd [,string dbname [,int port [,string socket [,int flags]]]]]]])
1918    Open a connection to a mysql server */
1919 PHP_FUNCTION(mysqli_real_connect)
1920 {
1921 	mysqli_common_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, TRUE, FALSE);
1922 }
1923 /* }}} */
1924 
1925 /* {{{ proto bool mysqli_real_query(object link, string query)
1926    Binary-safe version of mysql_query() */
1927 PHP_FUNCTION(mysqli_real_query)
1928 {
1929 	MY_MYSQL	*mysql;
1930 	zval		*mysql_link;
1931 	char		*query = NULL;
1932 	size_t		query_len;
1933 
1934 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &mysql_link, mysqli_link_class_entry, &query, &query_len) == FAILURE) {
1935 		return;
1936 	}
1937 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1938 
1939 	MYSQLI_DISABLE_MQ; /* disable multi statements/queries */
1940 
1941 	if (mysql_real_query(mysql->mysql, query, query_len)) {
1942 		MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
1943 		RETURN_FALSE;
1944 	}
1945 
1946 	if (!mysql_field_count(mysql->mysql)) {
1947 		if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
1948 			php_mysqli_report_index(query, mysqli_server_status(mysql->mysql));
1949 		}
1950 	}
1951 
1952 	RETURN_TRUE;
1953 }
1954 /* }}} */
1955 
1956 #if defined(MYSQLI_USE_MYSQLND) || MYSQL_VERSION_ID < 50707 || defined(MARIADB_BASE_VERSION)
1957 # define mysql_real_escape_string_quote(mysql, to, from, length, quote) \
1958 	mysql_real_escape_string(mysql, to, from, length)
1959 #endif
1960 
1961 /* {{{ proto string mysqli_real_escape_string(object link, string escapestr)
1962    Escapes special characters in a string for use in a SQL statement, taking into account the current charset of the connection */
1963 PHP_FUNCTION(mysqli_real_escape_string) {
1964 	MY_MYSQL	*mysql;
1965 	zval		*mysql_link = NULL;
1966 	char		*escapestr;
1967 	size_t			escapestr_len;
1968 	zend_string *newstr;
1969 
1970 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &mysql_link, mysqli_link_class_entry, &escapestr, &escapestr_len) == FAILURE) {
1971 		return;
1972 	}
1973 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1974 
1975 	newstr = zend_string_safe_alloc(2, escapestr_len, 0, 0);
1976 	ZSTR_LEN(newstr) = mysql_real_escape_string_quote(mysql->mysql, ZSTR_VAL(newstr), escapestr, escapestr_len, '\'');
1977 	newstr = zend_string_truncate(newstr, ZSTR_LEN(newstr), 0);
1978 
1979 	RETURN_NEW_STR(newstr);
1980 }
1981 /* }}} */
1982 
1983 /* {{{ proto bool mysqli_rollback(object link)
1984    Undo actions from current transaction */
1985 PHP_FUNCTION(mysqli_rollback)
1986 {
1987 	MY_MYSQL	*mysql;
1988 	zval		*mysql_link;
1989 	zend_long		flags = TRANS_COR_NO_OPT;
1990 	char *		name = NULL;
1991 	size_t			name_len = 0;
1992 
1993 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|ls", &mysql_link, mysqli_link_class_entry, &flags, &name, &name_len) == FAILURE) {
1994 		return;
1995 	}
1996 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1997 
1998 #if !defined(MYSQLI_USE_MYSQLND)
1999 	if (mysqli_commit_or_rollback_libmysql(mysql->mysql, FALSE, flags, name)) {
2000 #else
2001 	if (FAIL == mysqlnd_rollback(mysql->mysql, flags, name)) {
2002 #endif
2003 		MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
2004 		RETURN_FALSE;
2005 	}
2006 	RETURN_TRUE;
2007 }
2008 /* }}} */
2009 
2010 /* {{{ proto bool mysqli_stmt_send_long_data(object stmt, int param_nr, string data)
2011 */
2012 PHP_FUNCTION(mysqli_stmt_send_long_data)
2013 {
2014 	MY_STMT *stmt;
2015 	zval	*mysql_stmt;
2016 	char	*data;
2017 	zend_long	param_nr;
2018 	size_t		data_len;
2019 
2020 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ols", &mysql_stmt, mysqli_stmt_class_entry, &param_nr, &data, &data_len) == FAILURE) {
2021 		return;
2022 	}
2023 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2024 
2025 	if (param_nr < 0) {
2026 		php_error_docref(NULL, E_WARNING, "Invalid parameter number");
2027 		RETURN_FALSE;
2028 	}
2029 	if (mysql_stmt_send_long_data(stmt->stmt, param_nr, data, data_len)) {
2030 		RETURN_FALSE;
2031 	}
2032 	RETURN_TRUE;
2033 }
2034 /* }}} */
2035 
2036 /* {{{ proto string|int|false mysqli_stmt_affected_rows(object stmt)
2037    Return the number of rows affected in the last query for the given link. */
2038 PHP_FUNCTION(mysqli_stmt_affected_rows)
2039 {
2040 	MY_STMT			*stmt;
2041 	zval			*mysql_stmt;
2042 	my_ulonglong	rc;
2043 
2044 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2045 		return;
2046 	}
2047 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2048 
2049 	rc = mysql_stmt_affected_rows(stmt->stmt);
2050 	if (rc == (my_ulonglong) -1) {
2051 		RETURN_LONG(-1);
2052 	}
2053 	MYSQLI_RETURN_LONG_INT(rc)
2054 }
2055 /* }}} */
2056 
2057 /* {{{ proto bool mysqli_stmt_close(object stmt)
2058    Close statement */
2059 PHP_FUNCTION(mysqli_stmt_close)
2060 {
2061 	MY_STMT		*stmt;
2062 	zval		*mysql_stmt;
2063 
2064 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2065 		return;
2066 	}
2067 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2068 
2069 	mysqli_stmt_close(stmt->stmt, FALSE);
2070 	stmt->stmt = NULL;
2071 	php_clear_stmt_bind(stmt);
2072 	MYSQLI_CLEAR_RESOURCE(mysql_stmt);
2073 	RETURN_TRUE;
2074 }
2075 /* }}} */
2076 
2077 /* {{{ proto void mysqli_stmt_data_seek(object stmt, int offset)
2078    Move internal result pointer */
2079 PHP_FUNCTION(mysqli_stmt_data_seek)
2080 {
2081 	MY_STMT		*stmt;
2082 	zval		*mysql_stmt;
2083 	zend_long		offset;
2084 
2085 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &mysql_stmt, mysqli_stmt_class_entry, &offset) == FAILURE) {
2086 		return;
2087 	}
2088 	if (offset < 0) {
2089 		php_error_docref(NULL, E_WARNING, "Offset must be positive");
2090 		RETURN_FALSE;
2091 	}
2092 
2093 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2094 
2095 	mysql_stmt_data_seek(stmt->stmt, offset);
2096 }
2097 /* }}} */
2098 
2099 /* {{{ proto int mysqli_stmt_field_count(object stmt) {
2100    Return the number of result columns for the given statement */
2101 PHP_FUNCTION(mysqli_stmt_field_count)
2102 {
2103 	MY_STMT		*stmt;
2104 	zval		*mysql_stmt;
2105 
2106 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2107 		return;
2108 	}
2109 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2110 
2111 	RETURN_LONG(mysql_stmt_field_count(stmt->stmt));
2112 }
2113 /* }}} */
2114 
2115 /* {{{ proto void mysqli_stmt_free_result(object stmt)
2116    Free stored result memory for the given statement handle */
2117 PHP_FUNCTION(mysqli_stmt_free_result)
2118 {
2119 	MY_STMT		*stmt;
2120 	zval		*mysql_stmt;
2121 
2122 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2123 		return;
2124 	}
2125 
2126 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2127 
2128 	mysql_stmt_free_result(stmt->stmt);
2129 }
2130 /* }}} */
2131 
2132 /* {{{ proto mixed mysqli_stmt_insert_id(object stmt)
2133    Get the ID generated from the previous INSERT operation */
2134 PHP_FUNCTION(mysqli_stmt_insert_id)
2135 {
2136 	MY_STMT			*stmt;
2137 	my_ulonglong	rc;
2138 	zval			*mysql_stmt;
2139 
2140 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2141 		return;
2142 	}
2143 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2144 	rc = mysql_stmt_insert_id(stmt->stmt);
2145 	MYSQLI_RETURN_LONG_INT(rc)
2146 }
2147 /* }}} */
2148 
2149 /* {{{ proto int mysqli_stmt_param_count(object stmt)
2150    Return the number of parameter for the given statement */
2151 PHP_FUNCTION(mysqli_stmt_param_count)
2152 {
2153 	MY_STMT		*stmt;
2154 	zval		*mysql_stmt;
2155 
2156 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2157 		return;
2158 	}
2159 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2160 
2161 	RETURN_LONG(mysql_stmt_param_count(stmt->stmt));
2162 }
2163 /* }}} */
2164 
2165 /* {{{ proto bool mysqli_stmt_reset(object stmt)
2166    reset a prepared statement */
2167 PHP_FUNCTION(mysqli_stmt_reset)
2168 {
2169 	MY_STMT		*stmt;
2170 	zval		*mysql_stmt;
2171 
2172 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2173 		return;
2174 	}
2175 
2176 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2177 
2178 	if (mysql_stmt_reset(stmt->stmt)) {
2179 		RETURN_FALSE;
2180 	}
2181 	RETURN_TRUE;
2182 }
2183 /* }}} */
2184 
2185 /* {{{ proto mixed mysqli_stmt_num_rows(object stmt)
2186    Return the number of rows in statements result set */
2187 PHP_FUNCTION(mysqli_stmt_num_rows)
2188 {
2189 	MY_STMT			*stmt;
2190 	zval			*mysql_stmt;
2191 	my_ulonglong	rc;
2192 
2193 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2194 		return;
2195 	}
2196 
2197 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2198 
2199 	rc = mysql_stmt_num_rows(stmt->stmt);
2200 	MYSQLI_RETURN_LONG_INT(rc)
2201 }
2202 /* }}} */
2203 
2204 /* {{{ proto bool mysqli_select_db(object link, string dbname)
2205    Select a MySQL database */
2206 PHP_FUNCTION(mysqli_select_db)
2207 {
2208 	MY_MYSQL	*mysql;
2209 	zval		*mysql_link;
2210 	char		*dbname;
2211 	size_t			dbname_len;
2212 
2213 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &mysql_link, mysqli_link_class_entry, &dbname, &dbname_len) == FAILURE) {
2214 		return;
2215 	}
2216 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
2217 
2218 	if (mysql_select_db(mysql->mysql, dbname)) {
2219 		MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
2220 		RETURN_FALSE;
2221 	}
2222 	RETURN_TRUE;
2223 }
2224 /* }}} */
2225 
2226 /* {{{ proto string mysqli_sqlstate(object link)
2227    Returns the SQLSTATE error from previous MySQL operation */
2228 PHP_FUNCTION(mysqli_sqlstate)
2229 {
2230 	MY_MYSQL	*mysql;
2231 	zval		*mysql_link;
2232 	const char	*state;
2233 
2234 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
2235 		return;
2236 	}
2237 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
2238 	state = mysql_sqlstate(mysql->mysql);
2239 	if (state) {
2240 		RETURN_STRING(state);
2241 	}
2242 }
2243 /* }}} */
2244 
2245 /* {{{ proto bool mysqli_ssl_set(object link ,string key ,string cert ,string ca ,string capath ,string cipher])
2246 */
2247 PHP_FUNCTION(mysqli_ssl_set)
2248 {
2249 	MY_MYSQL	*mysql;
2250 	zval		*mysql_link;
2251 	char		*ssl_parm[5];
2252 	size_t			ssl_parm_len[5], i;
2253 
2254 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Osssss", &mysql_link, mysqli_link_class_entry, &ssl_parm[0], &ssl_parm_len[0], &ssl_parm[1], &ssl_parm_len[1], &ssl_parm[2], &ssl_parm_len[2], &ssl_parm[3], &ssl_parm_len[3], &ssl_parm[4], &ssl_parm_len[4])   == FAILURE) {
2255 		return;
2256 	}
2257 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_INITIALIZED);
2258 
2259 	for (i = 0; i < 5; i++) {
2260 		if (!ssl_parm_len[i]) {
2261 			ssl_parm[i] = NULL;
2262 		}
2263 	}
2264 
2265 	mysql_ssl_set(mysql->mysql, ssl_parm[0], ssl_parm[1], ssl_parm[2], ssl_parm[3], ssl_parm[4]);
2266 
2267 	RETURN_TRUE;
2268 }
2269 /* }}} */
2270 
2271 /* {{{ proto mixed mysqli_stat(object link)
2272    Get current system status */
2273 PHP_FUNCTION(mysqli_stat)
2274 {
2275 	MY_MYSQL	*mysql;
2276 	zval		*mysql_link;
2277 #if defined(MYSQLI_USE_MYSQLND)
2278 	zend_string *stat;
2279 #else
2280 	char		*stat;
2281 #endif
2282 
2283 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
2284 		return;
2285 	}
2286 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
2287 
2288 #if !defined(MYSQLI_USE_MYSQLND)
2289 	if ((stat = (char *)mysql_stat(mysql->mysql)))
2290 	{
2291 		RETURN_STRING(stat);
2292 #else
2293 	if (mysqlnd_stat(mysql->mysql, &stat) == PASS)
2294 	{
2295 		RETURN_STR(stat);
2296 #endif
2297 	} else {
2298 		RETURN_FALSE;
2299 	}
2300 }
2301 
2302 /* }}} */
2303 
2304 /* {{{ proto bool mysqli_refresh(object link, int options)
2305    Flush tables or caches, or reset replication server information */
2306 PHP_FUNCTION(mysqli_refresh)
2307 {
2308 	MY_MYSQL *mysql;
2309 	zval *mysql_link = NULL;
2310 	zend_long options;
2311 
2312 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &mysql_link, mysqli_link_class_entry, &options) == FAILURE) {
2313 		return;
2314 	}
2315 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_INITIALIZED);
2316 #ifdef MYSQLI_USE_MYSQLND
2317 	RETURN_BOOL(!mysql_refresh(mysql->mysql, (uint8_t) options));
2318 #else
2319 	RETURN_BOOL(!mysql_refresh(mysql->mysql, options));
2320 #endif
2321 }
2322 /* }}} */
2323 
2324 /* {{{ proto int mysqli_stmt_attr_set(object stmt, int attr, int mode)
2325 */
2326 PHP_FUNCTION(mysqli_stmt_attr_set)
2327 {
2328 	MY_STMT	*stmt;
2329 	zval	*mysql_stmt;
2330 	zend_long	mode_in;
2331 #if MYSQL_VERSION_ID >= 50107
2332 	my_bool	mode_b;
2333 #endif
2334 	unsigned long	mode;
2335 	zend_long	attr;
2336 	void	*mode_p;
2337 
2338 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Oll", &mysql_stmt, mysqli_stmt_class_entry, &attr, &mode_in) == FAILURE) {
2339 		return;
2340 	}
2341 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2342 
2343 	if (mode_in < 0) {
2344 		php_error_docref(NULL, E_WARNING, "mode should be non-negative, " ZEND_LONG_FMT " passed", mode_in);
2345 		RETURN_FALSE;
2346 	}
2347 
2348 	switch (attr) {
2349 #if MYSQL_VERSION_ID >= 50107
2350 	case STMT_ATTR_UPDATE_MAX_LENGTH:
2351 		mode_b = (my_bool) mode_in;
2352 		mode_p = &mode_b;
2353 		break;
2354 #endif
2355 	default:
2356 		mode = mode_in;
2357 		mode_p = &mode;
2358 		break;
2359 	}
2360 #if !defined(MYSQLI_USE_MYSQLND)
2361 	if (mysql_stmt_attr_set(stmt->stmt, attr, mode_p)) {
2362 #else
2363 	if (FAIL == mysql_stmt_attr_set(stmt->stmt, attr, mode_p)) {
2364 #endif
2365 		MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
2366 		RETURN_FALSE;
2367 	}
2368 	RETURN_TRUE;
2369 }
2370 /* }}} */
2371 
2372 /* {{{ proto int mysqli_stmt_attr_get(object stmt, int attr)
2373 */
2374 PHP_FUNCTION(mysqli_stmt_attr_get)
2375 {
2376 	MY_STMT	*stmt;
2377 	zval	*mysql_stmt;
2378 	unsigned long	value = 0;
2379 	zend_long	attr;
2380 	int		rc;
2381 
2382 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &mysql_stmt, mysqli_stmt_class_entry, &attr) == FAILURE) {
2383 		return;
2384 	}
2385 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2386 
2387 	if ((rc = mysql_stmt_attr_get(stmt->stmt, attr, &value))) {
2388 		RETURN_FALSE;
2389 	}
2390 
2391 #if MYSQL_VERSION_ID >= 50107
2392 	if (attr == STMT_ATTR_UPDATE_MAX_LENGTH)
2393 		value = *((my_bool *)&value);
2394 #endif
2395 	RETURN_LONG((unsigned long)value);
2396 }
2397 /* }}} */
2398 
2399 /* {{{ proto int mysqli_stmt_errno(object stmt)
2400 */
2401 PHP_FUNCTION(mysqli_stmt_errno)
2402 {
2403 	MY_STMT	*stmt;
2404 	zval	*mysql_stmt;
2405 
2406 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2407 		return;
2408 	}
2409 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_INITIALIZED);
2410 
2411 	RETURN_LONG(mysql_stmt_errno(stmt->stmt));
2412 }
2413 /* }}} */
2414 
2415 /* {{{ proto string mysqli_stmt_error(object stmt)
2416 */
2417 PHP_FUNCTION(mysqli_stmt_error)
2418 {
2419 	MY_STMT	*stmt;
2420 	zval 	*mysql_stmt;
2421 	const char * err;
2422 
2423 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2424 		return;
2425 	}
2426 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_INITIALIZED);
2427 
2428 	err = mysql_stmt_error(stmt->stmt);
2429 	if (err) {
2430 		RETURN_STRING(err);
2431 	}
2432 }
2433 /* }}} */
2434 
2435 /* {{{ proto mixed mysqli_stmt_init(object link)
2436    Initialize statement object
2437 */
2438 PHP_FUNCTION(mysqli_stmt_init)
2439 {
2440 	MY_MYSQL		*mysql;
2441 	MY_STMT			*stmt;
2442 	zval			*mysql_link;
2443 	MYSQLI_RESOURCE	*mysqli_resource;
2444 
2445 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O",&mysql_link, mysqli_link_class_entry) == FAILURE) {
2446 		return;
2447 	}
2448 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
2449 
2450 	stmt = (MY_STMT *)ecalloc(1,sizeof(MY_STMT));
2451 
2452 	if (!(stmt->stmt = mysql_stmt_init(mysql->mysql))) {
2453 		efree(stmt);
2454 		RETURN_FALSE;
2455 	}
2456 #ifndef MYSQLI_USE_MYSQLND
2457 	ZVAL_COPY(&stmt->link_handle, mysql_link);
2458 #endif
2459 
2460 	mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
2461 	mysqli_resource->status = MYSQLI_STATUS_INITIALIZED;
2462 	mysqli_resource->ptr = (void *)stmt;
2463 	MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_stmt_class_entry);
2464 }
2465 /* }}} */
2466 
2467 /* {{{ proto bool mysqli_stmt_prepare(object stmt, string query)
2468    prepare server side statement with query
2469 */
2470 PHP_FUNCTION(mysqli_stmt_prepare)
2471 {
2472 	MY_STMT	*stmt;
2473 	zval 	*mysql_stmt;
2474 	char	*query;
2475 	size_t		query_len;
2476 
2477 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &mysql_stmt, mysqli_stmt_class_entry, &query, &query_len) == FAILURE) {
2478 		return;
2479 	}
2480 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_INITIALIZED);
2481 
2482 	if (mysql_stmt_prepare(stmt->stmt, query, query_len)) {
2483 		MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
2484 		RETURN_FALSE;
2485 	}
2486 	/* change status */
2487 	MYSQLI_SET_STATUS(mysql_stmt, MYSQLI_STATUS_VALID);
2488 	RETURN_TRUE;
2489 }
2490 /* }}} */
2491 
2492 /* {{{ proto mixed mysqli_stmt_result_metadata(object stmt)
2493    return result set from statement */
2494 PHP_FUNCTION(mysqli_stmt_result_metadata)
2495 {
2496 	MY_STMT			*stmt;
2497 	MYSQL_RES		*result;
2498 	zval			*mysql_stmt;
2499 	MYSQLI_RESOURCE	*mysqli_resource;
2500 
2501 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2502 		return;
2503 	}
2504 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2505 
2506 	if (!(result = mysql_stmt_result_metadata(stmt->stmt))){
2507 		MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
2508 		RETURN_FALSE;
2509 	}
2510 
2511 	mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
2512 	mysqli_resource->ptr = (void *)result;
2513 	mysqli_resource->status = MYSQLI_STATUS_VALID;
2514 	MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_result_class_entry);
2515 }
2516 /* }}} */
2517 
2518 /* {{{ proto bool mysqli_stmt_store_result(object stmt)
2519 */
2520 PHP_FUNCTION(mysqli_stmt_store_result)
2521 {
2522 	MY_STMT	*stmt;
2523 	zval	*mysql_stmt;
2524 
2525 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2526 		return;
2527 	}
2528 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2529 
2530 #if !defined(MYSQLI_USE_MYSQLND)
2531 	{
2532 		/*
2533 		  If the user wants to store the data and we have BLOBs/TEXTs we try to allocate
2534 		  not the maximal length of the type (which is 16MB even for LONGBLOB) but
2535 		  the maximal length of the field in the result set. If he/she has quite big
2536 		  BLOB/TEXT columns after calling store_result() the memory usage of PHP will
2537 		  double - but this is a known problem of the simple MySQL API ;)
2538 		*/
2539 		int	i = 0;
2540 
2541 		for (i = mysql_stmt_field_count(stmt->stmt) - 1; i >=0; --i) {
2542 			if (stmt->stmt->fields && (stmt->stmt->fields[i].type == MYSQL_TYPE_BLOB ||
2543 				stmt->stmt->fields[i].type == MYSQL_TYPE_MEDIUM_BLOB ||
2544 				stmt->stmt->fields[i].type == MYSQL_TYPE_LONG_BLOB ||
2545 				stmt->stmt->fields[i].type == MYSQL_TYPE_GEOMETRY))
2546 			{
2547 #if MYSQL_VERSION_ID >= 50107
2548 				my_bool	tmp=1;
2549 #else
2550 				uint32_t tmp=1;
2551 #endif
2552 				mysql_stmt_attr_set(stmt->stmt, STMT_ATTR_UPDATE_MAX_LENGTH, &tmp);
2553 				break;
2554 			}
2555 		}
2556 	}
2557 #endif
2558 
2559 	if (mysql_stmt_store_result(stmt->stmt)){
2560 		MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
2561 		RETURN_FALSE;
2562 	}
2563 	RETURN_TRUE;
2564 }
2565 /* }}} */
2566 
2567 /* {{{ proto string mysqli_stmt_sqlstate(object stmt)
2568 */
2569 PHP_FUNCTION(mysqli_stmt_sqlstate)
2570 {
2571 	MY_STMT	*stmt;
2572 	zval	*mysql_stmt;
2573 	const char * state;
2574 
2575 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2576 		return;
2577 	}
2578 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2579 
2580 	state = mysql_stmt_sqlstate(stmt->stmt);
2581 	if (state) {
2582 		RETURN_STRING(state);
2583 	}
2584 }
2585 /* }}} */
2586 
2587 /* {{{ proto object mysqli_store_result(object link [, int flags])
2588    Buffer result set on client */
2589 PHP_FUNCTION(mysqli_store_result)
2590 {
2591 	MY_MYSQL		*mysql;
2592 	MYSQL_RES		*result;
2593 	zval			*mysql_link;
2594 	MYSQLI_RESOURCE	*mysqli_resource;
2595 	zend_long flags = 0;
2596 
2597 
2598 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|l", &mysql_link, mysqli_link_class_entry, &flags) == FAILURE) {
2599 		return;
2600 	}
2601 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
2602 #if MYSQLI_USE_MYSQLND
2603 	result = flags & MYSQLI_STORE_RESULT_COPY_DATA? mysqlnd_store_result_ofs(mysql->mysql) : mysqlnd_store_result(mysql->mysql);
2604 #else
2605 	result = mysql_store_result(mysql->mysql);
2606 #endif
2607 	if (!result) {
2608 		MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
2609 		RETURN_FALSE;
2610 	}
2611 	if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
2612 		php_mysqli_report_index("from previous query", mysqli_server_status(mysql->mysql));
2613 	}
2614 
2615 	mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
2616 	mysqli_resource->ptr = (void *)result;
2617 	mysqli_resource->status = MYSQLI_STATUS_VALID;
2618 	MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_result_class_entry);
2619 }
2620 /* }}} */
2621 
2622 /* {{{ proto int mysqli_thread_id(object link)
2623    Return the current thread ID */
2624 PHP_FUNCTION(mysqli_thread_id)
2625 {
2626 	MY_MYSQL	*mysql;
2627 	zval		*mysql_link;
2628 
2629 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
2630 		return;
2631 	}
2632 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
2633 
2634 	RETURN_LONG((zend_long) mysql_thread_id(mysql->mysql));
2635 }
2636 /* }}} */
2637 
2638 /* {{{ proto bool mysqli_thread_safe(void)
2639    Return whether thread safety is given or not */
2640 PHP_FUNCTION(mysqli_thread_safe)
2641 {
2642 	RETURN_BOOL(mysql_thread_safe());
2643 }
2644 /* }}} */
2645 
2646 /* {{{ proto mixed mysqli_use_result(object link)
2647    Directly retrieve query results - do not buffer results on client side */
2648 PHP_FUNCTION(mysqli_use_result)
2649 {
2650 	MY_MYSQL		*mysql;
2651 	MYSQL_RES		*result;
2652 	zval			*mysql_link;
2653 	MYSQLI_RESOURCE	*mysqli_resource;
2654 
2655 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
2656 		return;
2657 	}
2658 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
2659 
2660 	if (!(result = mysql_use_result(mysql->mysql))) {
2661 		MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
2662 		RETURN_FALSE;
2663 	}
2664 
2665 	if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
2666 		php_mysqli_report_index("from previous query", mysqli_server_status(mysql->mysql));
2667 	}
2668 	mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
2669 	mysqli_resource->ptr = (void *)result;
2670 	mysqli_resource->status = MYSQLI_STATUS_VALID;
2671 	MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_result_class_entry);
2672 }
2673 /* }}} */
2674 
2675 /* {{{ proto int mysqli_warning_count(object link)
2676    Return number of warnings from the last query for the given link */
2677 PHP_FUNCTION(mysqli_warning_count)
2678 {
2679 	MY_MYSQL	*mysql;
2680 	zval		*mysql_link;
2681 
2682 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
2683 		return;
2684 	}
2685 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
2686 
2687 	RETURN_LONG(mysql_warning_count(mysql->mysql));
2688 }
2689 /* }}} */
2690