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