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