xref: /PHP-5.5/ext/mysqli/mysqli_api.c (revision 1933b556)
1 /*
2   +----------------------------------------------------------------------+
3   | PHP Version 5                                                        |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 1997-2015 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 /* {{{ proto bool 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 				zend_ptr_stack_push(&plist->free_links, mysql->mysql);
719 
720 				MyG(num_active_persistent)--;
721 				MyG(num_inactive_persistent)++;
722 			}
723 		}
724 		mysql->persistent = FALSE;
725 	}
726 	mysql->mysql = NULL;
727 
728 	php_clear_mysql(mysql);
729 }
730 /* }}} */
731 
732 
733 /* {{{ proto bool mysqli_close(object link)
734    Close connection */
PHP_FUNCTION(mysqli_close)735 PHP_FUNCTION(mysqli_close)
736 {
737 	zval		*mysql_link;
738 	MY_MYSQL	*mysql;
739 
740 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
741 		return;
742 	}
743 
744 	MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_INITIALIZED);
745 
746 	php_mysqli_close(mysql, MYSQLI_CLOSE_EXPLICIT, ((MYSQLI_RESOURCE *)((mysqli_object *)zend_object_store_get_object(mysql_link TSRMLS_CC))->ptr)->status TSRMLS_CC);
747 	((MYSQLI_RESOURCE *)((mysqli_object *)zend_object_store_get_object(mysql_link TSRMLS_CC))->ptr)->status = MYSQLI_STATUS_UNKNOWN;
748 
749 	MYSQLI_CLEAR_RESOURCE(&mysql_link);
750 	efree(mysql);
751 	RETURN_TRUE;
752 }
753 /* }}} */
754 
755 
756 
757 
758 /* {{{ proto bool mysqli_commit(object link[, int flags [, string name ]])
759    Commit outstanding actions and close transaction */
PHP_FUNCTION(mysqli_commit)760 PHP_FUNCTION(mysqli_commit)
761 {
762 	MY_MYSQL	*mysql;
763 	zval		*mysql_link;
764 	long		flags = TRANS_COR_NO_OPT;
765 	char *		name = NULL;
766 	int			name_len = 0;
767 
768 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O|ls", &mysql_link, mysqli_link_class_entry, &flags, &name, &name_len) == FAILURE) {
769 		return;
770 	}
771 	MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
772 
773 #if !defined(MYSQLI_USE_MYSQLND)
774 	if (mysqli_commit_or_rollback_libmysql(mysql->mysql, TRUE, flags, name TSRMLS_CC)) {
775 #else
776 	if (FAIL == mysqlnd_commit(mysql->mysql, flags, name)) {
777 #endif
778 		RETURN_FALSE;
779 	}
780 	RETURN_TRUE;
781 }
782 /* }}} */
783 
784 /* {{{ proto bool mysqli_data_seek(object result, int offset)
785    Move internal result pointer */
786 PHP_FUNCTION(mysqli_data_seek)
787 {
788 	MYSQL_RES	*result;
789 	zval		*mysql_result;
790 	long		offset;
791 
792 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol", &mysql_result, mysqli_result_class_entry, &offset) == FAILURE) {
793 		return;
794 	}
795 
796 	MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, &mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
797 
798 	if (mysqli_result_is_unbuffered(result)) {
799 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Function cannot be used with MYSQL_USE_RESULT");
800 		RETURN_FALSE;
801 	}
802 
803 	if (offset < 0 || offset >= mysql_num_rows(result)) {
804 		RETURN_FALSE;
805 	}
806 
807 	mysql_data_seek(result, offset);
808 	RETURN_TRUE;
809 }
810 /* }}} */
811 
812 /* {{{ proto void mysqli_debug(string debug) U
813 */
814 PHP_FUNCTION(mysqli_debug)
815 {
816 	char	*debug;
817 	int		debug_len;
818 
819 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &debug, &debug_len) == FAILURE) {
820 		return;
821 	}
822 
823 	mysql_debug(debug);
824 	RETURN_TRUE;
825 }
826 /* }}} */
827 
828 
829 /* {{{ proto bool mysqli_dump_debug_info(object link)
830 */
831 PHP_FUNCTION(mysqli_dump_debug_info)
832 {
833 	MY_MYSQL	*mysql;
834 	zval		*mysql_link;
835 
836 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
837 		return;
838 	}
839 	MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
840 
841 	RETURN_BOOL(!mysql_dump_debug_info(mysql->mysql))
842 }
843 /* }}} */
844 
845 /* {{{ proto int mysqli_errno(object link)
846    Returns the numerical value of the error message from previous MySQL operation */
847 PHP_FUNCTION(mysqli_errno)
848 {
849 	MY_MYSQL	*mysql;
850 	zval		*mysql_link;
851 
852 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
853 		return;
854 	}
855 	MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
856 	RETURN_LONG(mysql_errno(mysql->mysql));
857 }
858 /* }}} */
859 
860 /* {{{ proto string mysqli_error(object link)
861    Returns the text of the error message from previous MySQL operation */
862 PHP_FUNCTION(mysqli_error)
863 {
864 	MY_MYSQL	*mysql;
865 	zval		*mysql_link;
866 	const char	*err;
867 
868 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
869 		return;
870 	}
871 	MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
872 	err = mysql_error(mysql->mysql);
873 	if (err) {
874 		RETURN_STRING(err, 1);
875 	}
876 }
877 /* }}} */
878 
879 #ifndef MYSQLI_USE_MYSQLND
880 /* {{{ php_mysqli_stmt_copy_it */
881 static void
882 php_mysqli_stmt_copy_it(zval *** copies, zval *original, uint param_count, uint current)
883 {
884 	if (!*copies) {
885 		*copies = ecalloc(param_count, sizeof(zval *));
886 	}
887 	MAKE_STD_ZVAL((*copies)[current]);
888 	*(*copies)[current] = *original;
889 	Z_SET_REFCOUNT_P((*copies)[current], 1);
890 	zval_copy_ctor((*copies)[current]);
891 }
892 /* }}} */
893 #endif
894 
895 /* {{{ proto bool mysqli_stmt_execute(object stmt)
896    Execute a prepared statement */
897 PHP_FUNCTION(mysqli_stmt_execute)
898 {
899 	MY_STMT		*stmt;
900 	zval		*mysql_stmt;
901 #ifndef MYSQLI_USE_MYSQLND
902 	unsigned int	i;
903 	zval		**copies = NULL;
904 #endif
905 
906 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
907 		return;
908 	}
909 	MYSQLI_FETCH_RESOURCE_STMT(stmt, &mysql_stmt, MYSQLI_STATUS_VALID);
910 
911 #ifndef MYSQLI_USE_MYSQLND
912 	if (stmt->param.var_cnt) {
913 		int j;
914 		for (i = 0; i < stmt->param.var_cnt; i++) {
915 			for (j = i + 1; j < stmt->param.var_cnt; j++) {
916 				/* Oops, someone binding the same variable - clone */
917 				if (stmt->param.vars[j] == stmt->param.vars[i] && stmt->param.vars[i]) {
918 					php_mysqli_stmt_copy_it(&copies, stmt->param.vars[i], stmt->param.var_cnt, i);
919 					break;
920 				}
921 			}
922 		}
923 	}
924 	for (i = 0; i < stmt->param.var_cnt; i++) {
925 		if (stmt->param.vars[i]) {
926 			if ( !(stmt->param.is_null[i] = (stmt->param.vars[i]->type == IS_NULL)) ) {
927 				zval *the_var = copies && copies[i]? copies[i]:stmt->param.vars[i];
928 				switch (stmt->stmt->params[i].buffer_type) {
929 					case MYSQL_TYPE_VAR_STRING:
930 						if (the_var == stmt->param.vars[i] && Z_TYPE_P(stmt->param.vars[i]) != IS_STRING) {
931 							php_mysqli_stmt_copy_it(&copies, stmt->param.vars[i], stmt->param.var_cnt, i);
932 							the_var = copies[i];
933 						}
934 						convert_to_string_ex(&the_var);
935 						stmt->stmt->params[i].buffer = Z_STRVAL_P(the_var);
936 						stmt->stmt->params[i].buffer_length = Z_STRLEN_P(the_var);
937 						break;
938 					case MYSQL_TYPE_DOUBLE:
939 						if (the_var == stmt->param.vars[i] && Z_TYPE_P(stmt->param.vars[i]) != IS_DOUBLE) {
940 							php_mysqli_stmt_copy_it(&copies, stmt->param.vars[i], stmt->param.var_cnt, i);
941 							the_var = copies[i];
942 						}
943 						convert_to_double_ex(&the_var);
944 						stmt->stmt->params[i].buffer = &Z_DVAL_P(the_var);
945 						break;
946 					case MYSQL_TYPE_LONGLONG:
947 					case MYSQL_TYPE_LONG:
948 						if (the_var == stmt->param.vars[i] && Z_TYPE_P(stmt->param.vars[i]) != IS_LONG) {
949 							php_mysqli_stmt_copy_it(&copies, stmt->param.vars[i], stmt->param.var_cnt, i);
950 							the_var = copies[i];
951 						}
952 						convert_to_long_ex(&the_var);
953 						stmt->stmt->params[i].buffer = &Z_LVAL_P(the_var);
954 						break;
955 					default:
956 						break;
957 				}
958 			}
959 		}
960 	}
961 #endif
962 
963 	if (mysql_stmt_execute(stmt->stmt)) {
964 		MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
965 		RETVAL_FALSE;
966 	} else {
967 		RETVAL_TRUE;
968 	}
969 
970 #ifndef MYSQLI_USE_MYSQLND
971 	if (copies) {
972 		for (i = 0; i < stmt->param.var_cnt; i++) {
973 			if (copies[i]) {
974 				zval_ptr_dtor(&copies[i]);
975 			}
976 		}
977 		efree(copies);
978 	}
979 #endif
980 
981 	if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
982 		php_mysqli_report_index(stmt->query, mysqli_stmt_server_status(stmt->stmt) TSRMLS_CC);
983 	}
984 }
985 /* }}} */
986 
987 #ifndef MYSQLI_USE_MYSQLND
988 /* {{{ void mysqli_stmt_fetch_libmysql
989    Fetch results from a prepared statement into the bound variables */
990 void mysqli_stmt_fetch_libmysql(INTERNAL_FUNCTION_PARAMETERS)
991 {
992 	MY_STMT		*stmt;
993 	zval			*mysql_stmt;
994 	unsigned int	i;
995 	ulong			ret;
996 	unsigned int	uval;
997 	my_ulonglong	llval;
998 
999 
1000 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
1001 		return;
1002 	}
1003 	MYSQLI_FETCH_RESOURCE_STMT(stmt, &mysql_stmt, MYSQLI_STATUS_VALID);
1004 
1005 	/* reset buffers */
1006 	for (i = 0; i < stmt->result.var_cnt; i++) {
1007 		if (stmt->result.buf[i].type == IS_STRING) {
1008 			memset(stmt->result.buf[i].val, 0, stmt->result.buf[i].buflen);
1009 		}
1010 	}
1011 	ret = mysql_stmt_fetch(stmt->stmt);
1012 #ifdef MYSQL_DATA_TRUNCATED
1013 	if (!ret || ret == MYSQL_DATA_TRUNCATED) {
1014 #else
1015 	if (!ret) {
1016 #endif
1017 		for (i = 0; i < stmt->result.var_cnt; i++) {
1018 			/*
1019 			  QQ: Isn't it quite better to call zval_dtor(). What if the user has
1020 			  assigned a resource, or an array to the bound variable? We are going
1021 			  to leak probably. zval_dtor() will handle also Unicode/Non-unicode mode.
1022 			*/
1023 			/* Even if the string is of length zero there is one byte alloced so efree() in all cases */
1024 			if (Z_TYPE_P(stmt->result.vars[i]) == IS_STRING) {
1025 				STR_FREE(stmt->result.vars[i]->value.str.val);
1026 			}
1027 			if (!stmt->result.is_null[i]) {
1028 				switch (stmt->result.buf[i].type) {
1029 					case IS_LONG:
1030 						if ((stmt->stmt->fields[i].type == MYSQL_TYPE_LONG)
1031 						    && (stmt->stmt->fields[i].flags & UNSIGNED_FLAG))
1032 						{
1033 							/* unsigned int (11) */
1034 							uval= *(unsigned int *) stmt->result.buf[i].val;
1035 #if SIZEOF_LONG==4
1036 							if (uval > INT_MAX) {
1037 								char *tmp, *p;
1038 								int j=10;
1039 								tmp= emalloc(11);
1040 								p= &tmp[9];
1041 								do {
1042 									*p-- = (uval % 10) + 48;
1043 									uval = uval / 10;
1044 								} while (--j > 0);
1045 								tmp[10]= '\0';
1046 								/* unsigned int > INT_MAX is 10 digits - ALWAYS */
1047 								ZVAL_STRINGL(stmt->result.vars[i], tmp, 10, 0);
1048 								break;
1049 							}
1050 #endif
1051 						}
1052 						if (stmt->stmt->fields[i].flags & UNSIGNED_FLAG) {
1053 							ZVAL_LONG(stmt->result.vars[i], *(unsigned int *)stmt->result.buf[i].val);
1054 						} else {
1055 							ZVAL_LONG(stmt->result.vars[i], *(int *)stmt->result.buf[i].val);
1056 						}
1057 						break;
1058 					case IS_DOUBLE:
1059 					{
1060 						double dval;
1061 						if (stmt->stmt->bind[i].buffer_type == MYSQL_TYPE_FLOAT) {
1062 #ifndef NOT_FIXED_DEC
1063 # define NOT_FIXED_DEC 31
1064 #endif
1065 							dval = mysql_float_to_double(*(float *)stmt->result.buf[i].val,
1066 										(stmt->stmt->fields[i].decimals >= NOT_FIXED_DEC) ? -1 :
1067 										stmt->stmt->fields[i].decimals);
1068 						} else {
1069 							dval = *((double *)stmt->result.buf[i].val);
1070 						}
1071 
1072 						ZVAL_DOUBLE(stmt->result.vars[i], dval);
1073 						break;
1074 					}
1075 					case IS_STRING:
1076 						if (stmt->stmt->bind[i].buffer_type == MYSQL_TYPE_LONGLONG
1077 #if MYSQL_VERSION_ID > 50002
1078 						 || stmt->stmt->bind[i].buffer_type == MYSQL_TYPE_BIT
1079 #endif
1080 						 ) {
1081 							my_bool uns= (stmt->stmt->fields[i].flags & UNSIGNED_FLAG)? 1:0;
1082 #if MYSQL_VERSION_ID > 50002
1083 							if (stmt->stmt->bind[i].buffer_type == MYSQL_TYPE_BIT) {
1084 								switch (stmt->result.buf[i].output_len) {
1085 									case 8:llval = (my_ulonglong)  bit_uint8korr(stmt->result.buf[i].val);break;
1086 									case 7:llval = (my_ulonglong)  bit_uint7korr(stmt->result.buf[i].val);break;
1087 									case 6:llval = (my_ulonglong)  bit_uint6korr(stmt->result.buf[i].val);break;
1088 									case 5:llval = (my_ulonglong)  bit_uint5korr(stmt->result.buf[i].val);break;
1089 									case 4:llval = (my_ulonglong)  bit_uint4korr(stmt->result.buf[i].val);break;
1090 									case 3:llval = (my_ulonglong)  bit_uint3korr(stmt->result.buf[i].val);break;
1091 									case 2:llval = (my_ulonglong)  bit_uint2korr(stmt->result.buf[i].val);break;
1092 									case 1:llval = (my_ulonglong)  uint1korr(stmt->result.buf[i].val);break;
1093 								}
1094 							} else
1095 #endif
1096 							{
1097 								llval= *(my_ulonglong *) stmt->result.buf[i].val;
1098 							}
1099 #if SIZEOF_LONG==8
1100 							if (uns && llval > 9223372036854775807L) {
1101 #elif SIZEOF_LONG==4
1102 							if ((uns && llval > L64(2147483647)) ||
1103 								(!uns && (( L64(2147483647) < (my_longlong) llval) ||
1104 								(L64(-2147483648) > (my_longlong) llval))))
1105 							{
1106 #endif
1107 								char tmp[22];
1108 								/* even though lval is declared as unsigned, the value
1109 								 * may be negative. Therefor we cannot use MYSQLI_LLU_SPEC and must
1110 								 * use MYSQLI_LL_SPEC.
1111 								 */
1112 								snprintf(tmp, sizeof(tmp), (stmt->stmt->fields[i].flags & UNSIGNED_FLAG)? MYSQLI_LLU_SPEC : MYSQLI_LL_SPEC, llval);
1113 								ZVAL_STRING(stmt->result.vars[i], tmp, 1);
1114 							} else {
1115 								ZVAL_LONG(stmt->result.vars[i], llval);
1116 							}
1117 						} else {
1118 #if defined(MYSQL_DATA_TRUNCATED) && MYSQL_VERSION_ID > 50002
1119 							if (ret == MYSQL_DATA_TRUNCATED && *(stmt->stmt->bind[i].error) != 0) {
1120 								/* result was truncated */
1121 								ZVAL_STRINGL(stmt->result.vars[i], stmt->result.buf[i].val,
1122 											 stmt->stmt->bind[i].buffer_length, 1);
1123 							} else {
1124 #else
1125 							{
1126 #endif
1127 								ZVAL_STRINGL(stmt->result.vars[i], stmt->result.buf[i].val,
1128 											 stmt->result.buf[i].output_len, 1);
1129 							}
1130 						}
1131 						break;
1132 					default:
1133 						break;
1134 				}
1135 			} else {
1136 				ZVAL_NULL(stmt->result.vars[i]);
1137 			}
1138 		}
1139 	} else {
1140 		MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
1141 	}
1142 
1143 	switch (ret) {
1144 		case 0:
1145 #ifdef MYSQL_DATA_TRUNCATED
1146 		/* according to SQL standard truncation (e.g. loss of precision is
1147 		   not an error) - for detecting possible truncation you have to
1148 		   check mysqli_stmt_warning
1149 		*/
1150 		case MYSQL_DATA_TRUNCATED:
1151 #endif
1152 			RETURN_TRUE;
1153 		break;
1154 		case 1:
1155 			RETURN_FALSE;
1156 		break;
1157 		default:
1158 			RETURN_NULL();
1159 		break;
1160 	}
1161 }
1162 /* }}} */
1163 #else
1164 /* {{{ mixed mysqli_stmt_fetch_mysqlnd */
1165 void mysqli_stmt_fetch_mysqlnd(INTERNAL_FUNCTION_PARAMETERS)
1166 {
1167 	MY_STMT		*stmt;
1168 	zval		*mysql_stmt;
1169 	zend_bool	fetched_anything;
1170 
1171 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
1172 		return;
1173 	}
1174 	MYSQLI_FETCH_RESOURCE_STMT(stmt, &mysql_stmt, MYSQLI_STATUS_VALID);
1175 
1176 	if (FAIL  == mysqlnd_stmt_fetch(stmt->stmt, &fetched_anything)) {
1177 		RETURN_BOOL(FALSE);
1178 	} else if (fetched_anything == TRUE) {
1179 		RETURN_BOOL(TRUE);
1180 	} else {
1181 		RETURN_NULL();
1182 	}
1183 }
1184 #endif
1185 /* }}} */
1186 
1187 
1188 /* {{{ proto mixed mysqli_stmt_fetch(object stmt) U
1189    Fetch results from a prepared statement into the bound variables */
1190 PHP_FUNCTION(mysqli_stmt_fetch)
1191 {
1192 #if !defined(MYSQLI_USE_MYSQLND)
1193 	mysqli_stmt_fetch_libmysql(INTERNAL_FUNCTION_PARAM_PASSTHRU);
1194 #else
1195 	mysqli_stmt_fetch_mysqlnd(INTERNAL_FUNCTION_PARAM_PASSTHRU);
1196 #endif
1197 }
1198 /* }}} */
1199 
1200 /* {{{  php_add_field_properties */
1201 static void php_add_field_properties(zval *value, const MYSQL_FIELD *field TSRMLS_DC)
1202 {
1203 	add_property_string(value, "name",(field->name ? field->name : ""), 1);
1204 	add_property_string(value, "orgname",(field->org_name ? field->org_name : ""), 1);
1205 	add_property_string(value, "table",(field->table ? field->table : ""), 1);
1206 	add_property_string(value, "orgtable",(field->org_table ? field->org_table : ""), 1);
1207 	add_property_string(value, "def",(field->def ? field->def : ""), 1);
1208 	add_property_string(value, "db",(field->db ? field->db : ""), 1);
1209 
1210 	/* FIXME: manually set the catalog to "def" due to bug in
1211 	 * libmysqlclient which does not initialize field->catalog
1212 	 * and in addition, the catalog is always be "def"
1213 	 */
1214 	add_property_string(value, "catalog", "def", 1);
1215 
1216 	add_property_long(value, "max_length", field->max_length);
1217 	add_property_long(value, "length", field->length);
1218 	add_property_long(value, "charsetnr", field->charsetnr);
1219 	add_property_long(value, "flags", field->flags);
1220 	add_property_long(value, "type", field->type);
1221 	add_property_long(value, "decimals", field->decimals);
1222 }
1223 /* }}} */
1224 
1225 /* {{{ proto mixed mysqli_fetch_field (object result)
1226    Get column information from a result and return as an object */
1227 PHP_FUNCTION(mysqli_fetch_field)
1228 {
1229 	MYSQL_RES	*result;
1230 	zval		*mysql_result;
1231 	const MYSQL_FIELD	*field;
1232 
1233 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
1234 		return;
1235 	}
1236 
1237 	MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, &mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1238 
1239 	if (!(field = mysql_fetch_field(result))) {
1240 		RETURN_FALSE;
1241 	}
1242 
1243 	object_init(return_value);
1244 	php_add_field_properties(return_value, field TSRMLS_CC);
1245 }
1246 /* }}} */
1247 
1248 /* {{{ proto mixed mysqli_fetch_fields (object result)
1249    Return array of objects containing field meta-data */
1250 PHP_FUNCTION(mysqli_fetch_fields)
1251 {
1252 	MYSQL_RES	*result;
1253 	zval		*mysql_result;
1254 	zval		*obj;
1255 
1256 	unsigned int i;
1257 
1258 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
1259 		return;
1260 	}
1261 
1262 	MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, &mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1263 
1264 	array_init(return_value);
1265 
1266 	for (i = 0; i < mysql_num_fields(result); i++) {
1267 		const MYSQL_FIELD *field = mysql_fetch_field_direct(result, i);
1268 
1269 		MAKE_STD_ZVAL(obj);
1270 		object_init(obj);
1271 
1272 		php_add_field_properties(obj, field TSRMLS_CC);
1273 		add_index_zval(return_value, i, obj);
1274 	}
1275 }
1276 /* }}} */
1277 
1278 /* {{{ proto mixed mysqli_fetch_field_direct (object result, int offset)
1279    Fetch meta-data for a single field */
1280 PHP_FUNCTION(mysqli_fetch_field_direct)
1281 {
1282 	MYSQL_RES	*result;
1283 	zval		*mysql_result;
1284 	const MYSQL_FIELD	*field;
1285 	long		offset;
1286 
1287 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol", &mysql_result, mysqli_result_class_entry, &offset) == FAILURE) {
1288 		return;
1289 	}
1290 
1291 	MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, &mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1292 
1293 	if (offset < 0 || offset >= (long) mysql_num_fields(result)) {
1294 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Field offset is invalid for resultset");
1295 		RETURN_FALSE;
1296 	}
1297 
1298 	if (!(field = mysql_fetch_field_direct(result,offset))) {
1299 		RETURN_FALSE;
1300 	}
1301 
1302 	object_init(return_value);
1303 	php_add_field_properties(return_value, field TSRMLS_CC);
1304 }
1305 /* }}} */
1306 
1307 /* {{{ proto mixed mysqli_fetch_lengths (object result)
1308    Get the length of each output in a result */
1309 PHP_FUNCTION(mysqli_fetch_lengths)
1310 {
1311 	MYSQL_RES		*result;
1312 	zval			*mysql_result;
1313 	unsigned int	i;
1314 	unsigned long	*ret;
1315 
1316 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
1317 		return;
1318 	}
1319 
1320 	MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, &mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1321 
1322 	if (!(ret = mysql_fetch_lengths(result))) {
1323 		RETURN_FALSE;
1324 	}
1325 
1326 	array_init(return_value);
1327 
1328 	for (i = 0; i < mysql_num_fields(result); i++) {
1329 		add_index_long(return_value, i, ret[i]);
1330 	}
1331 }
1332 /* }}} */
1333 
1334 /* {{{ proto array mysqli_fetch_row (object result)
1335    Get a result row as an enumerated array */
1336 PHP_FUNCTION(mysqli_fetch_row)
1337 {
1338 	php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, MYSQLI_NUM, 0);
1339 }
1340 /* }}} */
1341 
1342 /* {{{ proto int mysqli_field_count(object link)
1343    Fetch the number of fields returned by the last query for the given link
1344 */
1345 PHP_FUNCTION(mysqli_field_count)
1346 {
1347 	MY_MYSQL	*mysql;
1348 	zval		*mysql_link;
1349 
1350 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1351 		return;
1352 	}
1353 	MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
1354 
1355 	RETURN_LONG(mysql_field_count(mysql->mysql));
1356 }
1357 /* }}} */
1358 
1359 /* {{{ proto int mysqli_field_seek(object result, int fieldnr)
1360    Set result pointer to a specified field offset
1361 */
1362 PHP_FUNCTION(mysqli_field_seek)
1363 {
1364 	MYSQL_RES		*result;
1365 	zval			*mysql_result;
1366 	unsigned long	fieldnr;
1367 
1368 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol", &mysql_result, mysqli_result_class_entry, &fieldnr) == FAILURE) {
1369 		return;
1370 	}
1371 	MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, &mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1372 
1373 	if (fieldnr < 0 || fieldnr >= mysql_num_fields(result)) {
1374 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid field offset");
1375 		RETURN_FALSE;
1376 	}
1377 
1378 	mysql_field_seek(result, fieldnr);
1379 	RETURN_TRUE;
1380 }
1381 /* }}} */
1382 
1383 /* {{{ proto int mysqli_field_tell(object result)
1384    Get current field offset of result pointer */
1385 PHP_FUNCTION(mysqli_field_tell)
1386 {
1387 	MYSQL_RES	*result;
1388 	zval		*mysql_result;
1389 
1390 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
1391 		return;
1392 	}
1393 	MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, &mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1394 
1395 	RETURN_LONG(mysql_field_tell(result));
1396 }
1397 /* }}} */
1398 
1399 /* {{{ proto void mysqli_free_result(object result)
1400    Free query result memory for the given result handle */
1401 PHP_FUNCTION(mysqli_free_result)
1402 {
1403 	MYSQL_RES	*result;
1404 	zval		*mysql_result;
1405 
1406 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
1407 		return;
1408 	}
1409 	MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, &mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1410 
1411 	mysqli_free_result(result, FALSE);
1412 	MYSQLI_CLEAR_RESOURCE(&mysql_result);
1413 }
1414 /* }}} */
1415 
1416 /* {{{ proto string mysqli_get_client_info(void)
1417    Get MySQL client info */
1418 PHP_FUNCTION(mysqli_get_client_info)
1419 {
1420 	const char * info = mysql_get_client_info();
1421 	if (info) {
1422 		RETURN_STRING(info, 1);
1423 	}
1424 }
1425 /* }}} */
1426 
1427 /* {{{ proto int mysqli_get_client_version(void)
1428    Get MySQL client info */
1429 PHP_FUNCTION(mysqli_get_client_version)
1430 {
1431 	RETURN_LONG((long)mysql_get_client_version());
1432 }
1433 /* }}} */
1434 
1435 /* {{{ proto string mysqli_get_host_info (object link)
1436    Get MySQL host info */
1437 PHP_FUNCTION(mysqli_get_host_info)
1438 {
1439 	MY_MYSQL	*mysql;
1440 	zval		*mysql_link = NULL;
1441 
1442 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1443 		return;
1444 	}
1445 	MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
1446 #if !defined(MYSQLI_USE_MYSQLND)
1447 	RETURN_STRING((mysql->mysql->host_info) ? mysql->mysql->host_info : "", 1);
1448 #else
1449 	RETURN_STRING((mysql->mysql->data->host_info) ? mysql->mysql->data->host_info : "", 1);
1450 #endif
1451 }
1452 /* }}} */
1453 
1454 /* {{{ proto int mysqli_get_proto_info(object link)
1455    Get MySQL protocol information */
1456 PHP_FUNCTION(mysqli_get_proto_info)
1457 {
1458 	MY_MYSQL	*mysql;
1459 	zval		*mysql_link = NULL;
1460 
1461 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1462 		return;
1463 	}
1464 	MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
1465 	RETURN_LONG(mysql_get_proto_info(mysql->mysql));
1466 }
1467 /* }}} */
1468 
1469 /* {{{ proto string mysqli_get_server_info(object link)
1470    Get MySQL server info */
1471 PHP_FUNCTION(mysqli_get_server_info)
1472 {
1473 	MY_MYSQL	*mysql;
1474 	zval		*mysql_link = NULL;
1475 	const char	*info;
1476 
1477 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1478 		return;
1479 	}
1480 	MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
1481 
1482 	info = mysql_get_server_info(mysql->mysql);
1483 	if (info) {
1484 		RETURN_STRING(info, 1);
1485 	}
1486 }
1487 /* }}} */
1488 
1489 /* {{{ proto int mysqli_get_server_version(object link)
1490    Return the MySQL version for the server referenced by the given link */
1491 PHP_FUNCTION(mysqli_get_server_version)
1492 {
1493 	MY_MYSQL	*mysql;
1494 	zval		*mysql_link = NULL;
1495 
1496 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1497 		return;
1498 	}
1499 	MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
1500 
1501 	RETURN_LONG(mysql_get_server_version(mysql->mysql));
1502 }
1503 /* }}} */
1504 
1505 /* {{{ proto string mysqli_info(object link)
1506    Get information about the most recent query */
1507 PHP_FUNCTION(mysqli_info)
1508 {
1509 	MY_MYSQL	*mysql;
1510 	zval		*mysql_link = NULL;
1511 	const char	*info;
1512 
1513 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1514 		return;
1515 	}
1516 	MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
1517 
1518 	info = mysql_info(mysql->mysql);
1519 	if (info) {
1520 		RETURN_STRING(info, 1);
1521 	}
1522 }
1523 /* }}} */
1524 
1525 
1526 /* {{{ php_mysqli_init() */
1527 void php_mysqli_init(INTERNAL_FUNCTION_PARAMETERS)
1528 {
1529 	MYSQLI_RESOURCE *mysqli_resource;
1530 	MY_MYSQL *mysql;
1531 
1532 	if (getThis() && ((mysqli_object *) zend_object_store_get_object(getThis() TSRMLS_CC))->ptr) {
1533 		return;
1534 	}
1535 
1536 	mysql = (MY_MYSQL *)ecalloc(1, sizeof(MY_MYSQL));
1537 
1538 #if !defined(MYSQLI_USE_MYSQLND)
1539 	if (!(mysql->mysql = mysql_init(NULL)))
1540 #else
1541 	/*
1542 	  We create always persistent, as if the user want to connecto
1543 	  to p:somehost, we can't convert the handle then
1544 	*/
1545 	if (!(mysql->mysql = mysql_init(TRUE)))
1546 #endif
1547 	{
1548 		efree(mysql);
1549 		RETURN_FALSE;
1550 	}
1551 
1552 	mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
1553 	mysqli_resource->ptr = (void *)mysql;
1554 	mysqli_resource->status = MYSQLI_STATUS_INITIALIZED;
1555 
1556 	if (!getThis() || !instanceof_function(Z_OBJCE_P(getThis()), mysqli_link_class_entry TSRMLS_CC)) {
1557 		MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_link_class_entry);
1558 	} else {
1559 		((mysqli_object *) zend_object_store_get_object(getThis() TSRMLS_CC))->ptr = mysqli_resource;
1560 	}
1561 }
1562 /* }}} */
1563 
1564 
1565 /* {{{ proto resource mysqli_init(void)
1566    Initialize mysqli and return a resource for use with mysql_real_connect */
1567 PHP_FUNCTION(mysqli_init)
1568 {
1569 	php_mysqli_init(INTERNAL_FUNCTION_PARAM_PASSTHRU);
1570 }
1571 /* }}} */
1572 
1573 /* {{{ proto mixed mysqli_insert_id(object link)
1574    Get the ID generated from the previous INSERT operation */
1575 PHP_FUNCTION(mysqli_insert_id)
1576 {
1577 	MY_MYSQL		*mysql;
1578 	my_ulonglong	rc;
1579 	zval			*mysql_link;
1580 
1581 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1582 		return;
1583 	}
1584 	MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
1585 	rc = mysql_insert_id(mysql->mysql);
1586 	MYSQLI_RETURN_LONG_LONG(rc)
1587 }
1588 /* }}} */
1589 
1590 /* {{{ proto bool mysqli_kill(object link, int processid)
1591    Kill a mysql process on the server */
1592 PHP_FUNCTION(mysqli_kill)
1593 {
1594 	MY_MYSQL	*mysql;
1595 	zval		*mysql_link;
1596 	long		processid;
1597 
1598 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol", &mysql_link, mysqli_link_class_entry, &processid) == FAILURE) {
1599 		return;
1600 	}
1601 	MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
1602 
1603 	if (processid <= 0) {
1604 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "processid should have positive value");
1605 		RETURN_FALSE;
1606 	}
1607 
1608 	if (mysql_kill(mysql->mysql, processid)) {
1609 		MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
1610 		RETURN_FALSE;
1611 	}
1612 	RETURN_TRUE;
1613 }
1614 /* }}} */
1615 
1616 /* {{{ proto bool mysqli_more_results(object link)
1617    check if there any more query results from a multi query */
1618 PHP_FUNCTION(mysqli_more_results)
1619 {
1620 	MY_MYSQL	*mysql;
1621 	zval		*mysql_link;
1622 
1623 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1624 		return;
1625 	}
1626 	MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
1627 
1628 	RETURN_BOOL(mysql_more_results(mysql->mysql));
1629 }
1630 /* }}} */
1631 
1632 /* {{{ proto bool mysqli_next_result(object link)
1633    read next result from multi_query */
1634 PHP_FUNCTION(mysqli_next_result) {
1635 	MY_MYSQL	*mysql;
1636 	zval		*mysql_link;
1637 
1638 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1639 		return;
1640 	}
1641 	MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
1642 
1643 	if (!mysql_more_results(mysql->mysql)) {
1644 		php_error_docref(NULL TSRMLS_CC, E_STRICT, "There is no next result set. "
1645 						"Please, call mysqli_more_results()/mysqli::more_results() to check "
1646 						"whether to call this function/method");
1647 	}
1648 
1649 	RETURN_BOOL(!mysql_next_result(mysql->mysql));
1650 }
1651 /* }}} */
1652 
1653 #if defined(HAVE_STMT_NEXT_RESULT) && defined(MYSQLI_USE_MYSQLND)
1654 /* {{{ proto bool mysqli_stmt_next_result(object link)
1655    check if there any more query results from a multi query */
1656 PHP_FUNCTION(mysqli_stmt_more_results)
1657 {
1658 	MY_STMT		*stmt;
1659 	zval		*mysql_stmt;
1660 
1661 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
1662 		return;
1663 	}
1664 	MYSQLI_FETCH_RESOURCE_STMT(stmt, &mysql_stmt, MYSQLI_STATUS_VALID);
1665 
1666 	RETURN_BOOL(mysqlnd_stmt_more_results(stmt->stmt));
1667 }
1668 /* }}} */
1669 
1670 
1671 /* {{{ proto bool mysqli_stmt_next_result(object link)
1672    read next result from multi_query */
1673 PHP_FUNCTION(mysqli_stmt_next_result) {
1674 	MY_STMT		*stmt;
1675 	zval		*mysql_stmt;
1676 
1677 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
1678 		return;
1679 	}
1680 	MYSQLI_FETCH_RESOURCE_STMT(stmt, &mysql_stmt, MYSQLI_STATUS_VALID);
1681 
1682 	if (!mysqlnd_stmt_more_results(stmt->stmt)) {
1683 		php_error_docref(NULL TSRMLS_CC, E_STRICT, "There is no next result set. "
1684 						"Please, call mysqli_stmt_more_results()/mysqli_stmt::more_results() to check "
1685 						"whether to call this function/method");
1686 	}
1687 
1688 	RETURN_BOOL(!mysql_stmt_next_result(stmt->stmt));
1689 }
1690 /* }}} */
1691 #endif
1692 
1693 
1694 /* {{{ proto int mysqli_num_fields(object result)
1695    Get number of fields in result */
1696 PHP_FUNCTION(mysqli_num_fields)
1697 {
1698 	MYSQL_RES	*result;
1699 	zval		*mysql_result;
1700 
1701 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
1702 		return;
1703 	}
1704 	MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, &mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1705 
1706 	RETURN_LONG(mysql_num_fields(result));
1707 }
1708 /* }}} */
1709 
1710 /* {{{ proto mixed mysqli_num_rows(object result)
1711    Get number of rows in result */
1712 PHP_FUNCTION(mysqli_num_rows)
1713 {
1714 	MYSQL_RES	*result;
1715 	zval		*mysql_result;
1716 
1717 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
1718 		return;
1719 	}
1720 	MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, &mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1721 
1722 	if (mysqli_result_is_unbuffered_and_not_everything_is_fetched(result)) {
1723 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Function cannot be used with MYSQL_USE_RESULT");
1724 		RETURN_LONG(0);
1725 	}
1726 
1727 	MYSQLI_RETURN_LONG_LONG(mysql_num_rows(result));
1728 }
1729 /* }}} */
1730 
1731 /* {{{ mysqli_options_get_option_zval_type */
1732 static int mysqli_options_get_option_zval_type(int option)
1733 {
1734 	switch (option) {
1735 #ifdef MYSQLI_USE_MYSQLND
1736 #if PHP_MAJOR_VERSION >= 6
1737 		case MYSQLND_OPT_NUMERIC_AND_DATETIME_AS_UNICODE:
1738 #endif
1739 		case MYSQLND_OPT_NET_CMD_BUFFER_SIZE:
1740 		case MYSQLND_OPT_NET_READ_BUFFER_SIZE:
1741 #ifdef MYSQLND_STRING_TO_INT_CONVERSION
1742 		case MYSQLND_OPT_INT_AND_FLOAT_NATIVE:
1743 #endif
1744 #endif /* MYSQLI_USE_MYSQLND */
1745 		case MYSQL_OPT_CONNECT_TIMEOUT:
1746 #ifdef MYSQL_REPORT_DATA_TRUNCATION
1747 		case MYSQL_REPORT_DATA_TRUNCATION:
1748 #endif
1749 		case MYSQL_OPT_LOCAL_INFILE:
1750 		case MYSQL_OPT_NAMED_PIPE:
1751 #ifdef MYSQL_OPT_PROTOCOL
1752                 case MYSQL_OPT_PROTOCOL:
1753 #endif /* MySQL 4.1.0 */
1754 #ifdef MYSQL_OPT_READ_TIMEOUT
1755 		case MYSQL_OPT_READ_TIMEOUT:
1756 		case MYSQL_OPT_WRITE_TIMEOUT:
1757 		case MYSQL_OPT_GUESS_CONNECTION:
1758 		case MYSQL_OPT_USE_EMBEDDED_CONNECTION:
1759 		case MYSQL_OPT_USE_REMOTE_CONNECTION:
1760 		case MYSQL_SECURE_AUTH:
1761 #endif /* MySQL 4.1.1 */
1762 #ifdef MYSQL_OPT_RECONNECT
1763 		case MYSQL_OPT_RECONNECT:
1764 #endif /* MySQL 5.0.13 */
1765 #ifdef MYSQL_OPT_SSL_VERIFY_SERVER_CERT
1766 		case MYSQL_OPT_SSL_VERIFY_SERVER_CERT:
1767 #endif /* MySQL 5.0.23 */
1768 #ifdef MYSQL_OPT_COMPRESS
1769 		case MYSQL_OPT_COMPRESS:
1770 #endif /* mysqlnd @ PHP 5.3.2 */
1771 #ifdef MYSQL_OPT_SSL_VERIFY_SERVER_CERT
1772 	REGISTER_LONG_CONSTANT("MYSQLI_OPT_SSL_VERIFY_SERVER_CERT", MYSQL_OPT_SSL_VERIFY_SERVER_CERT, CONST_CS | CONST_PERSISTENT);
1773 #endif /* MySQL 5.1.1., mysqlnd @ PHP 5.3.3 */
1774 #if (MYSQL_VERSION_ID >= 50611 && defined(CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS)) || defined(MYSQLI_USE_MYSQLND)
1775 		case MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS:
1776 #endif
1777 			return IS_LONG;
1778 
1779 #ifdef MYSQL_SHARED_MEMORY_BASE_NAME
1780                 case MYSQL_SHARED_MEMORY_BASE_NAME:
1781 #endif /* MySQL 4.1.0 */
1782 #ifdef MYSQL_SET_CLIENT_IP
1783 		case MYSQL_SET_CLIENT_IP:
1784 #endif /* MySQL 4.1.1 */
1785 		case MYSQL_READ_DEFAULT_FILE:
1786 		case MYSQL_READ_DEFAULT_GROUP:
1787 		case MYSQL_INIT_COMMAND:
1788 		case MYSQL_SET_CHARSET_NAME:
1789 		case MYSQL_SET_CHARSET_DIR:
1790 #if MYSQL_VERSION_ID > 50605 || defined(MYSQLI_USE_MYSQLND)
1791 		case MYSQL_SERVER_PUBLIC_KEY:
1792 #endif
1793 			return IS_STRING;
1794 
1795 		default:
1796 			return IS_NULL;
1797 	}
1798 }
1799 /* }}} */
1800 
1801 
1802 /* {{{ proto bool mysqli_options(object link, int flags, mixed values)
1803    Set options */
1804 PHP_FUNCTION(mysqli_options)
1805 {
1806 	MY_MYSQL		*mysql;
1807 	zval			*mysql_link = NULL;
1808 	zval			**mysql_value;
1809 	long			mysql_option;
1810 	unsigned int	l_value;
1811 	long			ret;
1812 	int				expected_type;
1813 
1814 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "OlZ", &mysql_link, mysqli_link_class_entry, &mysql_option, &mysql_value) == FAILURE) {
1815 		return;
1816 	}
1817 	MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_INITIALIZED);
1818 
1819 #if PHP_API_VERSION < 20100412
1820 	if ((PG(open_basedir) && PG(open_basedir)[0] != '\0') || PG(safe_mode)) {
1821 #else
1822 	if (PG(open_basedir) && PG(open_basedir)[0] != '\0') {
1823 #endif
1824 		if(mysql_option == MYSQL_OPT_LOCAL_INFILE) {
1825 			RETURN_FALSE;
1826 		}
1827 	}
1828 	expected_type = mysqli_options_get_option_zval_type(mysql_option);
1829 	if (expected_type != Z_TYPE_PP(mysql_value)) {
1830 		switch (expected_type) {
1831 			case IS_STRING:
1832 				convert_to_string_ex(mysql_value);
1833 				break;
1834 			case IS_LONG:
1835 				convert_to_long_ex(mysql_value);
1836 				break;
1837 			default:
1838 				break;
1839 		}
1840 	}
1841 	switch (expected_type) {
1842 		case IS_STRING:
1843 			ret = mysql_options(mysql->mysql, mysql_option, Z_STRVAL_PP(mysql_value));
1844 			break;
1845 		case IS_LONG:
1846 			l_value = Z_LVAL_PP(mysql_value);
1847 			ret = mysql_options(mysql->mysql, mysql_option, (char *)&l_value);
1848 			break;
1849 		default:
1850 			ret = 1;
1851 			break;
1852 	}
1853 
1854 	RETURN_BOOL(!ret);
1855 }
1856 /* }}} */
1857 
1858 
1859 /* {{{ proto bool mysqli_ping(object link)
1860    Ping a server connection or reconnect if there is no connection */
1861 PHP_FUNCTION(mysqli_ping)
1862 {
1863 	MY_MYSQL	*mysql;
1864 	zval		*mysql_link;
1865 	long		rc;
1866 
1867 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1868 		return;
1869 	}
1870 	MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
1871 	rc = mysql_ping(mysql->mysql);
1872 	MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
1873 
1874 	RETURN_BOOL(!rc);
1875 }
1876 /* }}} */
1877 
1878 /* {{{ proto mixed mysqli_prepare(object link, string query)
1879    Prepare a SQL statement for execution */
1880 PHP_FUNCTION(mysqli_prepare)
1881 {
1882 	MY_MYSQL		*mysql;
1883 	MY_STMT			*stmt;
1884 	char			*query = NULL;
1885 	int				query_len;
1886 	zval			*mysql_link;
1887 	MYSQLI_RESOURCE	*mysqli_resource;
1888 
1889 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os",&mysql_link, mysqli_link_class_entry, &query, &query_len) == FAILURE) {
1890 		return;
1891 	}
1892 	MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
1893 
1894 #if !defined(MYSQLI_USE_MYSQLND)
1895 	if (mysql->mysql->status == MYSQL_STATUS_GET_RESULT) {
1896 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "All data must be fetched before a new statement prepare takes place");
1897 		RETURN_FALSE;
1898 	}
1899 #endif
1900 
1901 	stmt = (MY_STMT *)ecalloc(1,sizeof(MY_STMT));
1902 
1903 	if ((stmt->stmt = mysql_stmt_init(mysql->mysql))) {
1904 		if (mysql_stmt_prepare(stmt->stmt, query, query_len)) {
1905 			/* mysql_stmt_close() clears errors, so we have to store them temporarily */
1906 #if !defined(MYSQLI_USE_MYSQLND)
1907 			char  last_error[MYSQL_ERRMSG_SIZE];
1908 			char  sqlstate[SQLSTATE_LENGTH+1];
1909 			unsigned int last_errno;
1910 
1911 			last_errno = stmt->stmt->last_errno;
1912 			memcpy(last_error, stmt->stmt->last_error, MYSQL_ERRMSG_SIZE);
1913 			memcpy(sqlstate, mysql->mysql->net.sqlstate, SQLSTATE_LENGTH+1);
1914 #else
1915 			MYSQLND_ERROR_INFO error_info = *mysql->mysql->data->error_info;
1916 #endif
1917 			mysqli_stmt_close(stmt->stmt, FALSE);
1918 			stmt->stmt = NULL;
1919 
1920 			/* restore error messages */
1921 #if !defined(MYSQLI_USE_MYSQLND)
1922 			mysql->mysql->net.last_errno = last_errno;
1923 			memcpy(mysql->mysql->net.last_error, last_error, MYSQL_ERRMSG_SIZE);
1924 			memcpy(mysql->mysql->net.sqlstate, sqlstate, SQLSTATE_LENGTH+1);
1925 #else
1926 			*mysql->mysql->data->error_info = error_info;
1927 #endif
1928 		}
1929 	}
1930 
1931 	/* don't initialize stmt->query with NULL, we ecalloc()-ed the memory */
1932 	/* Get performance boost if reporting is switched off */
1933 	if (stmt->stmt && query_len && (MyG(report_mode) & MYSQLI_REPORT_INDEX)) {
1934 		stmt->query = (char *)emalloc(query_len + 1);
1935 		memcpy(stmt->query, query, query_len);
1936 		stmt->query[query_len] = '\0';
1937 	}
1938 
1939 	/* don't join to the previous if because it won't work if mysql_stmt_prepare_fails */
1940 	if (!stmt->stmt) {
1941 		MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
1942 		efree(stmt);
1943 		RETURN_FALSE;
1944 	}
1945 #ifndef MYSQLI_USE_MYSQLND
1946 	stmt->link_handle = Z_OBJ_HANDLE(*mysql_link);
1947 	zend_objects_store_add_ref_by_handle(stmt->link_handle TSRMLS_CC);
1948 #endif
1949 
1950 	mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
1951 	mysqli_resource->ptr = (void *)stmt;
1952 
1953 	/* change status */
1954 	mysqli_resource->status = MYSQLI_STATUS_VALID;
1955 	MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_stmt_class_entry);
1956 }
1957 /* }}} */
1958 
1959 
1960 /* {{{ proto bool mysqli_real_connect(object link [,string hostname [,string username [,string passwd [,string dbname [,int port [,string socket [,int flags]]]]]]])
1961    Open a connection to a mysql server */
1962 PHP_FUNCTION(mysqli_real_connect)
1963 {
1964 	mysqli_common_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, TRUE, FALSE);
1965 }
1966 /* }}} */
1967 
1968 
1969 /* {{{ proto bool mysqli_real_query(object link, string query)
1970    Binary-safe version of mysql_query() */
1971 PHP_FUNCTION(mysqli_real_query)
1972 {
1973 	MY_MYSQL	*mysql;
1974 	zval		*mysql_link;
1975 	char		*query = NULL;
1976 	int			query_len;
1977 
1978 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &mysql_link, mysqli_link_class_entry, &query, &query_len) == FAILURE) {
1979 		return;
1980 	}
1981 	MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
1982 
1983 	MYSQLI_DISABLE_MQ; /* disable multi statements/queries */
1984 
1985 	if (mysql_real_query(mysql->mysql, query, query_len)) {
1986 		MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
1987 		RETURN_FALSE;
1988 	}
1989 
1990 	if (!mysql_field_count(mysql->mysql)) {
1991 		if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
1992 			php_mysqli_report_index(query, mysqli_server_status(mysql->mysql) TSRMLS_CC);
1993 		}
1994 	}
1995 
1996 	RETURN_TRUE;
1997 }
1998 /* }}} */
1999 
2000 /* {{{ proto string mysqli_real_escape_string(object link, string escapestr)
2001    Escapes special characters in a string for use in a SQL statement, taking into account the current charset of the connection */
2002 PHP_FUNCTION(mysqli_real_escape_string) {
2003 	MY_MYSQL	*mysql;
2004 	zval		*mysql_link = NULL;
2005 	char		*escapestr, *newstr;
2006 	int			escapestr_len, newstr_len;
2007 
2008 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &mysql_link, mysqli_link_class_entry, &escapestr, &escapestr_len) == FAILURE) {
2009 		return;
2010 	}
2011 	MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
2012 
2013 	newstr = safe_emalloc(2, escapestr_len, 1);
2014 	newstr_len = mysql_real_escape_string(mysql->mysql, newstr, escapestr, escapestr_len);
2015 	newstr = erealloc(newstr, newstr_len + 1);
2016 
2017 	RETURN_STRINGL(newstr, newstr_len, 0);
2018 }
2019 /* }}} */
2020 
2021 
2022 /* {{{ proto bool mysqli_rollback(object link)
2023    Undo actions from current transaction */
2024 PHP_FUNCTION(mysqli_rollback)
2025 {
2026 	MY_MYSQL	*mysql;
2027 	zval		*mysql_link;
2028 	long		flags = TRANS_COR_NO_OPT;
2029 	char *		name = NULL;
2030 	int			name_len = 0;
2031 
2032 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O|ls", &mysql_link, mysqli_link_class_entry, &flags, &name, &name_len) == FAILURE) {
2033 		return;
2034 	}
2035 	MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
2036 
2037 #if !defined(MYSQLI_USE_MYSQLND)
2038 	if (mysqli_commit_or_rollback_libmysql(mysql->mysql, FALSE, flags, name TSRMLS_CC)) {
2039 #else
2040 	if (FAIL == mysqlnd_rollback(mysql->mysql, flags, name)) {
2041 #endif
2042 		RETURN_FALSE;
2043 	}
2044 	RETURN_TRUE;
2045 }
2046 /* }}} */
2047 
2048 /* {{{ proto bool mysqli_stmt_send_long_data(object stmt, int param_nr, string data)
2049 */
2050 PHP_FUNCTION(mysqli_stmt_send_long_data)
2051 {
2052 	MY_STMT *stmt;
2053 	zval	*mysql_stmt;
2054 	char	*data;
2055 	long	param_nr;
2056 	int		data_len;
2057 
2058 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ols", &mysql_stmt, mysqli_stmt_class_entry, &param_nr, &data, &data_len) == FAILURE) {
2059 		return;
2060 	}
2061 	MYSQLI_FETCH_RESOURCE_STMT(stmt, &mysql_stmt, MYSQLI_STATUS_VALID);
2062 
2063 	if (param_nr < 0) {
2064 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid parameter number");
2065 		RETURN_FALSE;
2066 	}
2067 	if (mysql_stmt_send_long_data(stmt->stmt, param_nr, data, data_len)) {
2068 		RETURN_FALSE;
2069 	}
2070 	RETURN_TRUE;
2071 }
2072 /* }}} */
2073 
2074 
2075 /* {{{ proto mixed mysqli_stmt_affected_rows(object stmt)
2076    Return the number of rows affected in the last query for the given link */
2077 PHP_FUNCTION(mysqli_stmt_affected_rows)
2078 {
2079 	MY_STMT			*stmt;
2080 	zval			*mysql_stmt;
2081 	my_ulonglong	rc;
2082 
2083 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2084 		return;
2085 	}
2086 	MYSQLI_FETCH_RESOURCE_STMT(stmt, &mysql_stmt, MYSQLI_STATUS_VALID);
2087 
2088 	rc = mysql_stmt_affected_rows(stmt->stmt);
2089 	if (rc == (my_ulonglong) -1) {
2090 		RETURN_LONG(-1);
2091 	}
2092 	MYSQLI_RETURN_LONG_LONG(rc)
2093 }
2094 /* }}} */
2095 
2096 /* {{{ proto bool mysqli_stmt_close(object stmt)
2097    Close statement */
2098 PHP_FUNCTION(mysqli_stmt_close)
2099 {
2100 	MY_STMT		*stmt;
2101 	zval		*mysql_stmt;
2102 
2103 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2104 		return;
2105 	}
2106 	MYSQLI_FETCH_RESOURCE_STMT(stmt, &mysql_stmt, MYSQLI_STATUS_VALID);
2107 
2108 	mysqli_stmt_close(stmt->stmt, FALSE);
2109 	stmt->stmt = NULL;
2110 	php_clear_stmt_bind(stmt TSRMLS_CC);
2111 	MYSQLI_CLEAR_RESOURCE(&mysql_stmt);
2112 	RETURN_TRUE;
2113 }
2114 /* }}} */
2115 
2116 /* {{{ proto void mysqli_stmt_data_seek(object stmt, int offset)
2117    Move internal result pointer */
2118 PHP_FUNCTION(mysqli_stmt_data_seek)
2119 {
2120 	MY_STMT		*stmt;
2121 	zval		*mysql_stmt;
2122 	long		offset;
2123 
2124 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol", &mysql_stmt, mysqli_stmt_class_entry, &offset) == FAILURE) {
2125 		return;
2126 	}
2127 	if (offset < 0) {
2128 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset must be positive");
2129 		RETURN_FALSE;
2130 	}
2131 
2132 	MYSQLI_FETCH_RESOURCE_STMT(stmt, &mysql_stmt, MYSQLI_STATUS_VALID);
2133 
2134 	mysql_stmt_data_seek(stmt->stmt, offset);
2135 }
2136 /* }}} */
2137 
2138 /* {{{ proto int mysqli_stmt_field_count(object stmt) {
2139    Return the number of result columns for the given statement */
2140 PHP_FUNCTION(mysqli_stmt_field_count)
2141 {
2142 	MY_STMT		*stmt;
2143 	zval		*mysql_stmt;
2144 
2145 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2146 		return;
2147 	}
2148 	MYSQLI_FETCH_RESOURCE_STMT(stmt, &mysql_stmt, MYSQLI_STATUS_VALID);
2149 
2150 	RETURN_LONG(mysql_stmt_field_count(stmt->stmt));
2151 }
2152 /* }}} */
2153 
2154 /* {{{ proto void mysqli_stmt_free_result(object stmt)
2155    Free stored result memory for the given statement handle */
2156 PHP_FUNCTION(mysqli_stmt_free_result)
2157 {
2158 	MY_STMT		*stmt;
2159 	zval		*mysql_stmt;
2160 
2161 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2162 		return;
2163 	}
2164 
2165 	MYSQLI_FETCH_RESOURCE_STMT(stmt, &mysql_stmt, MYSQLI_STATUS_VALID);
2166 
2167 	mysql_stmt_free_result(stmt->stmt);
2168 }
2169 /* }}} */
2170 
2171 /* {{{ proto mixed mysqli_stmt_insert_id(object stmt)
2172    Get the ID generated from the previous INSERT operation */
2173 PHP_FUNCTION(mysqli_stmt_insert_id)
2174 {
2175 	MY_STMT			*stmt;
2176 	my_ulonglong	rc;
2177 	zval			*mysql_stmt;
2178 
2179 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2180 		return;
2181 	}
2182 	MYSQLI_FETCH_RESOURCE_STMT(stmt, &mysql_stmt, MYSQLI_STATUS_VALID);
2183 	rc = mysql_stmt_insert_id(stmt->stmt);
2184 	MYSQLI_RETURN_LONG_LONG(rc)
2185 }
2186 /* }}} */
2187 
2188 /* {{{ proto int mysqli_stmt_param_count(object stmt)
2189    Return the number of parameter for the given statement */
2190 PHP_FUNCTION(mysqli_stmt_param_count)
2191 {
2192 	MY_STMT		*stmt;
2193 	zval		*mysql_stmt;
2194 
2195 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2196 		return;
2197 	}
2198 	MYSQLI_FETCH_RESOURCE_STMT(stmt, &mysql_stmt, MYSQLI_STATUS_VALID);
2199 
2200 	RETURN_LONG(mysql_stmt_param_count(stmt->stmt));
2201 }
2202 /* }}} */
2203 
2204 /* {{{ proto bool mysqli_stmt_reset(object stmt)
2205    reset a prepared statement */
2206 PHP_FUNCTION(mysqli_stmt_reset)
2207 {
2208 	MY_STMT		*stmt;
2209 	zval		*mysql_stmt;
2210 
2211 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2212 		return;
2213 	}
2214 
2215 	MYSQLI_FETCH_RESOURCE_STMT(stmt, &mysql_stmt, MYSQLI_STATUS_VALID);
2216 
2217 	if (mysql_stmt_reset(stmt->stmt)) {
2218 		RETURN_FALSE;
2219 	}
2220 	RETURN_TRUE;
2221 }
2222 /* }}} */
2223 
2224 /* {{{ proto mixed mysqli_stmt_num_rows(object stmt)
2225    Return the number of rows in statements result set */
2226 PHP_FUNCTION(mysqli_stmt_num_rows)
2227 {
2228 	MY_STMT			*stmt;
2229 	zval			*mysql_stmt;
2230 	my_ulonglong	rc;
2231 
2232 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2233 		return;
2234 	}
2235 
2236 	MYSQLI_FETCH_RESOURCE_STMT(stmt, &mysql_stmt, MYSQLI_STATUS_VALID);
2237 
2238 	rc = mysql_stmt_num_rows(stmt->stmt);
2239 	MYSQLI_RETURN_LONG_LONG(rc)
2240 }
2241 /* }}} */
2242 
2243 /* {{{ proto bool mysqli_select_db(object link, string dbname)
2244    Select a MySQL database */
2245 PHP_FUNCTION(mysqli_select_db)
2246 {
2247 	MY_MYSQL	*mysql;
2248 	zval		*mysql_link;
2249 	char		*dbname;
2250 	int			dbname_len;
2251 
2252 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &mysql_link, mysqli_link_class_entry, &dbname, &dbname_len) == FAILURE) {
2253 		return;
2254 	}
2255 	MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
2256 
2257 	if (mysql_select_db(mysql->mysql, dbname)) {
2258 		MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
2259 		RETURN_FALSE;
2260 	}
2261 	RETURN_TRUE;
2262 }
2263 /* }}} */
2264 
2265 /* {{{ proto string mysqli_sqlstate(object link)
2266    Returns the SQLSTATE error from previous MySQL operation */
2267 PHP_FUNCTION(mysqli_sqlstate)
2268 {
2269 	MY_MYSQL	*mysql;
2270 	zval		*mysql_link;
2271 	const char	*state;
2272 
2273 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
2274 		return;
2275 	}
2276 	MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
2277 	state = mysql_sqlstate(mysql->mysql);
2278 	if (state) {
2279 		RETURN_STRING(state, 1);
2280 	}
2281 }
2282 /* }}} */
2283 
2284 /* {{{ proto bool mysqli_ssl_set(object link ,string key ,string cert ,string ca ,string capath ,string cipher]) U
2285 */
2286 PHP_FUNCTION(mysqli_ssl_set)
2287 {
2288 	MY_MYSQL	*mysql;
2289 	zval		*mysql_link;
2290 	char		*ssl_parm[5];
2291 	int			ssl_parm_len[5], i;
2292 
2293 	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) {
2294 		return;
2295 	}
2296 	MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_INITIALIZED);
2297 
2298 	for (i = 0; i < 5; i++) {
2299 		if (!ssl_parm_len[i]) {
2300 			ssl_parm[i] = NULL;
2301 		}
2302 	}
2303 
2304 	mysql_ssl_set(mysql->mysql, ssl_parm[0], ssl_parm[1], ssl_parm[2], ssl_parm[3], ssl_parm[4]);
2305 
2306 	RETURN_TRUE;
2307 }
2308 /* }}} */
2309 
2310 /* {{{ proto mixed mysqli_stat(object link)
2311    Get current system status */
2312 PHP_FUNCTION(mysqli_stat)
2313 {
2314 	MY_MYSQL	*mysql;
2315 	zval		*mysql_link;
2316 	char		*stat;
2317 #if defined(MYSQLI_USE_MYSQLND)
2318 	uint		stat_len;
2319 #endif
2320 
2321 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
2322 		return;
2323 	}
2324 	MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
2325 
2326 #if !defined(MYSQLI_USE_MYSQLND)
2327 	if ((stat = (char *)mysql_stat(mysql->mysql)))
2328 	{
2329 		RETURN_STRING(stat, 1);
2330 #else
2331 	if (mysqlnd_stat(mysql->mysql, &stat, &stat_len) == PASS)
2332 	{
2333 		RETURN_STRINGL(stat, stat_len, 0);
2334 #endif
2335 	} else {
2336 		RETURN_FALSE;
2337 	}
2338 }
2339 
2340 /* }}} */
2341 
2342 /* {{{ proto bool mysqli_refresh(object link, long options)
2343    Flush tables or caches, or reset replication server information */
2344 PHP_FUNCTION(mysqli_refresh)
2345 {
2346 	MY_MYSQL *mysql;
2347 	zval *mysql_link = NULL;
2348 	long options;
2349 
2350 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol", &mysql_link, mysqli_link_class_entry, &options) == FAILURE) {
2351 		return;
2352 	}
2353 	MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_INITIALIZED);
2354 #ifdef MYSQLI_USE_MYSQLND
2355 	RETURN_BOOL(!mysql_refresh(mysql->mysql, (uint8_t) options));
2356 #else
2357 	RETURN_BOOL(!mysql_refresh(mysql->mysql, options));
2358 #endif
2359 }
2360 /* }}} */
2361 
2362 /* {{{ proto int mysqli_stmt_attr_set(object stmt, long attr, long mode)
2363 */
2364 PHP_FUNCTION(mysqli_stmt_attr_set)
2365 {
2366 	MY_STMT	*stmt;
2367 	zval	*mysql_stmt;
2368 	long	mode_in;
2369 #if MYSQL_VERSION_ID >= 50107
2370 	my_bool	mode_b;
2371 #endif
2372 	ulong	mode;
2373 	ulong	attr;
2374 	void	*mode_p;
2375 
2376 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oll", &mysql_stmt, mysqli_stmt_class_entry, &attr, &mode_in) == FAILURE) {
2377 		return;
2378 	}
2379 	MYSQLI_FETCH_RESOURCE_STMT(stmt, &mysql_stmt, MYSQLI_STATUS_VALID);
2380 
2381 	if (mode_in < 0) {
2382 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "mode should be non-negative, %ld passed", mode_in);
2383 		RETURN_FALSE;
2384 	}
2385 
2386 	switch (attr) {
2387 #if MYSQL_VERSION_ID >= 50107
2388 	case STMT_ATTR_UPDATE_MAX_LENGTH:
2389 		mode_b = (my_bool) mode_in;
2390 		mode_p = &mode_b;
2391 		break;
2392 #endif
2393 	default:
2394 		mode = mode_in;
2395 		mode_p = &mode;
2396 		break;
2397 	}
2398 #if !defined(MYSQLI_USE_MYSQLND)
2399 	if (mysql_stmt_attr_set(stmt->stmt, attr, mode_p)) {
2400 #else
2401 	if (FAIL == mysql_stmt_attr_set(stmt->stmt, attr, mode_p)) {
2402 #endif
2403 		RETURN_FALSE;
2404 	}
2405 	RETURN_TRUE;
2406 }
2407 /* }}} */
2408 
2409 /* {{{ proto int mysqli_stmt_attr_get(object stmt, long attr)
2410 */
2411 PHP_FUNCTION(mysqli_stmt_attr_get)
2412 {
2413 	MY_STMT	*stmt;
2414 	zval	*mysql_stmt;
2415 	ulong	value = 0;
2416 	ulong	attr;
2417 	int		rc;
2418 
2419 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol", &mysql_stmt, mysqli_stmt_class_entry, &attr) == FAILURE) {
2420 		return;
2421 	}
2422 	MYSQLI_FETCH_RESOURCE_STMT(stmt, &mysql_stmt, MYSQLI_STATUS_VALID);
2423 
2424 	if ((rc = mysql_stmt_attr_get(stmt->stmt, attr, &value))) {
2425 		RETURN_FALSE;
2426 	}
2427 
2428 #if MYSQL_VERSION_ID >= 50107
2429 	if (attr == STMT_ATTR_UPDATE_MAX_LENGTH)
2430 		value = *((my_bool *)&value);
2431 #endif
2432 	RETURN_LONG((long)value);
2433 }
2434 /* }}} */
2435 
2436 /* {{{ proto int mysqli_stmt_errno(object stmt)
2437 */
2438 PHP_FUNCTION(mysqli_stmt_errno)
2439 {
2440 	MY_STMT	*stmt;
2441 	zval	*mysql_stmt;
2442 
2443 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2444 		return;
2445 	}
2446 	MYSQLI_FETCH_RESOURCE_STMT(stmt, &mysql_stmt, MYSQLI_STATUS_INITIALIZED);
2447 
2448 	RETURN_LONG(mysql_stmt_errno(stmt->stmt));
2449 }
2450 /* }}} */
2451 
2452 /* {{{ proto string mysqli_stmt_error(object stmt)
2453 */
2454 PHP_FUNCTION(mysqli_stmt_error)
2455 {
2456 	MY_STMT	*stmt;
2457 	zval 	*mysql_stmt;
2458 	const char * err;
2459 
2460 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2461 		return;
2462 	}
2463 	MYSQLI_FETCH_RESOURCE_STMT(stmt, &mysql_stmt, MYSQLI_STATUS_INITIALIZED);
2464 
2465 	err = mysql_stmt_error(stmt->stmt);
2466 	if (err) {
2467 		RETURN_STRING(err, 1);
2468 	}
2469 }
2470 /* }}} */
2471 
2472 /* {{{ proto mixed mysqli_stmt_init(object link)
2473    Initialize statement object
2474 */
2475 PHP_FUNCTION(mysqli_stmt_init)
2476 {
2477 	MY_MYSQL		*mysql;
2478 	MY_STMT			*stmt;
2479 	zval			*mysql_link;
2480 	MYSQLI_RESOURCE	*mysqli_resource;
2481 
2482 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",&mysql_link, mysqli_link_class_entry) == FAILURE) {
2483 		return;
2484 	}
2485 	MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
2486 
2487 	stmt = (MY_STMT *)ecalloc(1,sizeof(MY_STMT));
2488 
2489 	if (!(stmt->stmt = mysql_stmt_init(mysql->mysql))) {
2490 		efree(stmt);
2491 		RETURN_FALSE;
2492 	}
2493 #ifndef MYSQLI_USE_MYSQLND
2494 	stmt->link_handle = Z_OBJ_HANDLE(*mysql_link);
2495 	zend_objects_store_add_ref_by_handle(stmt->link_handle TSRMLS_CC);
2496 #endif
2497 
2498 	mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
2499 	mysqli_resource->status = MYSQLI_STATUS_INITIALIZED;
2500 	mysqli_resource->ptr = (void *)stmt;
2501 	MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_stmt_class_entry);
2502 }
2503 /* }}} */
2504 
2505 /* {{{ proto bool mysqli_stmt_prepare(object stmt, string query)
2506    prepare server side statement with query
2507 */
2508 PHP_FUNCTION(mysqli_stmt_prepare)
2509 {
2510 	MY_STMT	*stmt;
2511 	zval 	*mysql_stmt;
2512 	char	*query;
2513 	int		query_len;
2514 
2515 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &mysql_stmt, mysqli_stmt_class_entry, &query, &query_len) == FAILURE) {
2516 		return;
2517 	}
2518 	MYSQLI_FETCH_RESOURCE_STMT(stmt, &mysql_stmt, MYSQLI_STATUS_INITIALIZED);
2519 
2520 	if (mysql_stmt_prepare(stmt->stmt, query, query_len)) {
2521 		MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
2522 		RETURN_FALSE;
2523 	}
2524 	/* change status */
2525 	MYSQLI_SET_STATUS(&mysql_stmt, MYSQLI_STATUS_VALID);
2526 	RETURN_TRUE;
2527 }
2528 /* }}} */
2529 
2530 /* {{{ proto mixed mysqli_stmt_result_metadata(object stmt)
2531    return result set from statement */
2532 PHP_FUNCTION(mysqli_stmt_result_metadata)
2533 {
2534 	MY_STMT			*stmt;
2535 	MYSQL_RES		*result;
2536 	zval			*mysql_stmt;
2537 	MYSQLI_RESOURCE	*mysqli_resource;
2538 
2539 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2540 		return;
2541 	}
2542 	MYSQLI_FETCH_RESOURCE_STMT(stmt, &mysql_stmt, MYSQLI_STATUS_VALID);
2543 
2544 	if (!(result = mysql_stmt_result_metadata(stmt->stmt))){
2545 		MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
2546 		RETURN_FALSE;
2547 	}
2548 
2549 	mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
2550 	mysqli_resource->ptr = (void *)result;
2551 	mysqli_resource->status = MYSQLI_STATUS_VALID;
2552 	MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_result_class_entry);
2553 }
2554 /* }}} */
2555 
2556 /* {{{ proto bool mysqli_stmt_store_result(stmt)
2557 */
2558 PHP_FUNCTION(mysqli_stmt_store_result)
2559 {
2560 	MY_STMT	*stmt;
2561 	zval	*mysql_stmt;
2562 
2563 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2564 		return;
2565 	}
2566 	MYSQLI_FETCH_RESOURCE_STMT(stmt, &mysql_stmt, MYSQLI_STATUS_VALID);
2567 
2568 #if !defined(MYSQLI_USE_MYSQLND)
2569 	{
2570 		/*
2571 		  If the user wants to store the data and we have BLOBs/TEXTs we try to allocate
2572 		  not the maximal length of the type (which is 16MB even for LONGBLOB) but
2573 		  the maximal length of the field in the result set. If he/she has quite big
2574 		  BLOB/TEXT columns after calling store_result() the memory usage of PHP will
2575 		  double - but this is a known problem of the simple MySQL API ;)
2576 		*/
2577 		int	i = 0;
2578 
2579 		for (i = mysql_stmt_field_count(stmt->stmt) - 1; i >=0; --i) {
2580 			if (stmt->stmt->fields && (stmt->stmt->fields[i].type == MYSQL_TYPE_BLOB ||
2581 				stmt->stmt->fields[i].type == MYSQL_TYPE_MEDIUM_BLOB ||
2582 				stmt->stmt->fields[i].type == MYSQL_TYPE_LONG_BLOB ||
2583 				stmt->stmt->fields[i].type == MYSQL_TYPE_GEOMETRY))
2584 			{
2585 #if MYSQL_VERSION_ID >= 50107
2586 				my_bool	tmp=1;
2587 #else
2588 				uint tmp=1;
2589 #endif
2590 				mysql_stmt_attr_set(stmt->stmt, STMT_ATTR_UPDATE_MAX_LENGTH, &tmp);
2591 				break;
2592 			}
2593 		}
2594 	}
2595 #endif
2596 
2597 	if (mysql_stmt_store_result(stmt->stmt)){
2598 		MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
2599 		RETURN_FALSE;
2600 	}
2601 	RETURN_TRUE;
2602 }
2603 /* }}} */
2604 
2605 /* {{{ proto string mysqli_stmt_sqlstate(object stmt)
2606 */
2607 PHP_FUNCTION(mysqli_stmt_sqlstate)
2608 {
2609 	MY_STMT	*stmt;
2610 	zval	*mysql_stmt;
2611 	const char * state;
2612 
2613 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
2614 		return;
2615 	}
2616 	MYSQLI_FETCH_RESOURCE_STMT(stmt, &mysql_stmt, MYSQLI_STATUS_VALID);
2617 
2618 	state = mysql_stmt_sqlstate(stmt->stmt);
2619 	if (state) {
2620 		RETURN_STRING(state, 1);
2621 	}
2622 }
2623 /* }}} */
2624 
2625 /* {{{ proto object mysqli_store_result(object link)
2626    Buffer result set on client */
2627 PHP_FUNCTION(mysqli_store_result)
2628 {
2629 	MY_MYSQL		*mysql;
2630 	MYSQL_RES		*result;
2631 	zval			*mysql_link;
2632 	MYSQLI_RESOURCE	*mysqli_resource;
2633 
2634 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
2635 		return;
2636 	}
2637 	MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
2638 
2639 	if (!(result = mysql_store_result(mysql->mysql))) {
2640 		MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
2641 		RETURN_FALSE;
2642 	}
2643 	if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
2644 		php_mysqli_report_index("from previous query", mysqli_server_status(mysql->mysql) TSRMLS_CC);
2645 	}
2646 
2647 	mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
2648 	mysqli_resource->ptr = (void *)result;
2649 	mysqli_resource->status = MYSQLI_STATUS_VALID;
2650 	MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_result_class_entry);
2651 }
2652 /* }}} */
2653 
2654 
2655 /* {{{ proto int mysqli_thread_id(object link)
2656    Return the current thread ID */
2657 PHP_FUNCTION(mysqli_thread_id)
2658 {
2659 	MY_MYSQL	*mysql;
2660 	zval		*mysql_link;
2661 
2662 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
2663 		return;
2664 	}
2665 	MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
2666 
2667 	RETURN_LONG((long) mysql_thread_id(mysql->mysql));
2668 }
2669 /* }}} */
2670 
2671 /* {{{ proto bool mysqli_thread_safe(void)
2672    Return whether thread safety is given or not */
2673 PHP_FUNCTION(mysqli_thread_safe)
2674 {
2675 	RETURN_BOOL(mysql_thread_safe());
2676 }
2677 /* }}} */
2678 
2679 /* {{{ proto mixed mysqli_use_result(object link)
2680    Directly retrieve query results - do not buffer results on client side */
2681 PHP_FUNCTION(mysqli_use_result)
2682 {
2683 	MY_MYSQL		*mysql;
2684 	MYSQL_RES		*result;
2685 	zval			*mysql_link;
2686 	MYSQLI_RESOURCE	*mysqli_resource;
2687 
2688 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
2689 		return;
2690 	}
2691 	MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
2692 
2693 	if (!(result = mysql_use_result(mysql->mysql))) {
2694 		MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
2695 		RETURN_FALSE;
2696 	}
2697 
2698 	if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
2699 		php_mysqli_report_index("from previous query", mysqli_server_status(mysql->mysql) TSRMLS_CC);
2700 	}
2701 	mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
2702 	mysqli_resource->ptr = (void *)result;
2703 	mysqli_resource->status = MYSQLI_STATUS_VALID;
2704 	MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_result_class_entry);
2705 }
2706 /* }}} */
2707 
2708 /* {{{ proto int mysqli_warning_count (object link)
2709    Return number of warnings from the last query for the given link */
2710 PHP_FUNCTION(mysqli_warning_count)
2711 {
2712 	MY_MYSQL	*mysql;
2713 	zval		*mysql_link;
2714 
2715 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
2716 		return;
2717 	}
2718 	MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
2719 
2720 	RETURN_LONG(mysql_warning_count(mysql->mysql));
2721 }
2722 /* }}} */
2723 
2724 /*
2725  * Local variables:
2726  * tab-width: 4
2727  * c-basic-offset: 4
2728  * End:
2729  * vim600: noet sw=4 ts=4 fdm=marker
2730  * vim<600: noet sw=4 ts=4
2731  */
2732