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