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