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