1 /*
2   +----------------------------------------------------------------------+
3   | PHP Version 7                                                        |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 1997-2018 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 		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 		RETURN_FALSE;
759 	}
760 	RETURN_TRUE;
761 }
762 /* }}} */
763 
764 /* {{{ proto bool mysqli_data_seek(object result, int offset)
765    Move internal result pointer */
766 PHP_FUNCTION(mysqli_data_seek)
767 {
768 	MYSQL_RES	*result;
769 	zval		*mysql_result;
770 	zend_long		offset;
771 
772 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &mysql_result, mysqli_result_class_entry, &offset) == FAILURE) {
773 		return;
774 	}
775 
776 	MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
777 
778 	if (mysqli_result_is_unbuffered(result)) {
779 		php_error_docref(NULL, E_WARNING, "Function cannot be used with MYSQL_USE_RESULT");
780 		RETURN_FALSE;
781 	}
782 
783 	if (offset < 0 || (uint64_t)offset >= mysql_num_rows(result)) {
784 		RETURN_FALSE;
785 	}
786 
787 	mysql_data_seek(result, offset);
788 	RETURN_TRUE;
789 }
790 /* }}} */
791 
792 /* {{{ proto void mysqli_debug(string debug)
793 */
794 PHP_FUNCTION(mysqli_debug)
795 {
796 	char	*debug;
797 	size_t		debug_len;
798 
799 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &debug, &debug_len) == FAILURE) {
800 		return;
801 	}
802 
803 	mysql_debug(debug);
804 	RETURN_TRUE;
805 }
806 /* }}} */
807 
808 /* {{{ proto bool mysqli_dump_debug_info(object link)
809 */
810 PHP_FUNCTION(mysqli_dump_debug_info)
811 {
812 	MY_MYSQL	*mysql;
813 	zval		*mysql_link;
814 
815 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
816 		return;
817 	}
818 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
819 
820 	RETURN_BOOL(!mysql_dump_debug_info(mysql->mysql))
821 }
822 /* }}} */
823 
824 /* {{{ proto int mysqli_errno(object link)
825    Returns the numerical value of the error message from previous MySQL operation */
826 PHP_FUNCTION(mysqli_errno)
827 {
828 	MY_MYSQL	*mysql;
829 	zval		*mysql_link;
830 
831 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
832 		return;
833 	}
834 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
835 	RETURN_LONG(mysql_errno(mysql->mysql));
836 }
837 /* }}} */
838 
839 /* {{{ proto string mysqli_error(object link)
840    Returns the text of the error message from previous MySQL operation */
841 PHP_FUNCTION(mysqli_error)
842 {
843 	MY_MYSQL	*mysql;
844 	zval		*mysql_link;
845 	const char	*err;
846 
847 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
848 		return;
849 	}
850 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
851 	err = mysql_error(mysql->mysql);
852 	if (err) {
853 		RETURN_STRING(err);
854 	}
855 }
856 /* }}} */
857 
858 /* {{{ proto bool mysqli_stmt_execute(object stmt)
859    Execute a prepared statement */
860 PHP_FUNCTION(mysqli_stmt_execute)
861 {
862 	MY_STMT		*stmt;
863 	zval		*mysql_stmt;
864 #ifndef MYSQLI_USE_MYSQLND
865 	unsigned int	i;
866 #endif
867 
868 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
869 		return;
870 	}
871 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
872 
873 #ifndef MYSQLI_USE_MYSQLND
874 	if (stmt->param.var_cnt) {
875 		int j;
876 		for (i = 0; i < stmt->param.var_cnt; i++) {
877 			if (!Z_ISREF(stmt->param.vars[i])) {
878 				continue;
879 			}
880 			for (j = i + 1; j < stmt->param.var_cnt; j++) {
881 				/* Oops, someone binding the same variable - clone */
882 				if (Z_ISREF(stmt->param.vars[j]) &&
883 					   	Z_REFVAL(stmt->param.vars[j]) == Z_REFVAL(stmt->param.vars[i])) {
884 					/*SEPARATE_ZVAL(&stmt->param.vars[j]);*/
885 					Z_DELREF_P(&stmt->param.vars[j]);
886 					ZVAL_COPY(&stmt->param.vars[j], Z_REFVAL(stmt->param.vars[j]));
887 					break;
888 				}
889 			}
890 		}
891 	}
892 	for (i = 0; i < stmt->param.var_cnt; i++) {
893 		if (!Z_ISUNDEF(stmt->param.vars[i])) {
894 			zval *param;
895 			if (Z_ISREF(stmt->param.vars[i])) {
896 				param = Z_REFVAL(stmt->param.vars[i]);
897 			} else {
898 				param = &stmt->param.vars[i];
899 			}
900 			if (!(stmt->param.is_null[i] = (Z_ISNULL_P(param)))) {
901 				switch (stmt->stmt->params[i].buffer_type) {
902 					case MYSQL_TYPE_VAR_STRING:
903 						convert_to_string_ex(param);
904 						stmt->stmt->params[i].buffer = Z_STRVAL_P(param);
905 						stmt->stmt->params[i].buffer_length = Z_STRLEN_P(param);
906 						break;
907 					case MYSQL_TYPE_DOUBLE:
908 						convert_to_double_ex(param);
909 						stmt->stmt->params[i].buffer = &Z_DVAL_P(param);
910 						break;
911 					case MYSQL_TYPE_LONGLONG:
912 					case MYSQL_TYPE_LONG:
913 						convert_to_long_ex(param);
914 						stmt->stmt->params[i].buffer = &Z_LVAL_P(param);
915 						break;
916 					default:
917 						break;
918 				}
919 			}
920 		}
921 	}
922 #endif
923 
924 	if (mysql_stmt_execute(stmt->stmt)) {
925 		MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
926 		RETVAL_FALSE;
927 	} else {
928 		RETVAL_TRUE;
929 	}
930 
931 	if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
932 		php_mysqli_report_index(stmt->query, mysqli_stmt_server_status(stmt->stmt));
933 	}
934 }
935 /* }}} */
936 
937 #ifndef MYSQLI_USE_MYSQLND
938 /* {{{ void mysqli_stmt_fetch_libmysql
939    Fetch results from a prepared statement into the bound variables */
940 void mysqli_stmt_fetch_libmysql(INTERNAL_FUNCTION_PARAMETERS)
941 {
942 	MY_STMT		*stmt;
943 	zval			*mysql_stmt;
944 	unsigned int	i;
945 	zend_ulong			ret;
946 	unsigned int	uval;
947 	my_ulonglong	llval;
948 
949 
950 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
951 		return;
952 	}
953 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
954 
955 	/* reset buffers */
956 	for (i = 0; i < stmt->result.var_cnt; i++) {
957 		if (stmt->result.buf[i].type == IS_STRING) {
958 			memset(stmt->result.buf[i].val, 0, stmt->result.buf[i].buflen);
959 		}
960 	}
961 	ret = mysql_stmt_fetch(stmt->stmt);
962 #ifdef MYSQL_DATA_TRUNCATED
963 	if (!ret || ret == MYSQL_DATA_TRUNCATED) {
964 #else
965 	if (!ret) {
966 #endif
967 		for (i = 0; i < stmt->result.var_cnt; i++) {
968 			zval *result;
969 			/* it must be a reference, isn't it? */
970 			if (Z_ISREF(stmt->result.vars[i])) {
971 				result = Z_REFVAL(stmt->result.vars[i]);
972 			} else {
973 				result = &stmt->result.vars[i];
974 			}
975 			/*
976 			  QQ: Isn't it quite better to call zval_dtor(). What if the user has
977 			  assigned a resource, or an array to the bound variable? We are going
978 			  to leak probably. zval_dtor() will handle also Unicode/Non-unicode mode.
979 			*/
980 			/* Even if the string is of length zero there is one byte alloced so efree() in all cases */
981 			zval_ptr_dtor(result);
982 			if (!stmt->result.is_null[i]) {
983 				switch (stmt->result.buf[i].type) {
984 					case IS_LONG:
985 						if ((stmt->stmt->fields[i].type == MYSQL_TYPE_LONG)
986 						    && (stmt->stmt->fields[i].flags & UNSIGNED_FLAG))
987 						{
988 							/* unsigned int (11) */
989 							uval= *(unsigned int *) stmt->result.buf[i].val;
990 #if SIZEOF_ZEND_LONG==4
991 							if (uval > INT_MAX) {
992 								char *tmp, *p;
993 								int j = 10;
994 								tmp = emalloc(11);
995 								p= &tmp[9];
996 								do {
997 									*p-- = (uval % 10) + 48;
998 									uval = uval / 10;
999 								} while (--j > 0);
1000 								tmp[10]= '\0';
1001 								/* unsigned int > INT_MAX is 10 digits - ALWAYS */
1002 								ZVAL_STRINGL(result, tmp, 10);
1003 								efree(tmp);
1004 								break;
1005 							}
1006 #endif
1007 						}
1008 						if (stmt->stmt->fields[i].flags & UNSIGNED_FLAG) {
1009 							ZVAL_LONG(result, *(unsigned int *)stmt->result.buf[i].val);
1010 						} else {
1011 							ZVAL_LONG(result, *(int *)stmt->result.buf[i].val);
1012 						}
1013 						break;
1014 					case IS_DOUBLE:
1015 					{
1016 						double dval;
1017 						if (stmt->stmt->bind[i].buffer_type == MYSQL_TYPE_FLOAT) {
1018 #ifndef NOT_FIXED_DEC
1019 # define NOT_FIXED_DEC 31
1020 #endif
1021 							dval = mysql_float_to_double(*(float *)stmt->result.buf[i].val,
1022 										(stmt->stmt->fields[i].decimals >= NOT_FIXED_DEC) ? -1 :
1023 										stmt->stmt->fields[i].decimals);
1024 						} else {
1025 							dval = *((double *)stmt->result.buf[i].val);
1026 						}
1027 
1028 						ZVAL_DOUBLE(result, dval);
1029 						break;
1030 					}
1031 					case IS_STRING:
1032 						if (stmt->stmt->bind[i].buffer_type == MYSQL_TYPE_LONGLONG
1033 #if MYSQL_VERSION_ID > 50002
1034 						 || stmt->stmt->bind[i].buffer_type == MYSQL_TYPE_BIT
1035 #endif
1036 						 ) {
1037 							my_bool uns = (stmt->stmt->fields[i].flags & UNSIGNED_FLAG)? 1:0;
1038 #if MYSQL_VERSION_ID > 50002
1039 							if (stmt->stmt->bind[i].buffer_type == MYSQL_TYPE_BIT) {
1040 								switch (stmt->result.buf[i].output_len) {
1041 									case 8:llval = (my_ulonglong)  bit_uint8korr(stmt->result.buf[i].val);break;
1042 									case 7:llval = (my_ulonglong)  bit_uint7korr(stmt->result.buf[i].val);break;
1043 									case 6:llval = (my_ulonglong)  bit_uint6korr(stmt->result.buf[i].val);break;
1044 									case 5:llval = (my_ulonglong)  bit_uint5korr(stmt->result.buf[i].val);break;
1045 									case 4:llval = (my_ulonglong)  bit_uint4korr(stmt->result.buf[i].val);break;
1046 									case 3:llval = (my_ulonglong)  bit_uint3korr(stmt->result.buf[i].val);break;
1047 									case 2:llval = (my_ulonglong)  bit_uint2korr(stmt->result.buf[i].val);break;
1048 									case 1:llval = (my_ulonglong)  uint1korr(stmt->result.buf[i].val);break;
1049 								}
1050 							} else
1051 #endif
1052 							{
1053 								llval= *(my_ulonglong *) stmt->result.buf[i].val;
1054 							}
1055 #if SIZEOF_ZEND_LONG==8
1056 							if (uns && llval > 9223372036854775807L) {
1057 #elif SIZEOF_ZEND_LONG==4
1058 							if ((uns && llval > L64(2147483647)) ||
1059 								(!uns && (( L64(2147483647) < (my_longlong) llval) ||
1060 								(L64(-2147483648) > (my_longlong) llval))))
1061 							{
1062 #endif
1063 								char tmp[22];
1064 								/* even though lval is declared as unsigned, the value
1065 								 * may be negative. Therefor we cannot use MYSQLI_LLU_SPEC and must
1066 								 * use MYSQLI_LL_SPEC.
1067 								 */
1068 								snprintf(tmp, sizeof(tmp), (stmt->stmt->fields[i].flags & UNSIGNED_FLAG)? MYSQLI_LLU_SPEC : MYSQLI_LL_SPEC, llval);
1069 								ZVAL_STRING(result, tmp);
1070 							} else {
1071 								ZVAL_LONG(result, llval);
1072 							}
1073 						} else {
1074 #if defined(MYSQL_DATA_TRUNCATED) && MYSQL_VERSION_ID > 50002
1075 							if (ret == MYSQL_DATA_TRUNCATED && *(stmt->stmt->bind[i].error) != 0) {
1076 								/* result was truncated */
1077 								ZVAL_STRINGL(result, stmt->result.buf[i].val, stmt->stmt->bind[i].buffer_length);
1078 							} else {
1079 #else
1080 							{
1081 #endif
1082 								ZVAL_STRINGL(result, stmt->result.buf[i].val, stmt->result.buf[i].output_len);
1083 							}
1084 						}
1085 						break;
1086 					default:
1087 						break;
1088 				}
1089 			} else {
1090 				ZVAL_NULL(result);
1091 			}
1092 		}
1093 	} else {
1094 		MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
1095 	}
1096 
1097 	switch (ret) {
1098 		case 0:
1099 #ifdef MYSQL_DATA_TRUNCATED
1100 		/* according to SQL standard truncation (e.g. loss of precision is
1101 		   not an error) - for detecting possible truncation you have to
1102 		   check mysqli_stmt_warning
1103 		*/
1104 		case MYSQL_DATA_TRUNCATED:
1105 #endif
1106 			RETURN_TRUE;
1107 		break;
1108 		case 1:
1109 			RETURN_FALSE;
1110 		break;
1111 		default:
1112 			RETURN_NULL();
1113 		break;
1114 	}
1115 }
1116 /* }}} */
1117 #else
1118 /* {{{ mixed mysqli_stmt_fetch_mysqlnd */
1119 void mysqli_stmt_fetch_mysqlnd(INTERNAL_FUNCTION_PARAMETERS)
1120 {
1121 	MY_STMT		*stmt;
1122 	zval		*mysql_stmt;
1123 	zend_bool	fetched_anything;
1124 
1125 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
1126 		return;
1127 	}
1128 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
1129 
1130 	if (FAIL  == mysqlnd_stmt_fetch(stmt->stmt, &fetched_anything)) {
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_more_results(mysql->mysql)) {
1613 		php_error_docref(NULL, E_STRICT, "There is no next result set. "
1614 						"Please, call mysqli_more_results()/mysqli::more_results() to check "
1615 						"whether to call this function/method");
1616 	}
1617 
1618 	RETURN_BOOL(!mysql_next_result(mysql->mysql));
1619 }
1620 /* }}} */
1621 
1622 #if defined(HAVE_STMT_NEXT_RESULT) && defined(MYSQLI_USE_MYSQLND)
1623 /* {{{ proto bool mysqli_stmt_next_result(object link)
1624    check if there any more query results from a multi query */
1625 PHP_FUNCTION(mysqli_stmt_more_results)
1626 {
1627 	MY_STMT		*stmt;
1628 	zval		*mysql_stmt;
1629 
1630 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
1631 		return;
1632 	}
1633 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
1634 
1635 	RETURN_BOOL(mysqlnd_stmt_more_results(stmt->stmt));
1636 }
1637 /* }}} */
1638 
1639 /* {{{ proto bool mysqli_stmt_next_result(object link)
1640    read next result from multi_query */
1641 PHP_FUNCTION(mysqli_stmt_next_result) {
1642 	MY_STMT		*stmt;
1643 	zval		*mysql_stmt;
1644 
1645 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
1646 		return;
1647 	}
1648 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
1649 
1650 	if (!mysqlnd_stmt_more_results(stmt->stmt)) {
1651 		php_error_docref(NULL, E_STRICT, "There is no next result set. "
1652 						"Please, call mysqli_stmt_more_results()/mysqli_stmt::more_results() to check "
1653 						"whether to call this function/method");
1654 	}
1655 
1656 	RETURN_BOOL(!mysql_stmt_next_result(stmt->stmt));
1657 }
1658 /* }}} */
1659 #endif
1660 
1661 /* {{{ proto int mysqli_num_fields(object result)
1662    Get number of fields in result */
1663 PHP_FUNCTION(mysqli_num_fields)
1664 {
1665 	MYSQL_RES	*result;
1666 	zval		*mysql_result;
1667 
1668 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
1669 		return;
1670 	}
1671 	MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1672 
1673 	RETURN_LONG(mysql_num_fields(result));
1674 }
1675 /* }}} */
1676 
1677 /* {{{ proto mixed mysqli_num_rows(object result)
1678    Get number of rows in result */
1679 PHP_FUNCTION(mysqli_num_rows)
1680 {
1681 	MYSQL_RES	*result;
1682 	zval		*mysql_result;
1683 
1684 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
1685 		return;
1686 	}
1687 	MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1688 
1689 	if (mysqli_result_is_unbuffered_and_not_everything_is_fetched(result)) {
1690 		php_error_docref(NULL, E_WARNING, "Function cannot be used with MYSQL_USE_RESULT");
1691 		RETURN_LONG(0);
1692 	}
1693 
1694 	MYSQLI_RETURN_LONG_INT(mysql_num_rows(result));
1695 }
1696 /* }}} */
1697 
1698 /* {{{ mysqli_options_get_option_zval_type */
1699 static int mysqli_options_get_option_zval_type(int option)
1700 {
1701 	switch (option) {
1702 #ifdef MYSQLI_USE_MYSQLND
1703 		case MYSQLND_OPT_NET_CMD_BUFFER_SIZE:
1704 		case MYSQLND_OPT_NET_READ_BUFFER_SIZE:
1705 #ifdef MYSQLND_STRING_TO_INT_CONVERSION
1706 		case MYSQLND_OPT_INT_AND_FLOAT_NATIVE:
1707 #endif
1708 #endif /* MYSQLI_USE_MYSQLND */
1709 		case MYSQL_OPT_CONNECT_TIMEOUT:
1710 #ifdef MYSQL_REPORT_DATA_TRUNCATION
1711 		case MYSQL_REPORT_DATA_TRUNCATION:
1712 #endif
1713 		case MYSQL_OPT_LOCAL_INFILE:
1714 		case MYSQL_OPT_NAMED_PIPE:
1715 #ifdef MYSQL_OPT_PROTOCOL
1716                 case MYSQL_OPT_PROTOCOL:
1717 #endif /* MySQL 4.1.0 */
1718 		case MYSQL_OPT_READ_TIMEOUT:
1719 		case MYSQL_OPT_WRITE_TIMEOUT:
1720 #ifdef MYSQL_OPT_GUESS_CONNECTION /* removed in MySQL-8.0 */
1721 		case MYSQL_OPT_GUESS_CONNECTION:
1722 		case MYSQL_OPT_USE_EMBEDDED_CONNECTION:
1723 		case MYSQL_OPT_USE_REMOTE_CONNECTION:
1724 		case MYSQL_SECURE_AUTH:
1725 #endif
1726 #ifdef MYSQL_OPT_RECONNECT
1727 		case MYSQL_OPT_RECONNECT:
1728 #endif /* MySQL 5.0.13 */
1729 #ifdef MYSQL_OPT_SSL_VERIFY_SERVER_CERT
1730 		case MYSQL_OPT_SSL_VERIFY_SERVER_CERT:
1731 #endif /* MySQL 5.0.23 */
1732 #ifdef MYSQL_OPT_COMPRESS
1733 		case MYSQL_OPT_COMPRESS:
1734 #endif /* mysqlnd @ PHP 5.3.2 */
1735 #if (MYSQL_VERSION_ID >= 50611 && defined(CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS)) || defined(MYSQLI_USE_MYSQLND)
1736 		case MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS:
1737 #endif
1738 			return IS_LONG;
1739 
1740 #ifdef MYSQL_SHARED_MEMORY_BASE_NAME
1741 		case MYSQL_SHARED_MEMORY_BASE_NAME:
1742 #endif /* MySQL 4.1.0 */
1743 #ifdef MYSQL_SET_CLIENT_IP
1744 		case MYSQL_SET_CLIENT_IP:
1745 #endif /* MySQL 4.1.1 */
1746 		case MYSQL_READ_DEFAULT_FILE:
1747 		case MYSQL_READ_DEFAULT_GROUP:
1748 		case MYSQL_INIT_COMMAND:
1749 		case MYSQL_SET_CHARSET_NAME:
1750 		case MYSQL_SET_CHARSET_DIR:
1751 #if MYSQL_VERSION_ID > 50605 || defined(MYSQLI_USE_MYSQLND)
1752 		case MYSQL_SERVER_PUBLIC_KEY:
1753 #endif
1754 			return IS_STRING;
1755 
1756 		default:
1757 			return IS_NULL;
1758 	}
1759 }
1760 /* }}} */
1761 
1762 /* {{{ proto bool mysqli_options(object link, int flags, mixed values)
1763    Set options */
1764 PHP_FUNCTION(mysqli_options)
1765 {
1766 	MY_MYSQL		*mysql;
1767 	zval			*mysql_link = NULL;
1768 	zval			*mysql_value;
1769 	zend_long			mysql_option;
1770 	unsigned int	l_value;
1771 	zend_long			ret;
1772 	int				expected_type;
1773 
1774 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Olz", &mysql_link, mysqli_link_class_entry, &mysql_option, &mysql_value) == FAILURE) {
1775 		return;
1776 	}
1777 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_INITIALIZED);
1778 
1779 #if !defined(MYSQLI_USE_MYSQLND)
1780 	if (PG(open_basedir) && PG(open_basedir)[0] != '\0') {
1781 		if(mysql_option == MYSQL_OPT_LOCAL_INFILE) {
1782 			RETURN_FALSE;
1783 		}
1784 	}
1785 #endif
1786 	expected_type = mysqli_options_get_option_zval_type(mysql_option);
1787 	if (expected_type != Z_TYPE_P(mysql_value)) {
1788 		switch (expected_type) {
1789 			case IS_STRING:
1790 				convert_to_string_ex(mysql_value);
1791 				break;
1792 			case IS_LONG:
1793 				convert_to_long_ex(mysql_value);
1794 				break;
1795 			default:
1796 				break;
1797 		}
1798 	}
1799 	switch (expected_type) {
1800 		case IS_STRING:
1801 			ret = mysql_options(mysql->mysql, mysql_option, Z_STRVAL_P(mysql_value));
1802 			break;
1803 		case IS_LONG:
1804 			l_value = Z_LVAL_P(mysql_value);
1805 			ret = mysql_options(mysql->mysql, mysql_option, (char *)&l_value);
1806 			break;
1807 		default:
1808 			ret = 1;
1809 			break;
1810 	}
1811 
1812 	RETURN_BOOL(!ret);
1813 }
1814 /* }}} */
1815 
1816 /* {{{ proto bool mysqli_ping(object link)
1817    Ping a server connection or reconnect if there is no connection */
1818 PHP_FUNCTION(mysqli_ping)
1819 {
1820 	MY_MYSQL	*mysql;
1821 	zval		*mysql_link;
1822 	zend_long		rc;
1823 
1824 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1825 		return;
1826 	}
1827 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1828 	rc = mysql_ping(mysql->mysql);
1829 	MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
1830 
1831 	RETURN_BOOL(!rc);
1832 }
1833 /* }}} */
1834 
1835 /* {{{ proto mixed mysqli_prepare(object link, string query)
1836    Prepare a SQL statement for execution */
1837 PHP_FUNCTION(mysqli_prepare)
1838 {
1839 	MY_MYSQL		*mysql;
1840 	MY_STMT			*stmt;
1841 	char			*query = NULL;
1842 	size_t				query_len;
1843 	zval			*mysql_link;
1844 	MYSQLI_RESOURCE	*mysqli_resource;
1845 
1846 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os",&mysql_link, mysqli_link_class_entry, &query, &query_len) == FAILURE) {
1847 		return;
1848 	}
1849 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1850 
1851 #if !defined(MYSQLI_USE_MYSQLND)
1852 	if (mysql->mysql->status == MYSQL_STATUS_GET_RESULT) {
1853 		php_error_docref(NULL, E_WARNING, "All data must be fetched before a new statement prepare takes place");
1854 		RETURN_FALSE;
1855 	}
1856 #endif
1857 
1858 	stmt = (MY_STMT *)ecalloc(1,sizeof(MY_STMT));
1859 
1860 	if ((stmt->stmt = mysql_stmt_init(mysql->mysql))) {
1861 		if (mysql_stmt_prepare(stmt->stmt, query, query_len)) {
1862 			/* mysql_stmt_close() clears errors, so we have to store them temporarily */
1863 #if !defined(MYSQLI_USE_MYSQLND)
1864 			char  last_error[MYSQL_ERRMSG_SIZE];
1865 			char  sqlstate[SQLSTATE_LENGTH+1];
1866 			unsigned int last_errno;
1867 
1868 			last_errno = stmt->stmt->last_errno;
1869 			memcpy(last_error, stmt->stmt->last_error, MYSQL_ERRMSG_SIZE);
1870 			memcpy(sqlstate, mysql->mysql->net.sqlstate, SQLSTATE_LENGTH+1);
1871 #else
1872 			MYSQLND_ERROR_INFO error_info = *mysql->mysql->data->error_info;
1873 			mysql->mysql->data->error_info->error_list.head = NULL;
1874 			mysql->mysql->data->error_info->error_list.tail = NULL;
1875 			mysql->mysql->data->error_info->error_list.count = 0;
1876 #endif
1877 			mysqli_stmt_close(stmt->stmt, FALSE);
1878 			stmt->stmt = NULL;
1879 
1880 			/* restore error messages */
1881 #if !defined(MYSQLI_USE_MYSQLND)
1882 			mysql->mysql->net.last_errno = last_errno;
1883 			memcpy(mysql->mysql->net.last_error, last_error, MYSQL_ERRMSG_SIZE);
1884 			memcpy(mysql->mysql->net.sqlstate, sqlstate, SQLSTATE_LENGTH+1);
1885 #else
1886 			zend_llist_clean(&mysql->mysql->data->error_info->error_list);
1887 			*mysql->mysql->data->error_info = error_info;
1888 #endif
1889 		}
1890 	}
1891 
1892 	/* don't initialize stmt->query with NULL, we ecalloc()-ed the memory */
1893 	/* Get performance boost if reporting is switched off */
1894 	if (stmt->stmt && query_len && (MyG(report_mode) & MYSQLI_REPORT_INDEX)) {
1895 		stmt->query = (char *)emalloc(query_len + 1);
1896 		memcpy(stmt->query, query, query_len);
1897 		stmt->query[query_len] = '\0';
1898 	}
1899 
1900 	/* don't join to the previous if because it won't work if mysql_stmt_prepare_fails */
1901 	if (!stmt->stmt) {
1902 		MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
1903 		efree(stmt);
1904 		RETURN_FALSE;
1905 	}
1906 #ifndef MYSQLI_USE_MYSQLND
1907 	ZVAL_COPY(&stmt->link_handle, mysql_link);
1908 #endif
1909 
1910 	mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
1911 	mysqli_resource->ptr = (void *)stmt;
1912 
1913 	/* change status */
1914 	mysqli_resource->status = MYSQLI_STATUS_VALID;
1915 	MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_stmt_class_entry);
1916 }
1917 /* }}} */
1918 
1919 /* {{{ proto bool mysqli_real_connect(object link [,string hostname [,string username [,string passwd [,string dbname [,int port [,string socket [,int flags]]]]]]])
1920    Open a connection to a mysql server */
1921 PHP_FUNCTION(mysqli_real_connect)
1922 {
1923 	mysqli_common_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, TRUE, FALSE);
1924 }
1925 /* }}} */
1926 
1927 /* {{{ proto bool mysqli_real_query(object link, string query)
1928    Binary-safe version of mysql_query() */
1929 PHP_FUNCTION(mysqli_real_query)
1930 {
1931 	MY_MYSQL	*mysql;
1932 	zval		*mysql_link;
1933 	char		*query = NULL;
1934 	size_t		query_len;
1935 
1936 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &mysql_link, mysqli_link_class_entry, &query, &query_len) == FAILURE) {
1937 		return;
1938 	}
1939 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1940 
1941 	MYSQLI_DISABLE_MQ; /* disable multi statements/queries */
1942 
1943 	if (mysql_real_query(mysql->mysql, query, query_len)) {
1944 		MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
1945 		RETURN_FALSE;
1946 	}
1947 
1948 	if (!mysql_field_count(mysql->mysql)) {
1949 		if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
1950 			php_mysqli_report_index(query, mysqli_server_status(mysql->mysql));
1951 		}
1952 	}
1953 
1954 	RETURN_TRUE;
1955 }
1956 /* }}} */
1957 
1958 #if defined(MYSQLI_USE_MYSQLND) || MYSQL_VERSION_ID < 50707 || defined(MARIADB_BASE_VERSION)
1959 # define mysql_real_escape_string_quote(mysql, to, from, length, quote) \
1960 	mysql_real_escape_string(mysql, to, from, length)
1961 #endif
1962 
1963 /* {{{ proto string mysqli_real_escape_string(object link, string escapestr)
1964    Escapes special characters in a string for use in a SQL statement, taking into account the current charset of the connection */
1965 PHP_FUNCTION(mysqli_real_escape_string) {
1966 	MY_MYSQL	*mysql;
1967 	zval		*mysql_link = NULL;
1968 	char		*escapestr;
1969 	size_t			escapestr_len;
1970 	zend_string *newstr;
1971 
1972 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &mysql_link, mysqli_link_class_entry, &escapestr, &escapestr_len) == FAILURE) {
1973 		return;
1974 	}
1975 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1976 
1977 	newstr = zend_string_alloc(2 * escapestr_len, 0);
1978 	ZSTR_LEN(newstr) = mysql_real_escape_string_quote(mysql->mysql, ZSTR_VAL(newstr), escapestr, escapestr_len, '\'');
1979 	newstr = zend_string_truncate(newstr, ZSTR_LEN(newstr), 0);
1980 
1981 	RETURN_NEW_STR(newstr);
1982 }
1983 /* }}} */
1984 
1985 /* {{{ proto bool mysqli_rollback(object link)
1986    Undo actions from current transaction */
1987 PHP_FUNCTION(mysqli_rollback)
1988 {
1989 	MY_MYSQL	*mysql;
1990 	zval		*mysql_link;
1991 	zend_long		flags = TRANS_COR_NO_OPT;
1992 	char *		name = NULL;
1993 	size_t			name_len = 0;
1994 
1995 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|ls", &mysql_link, mysqli_link_class_entry, &flags, &name, &name_len) == FAILURE) {
1996 		return;
1997 	}
1998 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1999 
2000 #if !defined(MYSQLI_USE_MYSQLND)
2001 	if (mysqli_commit_or_rollback_libmysql(mysql->mysql, FALSE, flags, name)) {
2002 #else
2003 	if (FAIL == mysqlnd_rollback(mysql->mysql, flags, name)) {
2004 #endif
2005 		RETURN_FALSE;
2006 	}
2007 	RETURN_TRUE;
2008 }
2009 /* }}} */
2010 
2011 /* {{{ proto bool mysqli_stmt_send_long_data(object stmt, int param_nr, string data)
2012 */
2013 PHP_FUNCTION(mysqli_stmt_send_long_data)
2014 {
2015 	MY_STMT *stmt;
2016 	zval	*mysql_stmt;
2017 	char	*data;
2018 	zend_long	param_nr;
2019 	size_t		data_len;
2020 
2021 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ols", &mysql_stmt, mysqli_stmt_class_entry, &param_nr, &data, &data_len) == FAILURE) {
2022 		return;
2023 	}
2024 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2025 
2026 	if (param_nr < 0) {
2027 		php_error_docref(NULL, E_WARNING, "Invalid parameter number");
2028 		RETURN_FALSE;
2029 	}
2030 	if (mysql_stmt_send_long_data(stmt->stmt, param_nr, data, data_len)) {
2031 		RETURN_FALSE;
2032 	}
2033 	RETURN_TRUE;
2034 }
2035 /* }}} */
2036 
2037 /* {{{ proto string|int|false mysqli_stmt_affected_rows(object stmt)
2038    Return the number of rows affected in the last query for the given link. */
2039 PHP_FUNCTION(mysqli_stmt_affected_rows)
2040 {
2041 	MY_STMT			*stmt;
2042 	zval			*mysql_stmt;
2043 	my_ulonglong	rc;
2044 
2045 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2046 		return;
2047 	}
2048 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2049 
2050 	rc = mysql_stmt_affected_rows(stmt->stmt);
2051 	if (rc == (my_ulonglong) -1) {
2052 		RETURN_LONG(-1);
2053 	}
2054 	MYSQLI_RETURN_LONG_INT(rc)
2055 }
2056 /* }}} */
2057 
2058 /* {{{ proto bool mysqli_stmt_close(object stmt)
2059    Close statement */
2060 PHP_FUNCTION(mysqli_stmt_close)
2061 {
2062 	MY_STMT		*stmt;
2063 	zval		*mysql_stmt;
2064 
2065 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2066 		return;
2067 	}
2068 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2069 
2070 	mysqli_stmt_close(stmt->stmt, FALSE);
2071 	stmt->stmt = NULL;
2072 	php_clear_stmt_bind(stmt);
2073 	MYSQLI_CLEAR_RESOURCE(mysql_stmt);
2074 	RETURN_TRUE;
2075 }
2076 /* }}} */
2077 
2078 /* {{{ proto void mysqli_stmt_data_seek(object stmt, int offset)
2079    Move internal result pointer */
2080 PHP_FUNCTION(mysqli_stmt_data_seek)
2081 {
2082 	MY_STMT		*stmt;
2083 	zval		*mysql_stmt;
2084 	zend_long		offset;
2085 
2086 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &mysql_stmt, mysqli_stmt_class_entry, &offset) == FAILURE) {
2087 		return;
2088 	}
2089 	if (offset < 0) {
2090 		php_error_docref(NULL, E_WARNING, "Offset must be positive");
2091 		RETURN_FALSE;
2092 	}
2093 
2094 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2095 
2096 	mysql_stmt_data_seek(stmt->stmt, offset);
2097 }
2098 /* }}} */
2099 
2100 /* {{{ proto int mysqli_stmt_field_count(object stmt) {
2101    Return the number of result columns for the given statement */
2102 PHP_FUNCTION(mysqli_stmt_field_count)
2103 {
2104 	MY_STMT		*stmt;
2105 	zval		*mysql_stmt;
2106 
2107 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2108 		return;
2109 	}
2110 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2111 
2112 	RETURN_LONG(mysql_stmt_field_count(stmt->stmt));
2113 }
2114 /* }}} */
2115 
2116 /* {{{ proto void mysqli_stmt_free_result(object stmt)
2117    Free stored result memory for the given statement handle */
2118 PHP_FUNCTION(mysqli_stmt_free_result)
2119 {
2120 	MY_STMT		*stmt;
2121 	zval		*mysql_stmt;
2122 
2123 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2124 		return;
2125 	}
2126 
2127 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2128 
2129 	mysql_stmt_free_result(stmt->stmt);
2130 }
2131 /* }}} */
2132 
2133 /* {{{ proto mixed mysqli_stmt_insert_id(object stmt)
2134    Get the ID generated from the previous INSERT operation */
2135 PHP_FUNCTION(mysqli_stmt_insert_id)
2136 {
2137 	MY_STMT			*stmt;
2138 	my_ulonglong	rc;
2139 	zval			*mysql_stmt;
2140 
2141 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2142 		return;
2143 	}
2144 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2145 	rc = mysql_stmt_insert_id(stmt->stmt);
2146 	MYSQLI_RETURN_LONG_INT(rc)
2147 }
2148 /* }}} */
2149 
2150 /* {{{ proto int mysqli_stmt_param_count(object stmt)
2151    Return the number of parameter for the given statement */
2152 PHP_FUNCTION(mysqli_stmt_param_count)
2153 {
2154 	MY_STMT		*stmt;
2155 	zval		*mysql_stmt;
2156 
2157 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2158 		return;
2159 	}
2160 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2161 
2162 	RETURN_LONG(mysql_stmt_param_count(stmt->stmt));
2163 }
2164 /* }}} */
2165 
2166 /* {{{ proto bool mysqli_stmt_reset(object stmt)
2167    reset a prepared statement */
2168 PHP_FUNCTION(mysqli_stmt_reset)
2169 {
2170 	MY_STMT		*stmt;
2171 	zval		*mysql_stmt;
2172 
2173 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2174 		return;
2175 	}
2176 
2177 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2178 
2179 	if (mysql_stmt_reset(stmt->stmt)) {
2180 		RETURN_FALSE;
2181 	}
2182 	RETURN_TRUE;
2183 }
2184 /* }}} */
2185 
2186 /* {{{ proto mixed mysqli_stmt_num_rows(object stmt)
2187    Return the number of rows in statements result set */
2188 PHP_FUNCTION(mysqli_stmt_num_rows)
2189 {
2190 	MY_STMT			*stmt;
2191 	zval			*mysql_stmt;
2192 	my_ulonglong	rc;
2193 
2194 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2195 		return;
2196 	}
2197 
2198 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2199 
2200 	rc = mysql_stmt_num_rows(stmt->stmt);
2201 	MYSQLI_RETURN_LONG_INT(rc)
2202 }
2203 /* }}} */
2204 
2205 /* {{{ proto bool mysqli_select_db(object link, string dbname)
2206    Select a MySQL database */
2207 PHP_FUNCTION(mysqli_select_db)
2208 {
2209 	MY_MYSQL	*mysql;
2210 	zval		*mysql_link;
2211 	char		*dbname;
2212 	size_t			dbname_len;
2213 
2214 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &mysql_link, mysqli_link_class_entry, &dbname, &dbname_len) == FAILURE) {
2215 		return;
2216 	}
2217 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
2218 
2219 	if (mysql_select_db(mysql->mysql, dbname)) {
2220 		MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
2221 		RETURN_FALSE;
2222 	}
2223 	RETURN_TRUE;
2224 }
2225 /* }}} */
2226 
2227 /* {{{ proto string mysqli_sqlstate(object link)
2228    Returns the SQLSTATE error from previous MySQL operation */
2229 PHP_FUNCTION(mysqli_sqlstate)
2230 {
2231 	MY_MYSQL	*mysql;
2232 	zval		*mysql_link;
2233 	const char	*state;
2234 
2235 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
2236 		return;
2237 	}
2238 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
2239 	state = mysql_sqlstate(mysql->mysql);
2240 	if (state) {
2241 		RETURN_STRING(state);
2242 	}
2243 }
2244 /* }}} */
2245 
2246 /* {{{ proto bool mysqli_ssl_set(object link ,string key ,string cert ,string ca ,string capath ,string cipher])
2247 */
2248 PHP_FUNCTION(mysqli_ssl_set)
2249 {
2250 	MY_MYSQL	*mysql;
2251 	zval		*mysql_link;
2252 	char		*ssl_parm[5];
2253 	size_t			ssl_parm_len[5], i;
2254 
2255 	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) {
2256 		return;
2257 	}
2258 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_INITIALIZED);
2259 
2260 	for (i = 0; i < 5; i++) {
2261 		if (!ssl_parm_len[i]) {
2262 			ssl_parm[i] = NULL;
2263 		}
2264 	}
2265 
2266 	mysql_ssl_set(mysql->mysql, ssl_parm[0], ssl_parm[1], ssl_parm[2], ssl_parm[3], ssl_parm[4]);
2267 
2268 	RETURN_TRUE;
2269 }
2270 /* }}} */
2271 
2272 /* {{{ proto mixed mysqli_stat(object link)
2273    Get current system status */
2274 PHP_FUNCTION(mysqli_stat)
2275 {
2276 	MY_MYSQL	*mysql;
2277 	zval		*mysql_link;
2278 #if defined(MYSQLI_USE_MYSQLND)
2279 	zend_string *stat;
2280 #else
2281 	char		*stat;
2282 #endif
2283 
2284 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
2285 		return;
2286 	}
2287 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
2288 
2289 #if !defined(MYSQLI_USE_MYSQLND)
2290 	if ((stat = (char *)mysql_stat(mysql->mysql)))
2291 	{
2292 		RETURN_STRING(stat);
2293 #else
2294 	if (mysqlnd_stat(mysql->mysql, &stat) == PASS)
2295 	{
2296 		RETURN_STR(stat);
2297 #endif
2298 	} else {
2299 		RETURN_FALSE;
2300 	}
2301 }
2302 
2303 /* }}} */
2304 
2305 /* {{{ proto bool mysqli_refresh(object link, int options)
2306    Flush tables or caches, or reset replication server information */
2307 PHP_FUNCTION(mysqli_refresh)
2308 {
2309 	MY_MYSQL *mysql;
2310 	zval *mysql_link = NULL;
2311 	zend_long options;
2312 
2313 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &mysql_link, mysqli_link_class_entry, &options) == FAILURE) {
2314 		return;
2315 	}
2316 	MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_INITIALIZED);
2317 #ifdef MYSQLI_USE_MYSQLND
2318 	RETURN_BOOL(!mysql_refresh(mysql->mysql, (uint8_t) options));
2319 #else
2320 	RETURN_BOOL(!mysql_refresh(mysql->mysql, options));
2321 #endif
2322 }
2323 /* }}} */
2324 
2325 /* {{{ proto int mysqli_stmt_attr_set(object stmt, int attr, int mode)
2326 */
2327 PHP_FUNCTION(mysqli_stmt_attr_set)
2328 {
2329 	MY_STMT	*stmt;
2330 	zval	*mysql_stmt;
2331 	zend_long	mode_in;
2332 #if MYSQL_VERSION_ID >= 50107
2333 	my_bool	mode_b;
2334 #endif
2335 	unsigned long	mode;
2336 	zend_long	attr;
2337 	void	*mode_p;
2338 
2339 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Oll", &mysql_stmt, mysqli_stmt_class_entry, &attr, &mode_in) == FAILURE) {
2340 		return;
2341 	}
2342 	MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
2343 
2344 	if (mode_in < 0) {
2345 		php_error_docref(NULL, E_WARNING, "mode should be non-negative, " ZEND_LONG_FMT " passed", mode_in);
2346 		RETURN_FALSE;
2347 	}
2348 
2349 	switch (attr) {
2350 #if MYSQL_VERSION_ID >= 50107
2351 	case STMT_ATTR_UPDATE_MAX_LENGTH:
2352 		mode_b = (my_bool) mode_in;
2353 		mode_p = &mode_b;
2354 		break;
2355 #endif
2356 	default:
2357 		mode = mode_in;
2358 		mode_p = &mode;
2359 		break;
2360 	}
2361 #if !defined(MYSQLI_USE_MYSQLND)
2362 	if (mysql_stmt_attr_set(stmt->stmt, attr, mode_p)) {
2363 #else
2364 	if (FAIL == mysql_stmt_attr_set(stmt->stmt, attr, mode_p)) {
2365 #endif
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 
2691 /*
2692  * Local variables:
2693  * tab-width: 4
2694  * c-basic-offset: 4
2695  * End:
2696  * vim600: noet sw=4 ts=4 fdm=marker
2697  * vim<600: noet sw=4 ts=4
2698  */
2699