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