1 /*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | https://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Authors: Georg Richter <georg@php.net> |
14 | Andrey Hristov <andrey@php.net> |
15 | Ulf Wendel <uw@php.net> |
16 +----------------------------------------------------------------------+
17 */
18
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22
23 #include <signal.h>
24
25 #include "php.h"
26 #include "php_ini.h"
27 #include "php_globals.h"
28 #include "ext/standard/info.h"
29 #include "zend_smart_str.h"
30 #include "php_mysqli_structs.h"
31 #include "mysqli_priv.h"
32 #include "ext/mysqlnd/mysql_float_to_double.h"
33
34 #define ERROR_ARG_POS(arg_num) (getThis() ? (arg_num-1) : (arg_num))
35
36 /* {{{ Get number of affected rows in previous MySQL operation */
PHP_FUNCTION(mysqli_affected_rows)37 PHP_FUNCTION(mysqli_affected_rows)
38 {
39 MY_MYSQL *mysql;
40 zval *mysql_link;
41 my_ulonglong rc;
42
43 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
44 RETURN_THROWS();
45 }
46
47 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
48
49 rc = mysql_affected_rows(mysql->mysql);
50 if (rc == (my_ulonglong) -1) {
51 RETURN_LONG(-1);
52 }
53 MYSQLI_RETURN_LONG_INT(rc);
54 }
55 /* }}} */
56
57 /* {{{ Turn auto commit on or of */
PHP_FUNCTION(mysqli_autocommit)58 PHP_FUNCTION(mysqli_autocommit)
59 {
60 MY_MYSQL *mysql;
61 zval *mysql_link;
62 bool automode;
63
64 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ob", &mysql_link, mysqli_link_class_entry, &automode) == FAILURE) {
65 RETURN_THROWS();
66 }
67 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
68
69 if (mysql_autocommit(mysql->mysql, (my_bool)automode)) {
70 MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
71 RETURN_FALSE;
72 }
73 RETURN_TRUE;
74 }
75 /* }}} */
76
77 /* {{{ mysqli_stmt_bind_param_do_bind */
78 static
mysqli_stmt_bind_param_do_bind(MY_STMT * stmt,unsigned int num_vars,zval * args,const char * const types,unsigned int num_extra_args)79 int mysqli_stmt_bind_param_do_bind(MY_STMT *stmt, unsigned int num_vars, zval *args, const char * const types, unsigned int num_extra_args)
80 {
81 unsigned int i;
82 MYSQLND_PARAM_BIND *params;
83 enum_func_status ret = FAIL;
84
85 /* If no params -> skip binding and return directly */
86 if (num_vars == 0) {
87 return PASS;
88 }
89 params = mysqlnd_stmt_alloc_param_bind(stmt->stmt);
90 if (!params) {
91 goto end;
92 }
93 for (i = 0; i < num_vars; i++) {
94 zend_uchar type;
95 switch (types[i]) {
96 case 'd': /* Double */
97 type = MYSQL_TYPE_DOUBLE;
98 break;
99 case 'i': /* Integer */
100 #if SIZEOF_ZEND_LONG==8
101 type = MYSQL_TYPE_LONGLONG;
102 #elif SIZEOF_ZEND_LONG==4
103 type = MYSQL_TYPE_LONG;
104 #endif
105 break;
106 case 'b': /* Blob (send data) */
107 type = MYSQL_TYPE_LONG_BLOB;
108 break;
109 case 's': /* string */
110 type = MYSQL_TYPE_VAR_STRING;
111 break;
112 default:
113 zend_argument_value_error(num_extra_args, "must only contain the \"b\", \"d\", \"i\", \"s\" type specifiers");
114 ret = FAIL;
115 mysqlnd_stmt_free_param_bind(stmt->stmt, params);
116 goto end;
117 }
118 ZVAL_COPY_VALUE(¶ms[i].zv, &args[i]);
119 params[i].type = type;
120 }
121 ret = mysqlnd_stmt_bind_param(stmt->stmt, params);
122
123 end:
124 return ret;
125 }
126 /* }}} */
127
128 /* {{{ Bind variables to a prepared statement as parameters */
PHP_FUNCTION(mysqli_stmt_bind_param)129 PHP_FUNCTION(mysqli_stmt_bind_param)
130 {
131 zval *args;
132 int argc;
133 MY_STMT *stmt;
134 zval *mysql_stmt;
135 char *types;
136 size_t types_len;
137
138 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os*", &mysql_stmt, mysqli_stmt_class_entry, &types, &types_len, &args, &argc) == FAILURE) {
139 RETURN_THROWS();
140 }
141
142 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
143
144 if (!types_len) {
145 zend_argument_value_error(ERROR_ARG_POS(2), "cannot be empty");
146 RETURN_THROWS();
147 }
148
149 if (types_len != (size_t) argc) {
150 /* number of bind variables doesn't match number of elements in type definition string */
151 zend_argument_count_error("The number of elements in the type definition string must match the number of bind variables");
152 RETURN_THROWS();
153 }
154
155 if (types_len != mysql_stmt_param_count(stmt->stmt)) {
156 zend_argument_count_error("The number of variables must match the number of parameters in the prepared statement");
157 RETURN_THROWS();
158 }
159
160 RETVAL_BOOL(!mysqli_stmt_bind_param_do_bind(stmt, argc, args, types, getThis() ? 1 : 2));
161 MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
162 }
163 /* }}} */
164
165 /* {{{ mysqli_stmt_bind_result_do_bind */
166 static int
mysqli_stmt_bind_result_do_bind(MY_STMT * stmt,zval * args,unsigned int argc)167 mysqli_stmt_bind_result_do_bind(MY_STMT *stmt, zval *args, unsigned int argc)
168 {
169 unsigned int i;
170 MYSQLND_RESULT_BIND *params = mysqlnd_stmt_alloc_result_bind(stmt->stmt);
171 if (params) {
172 for (i = 0; i < argc; i++) {
173 ZVAL_COPY_VALUE(¶ms[i].zv, &args[i]);
174 }
175 return mysqlnd_stmt_bind_result(stmt->stmt, params);
176 }
177 return FAIL;
178 }
179 /* }}} */
180
181 /* {{{ Bind variables to a prepared statement for result storage */
PHP_FUNCTION(mysqli_stmt_bind_result)182 PHP_FUNCTION(mysqli_stmt_bind_result)
183 {
184 zval *args;
185 int argc;
186 zend_ulong rc;
187 MY_STMT *stmt;
188 zval *mysql_stmt;
189
190 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O+", &mysql_stmt, mysqli_stmt_class_entry, &args, &argc) == FAILURE) {
191 RETURN_THROWS();
192 }
193
194 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
195
196 if ((uint32_t)argc != mysql_stmt_field_count(stmt->stmt)) {
197 zend_argument_count_error("Number of bind variables doesn't match number of fields in prepared statement");
198 RETURN_THROWS();
199 }
200
201 rc = mysqli_stmt_bind_result_do_bind(stmt, args, argc);
202 RETURN_BOOL(!rc);
203 }
204 /* }}} */
205
206 /* {{{ Change logged-in user of the active connection */
PHP_FUNCTION(mysqli_change_user)207 PHP_FUNCTION(mysqli_change_user)
208 {
209 MY_MYSQL *mysql;
210 zval *mysql_link = NULL;
211 char *user, *password, *dbname;
212 size_t user_len, password_len, dbname_len;
213 zend_ulong rc;
214
215 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Osss!", &mysql_link, mysqli_link_class_entry, &user, &user_len, &password, &password_len, &dbname, &dbname_len) == FAILURE) {
216 RETURN_THROWS();
217 }
218 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
219
220 rc = mysqlnd_change_user_ex(mysql->mysql, user, password, dbname, false, (size_t) password_len);
221 MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
222
223 if (rc) {
224 RETURN_FALSE;
225 }
226
227 RETURN_TRUE;
228 }
229 /* }}} */
230
231 /* {{{ Returns the name of the character set used for this connection */
PHP_FUNCTION(mysqli_character_set_name)232 PHP_FUNCTION(mysqli_character_set_name)
233 {
234 MY_MYSQL *mysql;
235 zval *mysql_link;
236
237 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
238 RETURN_THROWS();
239 }
240
241 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
242 RETURN_STRING(mysql_character_set_name(mysql->mysql));
243 }
244 /* }}} */
245
246 /* {{{ php_mysqli_close */
php_mysqli_close(MY_MYSQL * mysql,int close_type,int resource_status)247 void php_mysqli_close(MY_MYSQL * mysql, int close_type, int resource_status)
248 {
249 if (resource_status > MYSQLI_STATUS_INITIALIZED) {
250 MyG(num_links)--;
251 }
252
253 if (!mysql->persistent) {
254 mysqli_close(mysql->mysql, close_type);
255 } else {
256 zend_resource *le;
257 if ((le = zend_hash_find_ptr(&EG(persistent_list), mysql->hash_key)) != NULL) {
258 if (le->type == php_le_pmysqli()) {
259 mysqli_plist_entry *plist = (mysqli_plist_entry *) le->ptr;
260 mysqlnd_end_psession(mysql->mysql);
261
262 if (MyG(rollback_on_cached_plink) &&
263 FAIL == mysqlnd_rollback(mysql->mysql, TRANS_COR_NO_OPT, NULL))
264 {
265 mysqli_close(mysql->mysql, close_type);
266 } else {
267 zend_ptr_stack_push(&plist->free_links, mysql->mysql);
268 MyG(num_inactive_persistent)++;
269 }
270 MyG(num_active_persistent)--;
271 }
272 }
273 mysql->persistent = false;
274 }
275 mysql->mysql = NULL;
276
277 php_clear_mysql(mysql);
278 }
279 /* }}} */
280
281 /* {{{ Close connection */
PHP_FUNCTION(mysqli_close)282 PHP_FUNCTION(mysqli_close)
283 {
284 zval *mysql_link;
285 MY_MYSQL *mysql;
286
287 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
288 RETURN_THROWS();
289 }
290
291 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_INITIALIZED);
292
293 php_mysqli_close(mysql, MYSQLI_CLOSE_EXPLICIT, ((MYSQLI_RESOURCE *)(Z_MYSQLI_P(mysql_link))->ptr)->status);
294 ((MYSQLI_RESOURCE *)(Z_MYSQLI_P(mysql_link))->ptr)->status = MYSQLI_STATUS_UNKNOWN;
295
296 MYSQLI_CLEAR_RESOURCE(mysql_link);
297 efree(mysql);
298 RETURN_TRUE;
299 }
300 /* }}} */
301
302 /* {{{ Commit outstanding actions and close transaction */
PHP_FUNCTION(mysqli_commit)303 PHP_FUNCTION(mysqli_commit)
304 {
305 MY_MYSQL *mysql;
306 zval *mysql_link;
307 zend_long flags = TRANS_COR_NO_OPT;
308 char * name = NULL;
309 size_t name_len;
310
311 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|ls!", &mysql_link, mysqli_link_class_entry, &flags, &name, &name_len) == FAILURE) {
312 RETURN_THROWS();
313 }
314 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
315
316 if (FAIL == mysqlnd_commit(mysql->mysql, flags, name)) {
317 MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
318 RETURN_FALSE;
319 }
320 RETURN_TRUE;
321 }
322 /* }}} */
323
324 /* {{{ Move internal result pointer */
PHP_FUNCTION(mysqli_data_seek)325 PHP_FUNCTION(mysqli_data_seek)
326 {
327 MYSQL_RES *result;
328 zval *mysql_result;
329 zend_long offset;
330
331 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &mysql_result, mysqli_result_class_entry, &offset) == FAILURE) {
332 RETURN_THROWS();
333 }
334
335 if (offset < 0) {
336 zend_argument_value_error(ERROR_ARG_POS(2), "must be greater than or equal to 0");
337 RETURN_THROWS();
338 }
339
340 MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
341
342 if (mysqli_result_is_unbuffered(result)) {
343 if (getThis()) {
344 zend_throw_error(NULL, "mysqli_result::data_seek() cannot be used in MYSQLI_USE_RESULT mode");
345 } else {
346 zend_throw_error(NULL, "mysqli_data_seek() cannot be used in MYSQLI_USE_RESULT mode");
347 }
348 RETURN_THROWS();
349 }
350
351 if ((uint64_t)offset >= mysql_num_rows(result)) {
352 RETURN_FALSE;
353 }
354
355 mysql_data_seek(result, offset);
356 RETURN_TRUE;
357 }
358 /* }}} */
359
360 /* {{{ */
PHP_FUNCTION(mysqli_debug)361 PHP_FUNCTION(mysqli_debug)
362 {
363 char *debug;
364 size_t debug_len;
365
366 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &debug, &debug_len) == FAILURE) {
367 RETURN_THROWS();
368 }
369
370 mysql_debug(debug);
371 RETURN_TRUE;
372 }
373 /* }}} */
374
375 /* {{{ */
PHP_FUNCTION(mysqli_dump_debug_info)376 PHP_FUNCTION(mysqli_dump_debug_info)
377 {
378 MY_MYSQL *mysql;
379 zval *mysql_link;
380
381 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
382 RETURN_THROWS();
383 }
384 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
385
386 RETURN_BOOL(!mysql_dump_debug_info(mysql->mysql));
387 }
388 /* }}} */
389
390 /* {{{ Returns the numerical value of the error message from previous MySQL operation */
PHP_FUNCTION(mysqli_errno)391 PHP_FUNCTION(mysqli_errno)
392 {
393 MY_MYSQL *mysql;
394 zval *mysql_link;
395
396 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
397 RETURN_THROWS();
398 }
399 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
400 RETURN_LONG(mysql_errno(mysql->mysql));
401 }
402 /* }}} */
403
404 /* {{{ Returns the text of the error message from previous MySQL operation */
PHP_FUNCTION(mysqli_error)405 PHP_FUNCTION(mysqli_error)
406 {
407 MY_MYSQL *mysql;
408 zval *mysql_link;
409
410 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
411 RETURN_THROWS();
412 }
413 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
414 RETURN_STRING(mysql_error(mysql->mysql));
415 }
416 /* }}} */
417
418 /* {{{ Execute a prepared statement */
PHP_FUNCTION(mysqli_stmt_execute)419 PHP_FUNCTION(mysqli_stmt_execute)
420 {
421 MY_STMT *stmt;
422 zval *mysql_stmt;
423 HashTable *input_params = NULL;
424
425 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|h!", &mysql_stmt, mysqli_stmt_class_entry, &input_params) == FAILURE) {
426 RETURN_THROWS();
427 }
428 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
429
430 // bind-in-execute
431 if (input_params) {
432 zval *tmp;
433 unsigned int index;
434 unsigned int hash_num_elements;
435 unsigned int param_count;
436 MYSQLND_PARAM_BIND *params;
437
438 if (!zend_array_is_list(input_params)) {
439 zend_argument_value_error(ERROR_ARG_POS(2), "must be a list array");
440 RETURN_THROWS();
441 }
442
443 hash_num_elements = zend_hash_num_elements(input_params);
444 param_count = mysql_stmt_param_count(stmt->stmt);
445 if (hash_num_elements != param_count) {
446 zend_argument_value_error(ERROR_ARG_POS(2), "must consist of exactly %d elements, %d present", param_count, hash_num_elements);
447 RETURN_THROWS();
448 }
449
450 params = mysqlnd_stmt_alloc_param_bind(stmt->stmt);
451 ZEND_ASSERT(params);
452
453 index = 0;
454 ZEND_HASH_FOREACH_VAL(input_params, tmp) {
455 ZVAL_COPY_VALUE(¶ms[index].zv, tmp);
456 params[index].type = MYSQL_TYPE_VAR_STRING;
457 index++;
458 } ZEND_HASH_FOREACH_END();
459
460 if (mysqlnd_stmt_bind_param(stmt->stmt, params)) {
461 MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
462 RETVAL_FALSE;
463 }
464 }
465
466 if (mysql_stmt_execute(stmt->stmt)) {
467 MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
468 RETVAL_FALSE;
469 } else {
470 RETVAL_TRUE;
471 }
472
473 if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
474 php_mysqli_report_index(stmt->query, mysqli_stmt_server_status(stmt->stmt));
475 }
476 }
477 /* }}} */
478
close_stmt_and_copy_errors(MY_STMT * stmt,MY_MYSQL * mysql)479 void close_stmt_and_copy_errors(MY_STMT *stmt, MY_MYSQL *mysql)
480 {
481 /* mysql_stmt_close() clears errors, so we have to store them temporarily */
482 MYSQLND_ERROR_INFO error_info = *stmt->stmt->data->error_info;
483 stmt->stmt->data->error_info->error_list.head = NULL;
484 stmt->stmt->data->error_info->error_list.tail = NULL;
485 stmt->stmt->data->error_info->error_list.count = 0;
486
487 /* we also remember affected_rows which gets cleared too */
488 uint64_t affected_rows = mysql->mysql->data->upsert_status->affected_rows;
489
490 mysqli_stmt_close(stmt->stmt, false);
491 stmt->stmt = NULL;
492 php_clear_stmt_bind(stmt);
493
494 /* restore error messages, but into the mysql object */
495 zend_llist_clean(&mysql->mysql->data->error_info->error_list);
496 *mysql->mysql->data->error_info = error_info;
497 mysql->mysql->data->upsert_status->affected_rows = affected_rows;
498 }
499
PHP_FUNCTION(mysqli_execute_query)500 PHP_FUNCTION(mysqli_execute_query)
501 {
502 MY_MYSQL *mysql;
503 MY_STMT *stmt;
504 char *query = NULL;
505 size_t query_len;
506 zval *mysql_link;
507 HashTable *input_params = NULL;
508 MYSQL_RES *result;
509 MYSQLI_RESOURCE *mysqli_resource;
510
511 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os|h!", &mysql_link, mysqli_link_class_entry, &query, &query_len, &input_params) == FAILURE) {
512 RETURN_THROWS();
513 }
514 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
515
516 stmt = (MY_STMT *)ecalloc(1,sizeof(MY_STMT));
517
518 if (!(stmt->stmt = mysql_stmt_init(mysql->mysql))) {
519 MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
520 efree(stmt);
521 RETURN_FALSE;
522 }
523
524 if (FAIL == mysql_stmt_prepare(stmt->stmt, query, query_len)) {
525 MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
526
527 close_stmt_and_copy_errors(stmt, mysql);
528 RETURN_FALSE;
529 }
530
531 /* The bit below, which is copied from mysqli_prepare, is needed for bad index exceptions */
532 /* don't initialize stmt->query with NULL, we ecalloc()-ed the memory */
533 /* Get performance boost if reporting is switched off */
534 if (query_len && (MyG(report_mode) & MYSQLI_REPORT_INDEX)) {
535 stmt->query = estrdup(query);
536 }
537
538 // bind-in-execute
539 // It's very similar to the mysqli_stmt::execute, but it uses different error handling
540 if (input_params) {
541 zval *tmp;
542 unsigned int index;
543 unsigned int hash_num_elements;
544 unsigned int param_count;
545 MYSQLND_PARAM_BIND *params;
546
547 if (!zend_array_is_list(input_params)) {
548 mysqli_stmt_close(stmt->stmt, false);
549 stmt->stmt = NULL;
550 efree(stmt);
551 zend_argument_value_error(ERROR_ARG_POS(3), "must be a list array");
552 RETURN_THROWS();
553 }
554
555 hash_num_elements = zend_hash_num_elements(input_params);
556 param_count = mysql_stmt_param_count(stmt->stmt);
557 if (hash_num_elements != param_count) {
558 mysqli_stmt_close(stmt->stmt, false);
559 stmt->stmt = NULL;
560 efree(stmt);
561 zend_argument_value_error(ERROR_ARG_POS(3), "must consist of exactly %d elements, %d present", param_count, hash_num_elements);
562 RETURN_THROWS();
563 }
564
565 params = mysqlnd_stmt_alloc_param_bind(stmt->stmt);
566 ZEND_ASSERT(params);
567
568 index = 0;
569 ZEND_HASH_FOREACH_VAL(input_params, tmp) {
570 ZVAL_COPY_VALUE(¶ms[index].zv, tmp);
571 params[index].type = MYSQL_TYPE_VAR_STRING;
572 index++;
573 } ZEND_HASH_FOREACH_END();
574
575 if (mysqlnd_stmt_bind_param(stmt->stmt, params)) {
576 close_stmt_and_copy_errors(stmt, mysql);
577 RETURN_FALSE;
578 }
579
580 }
581
582 if (mysql_stmt_execute(stmt->stmt)) {
583 MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
584
585 if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
586 php_mysqli_report_index(stmt->query, mysqli_stmt_server_status(stmt->stmt));
587 }
588
589 close_stmt_and_copy_errors(stmt, mysql);
590 RETURN_FALSE;
591 }
592
593 if (!mysql_stmt_field_count(stmt->stmt)) {
594 /* no result set - not a SELECT */
595 close_stmt_and_copy_errors(stmt, mysql);
596 RETURN_TRUE;
597 }
598
599 if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
600 php_mysqli_report_index(stmt->query, mysqli_stmt_server_status(stmt->stmt));
601 }
602
603 /* get result */
604 if (!(result = mysqlnd_stmt_get_result(stmt->stmt))) {
605 MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
606
607 close_stmt_and_copy_errors(stmt, mysql);
608 RETURN_FALSE;
609 }
610
611 mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
612 mysqli_resource->ptr = (void *)result;
613 mysqli_resource->status = MYSQLI_STATUS_VALID;
614 MYSQLI_RETVAL_RESOURCE(mysqli_resource, mysqli_result_class_entry);
615
616 close_stmt_and_copy_errors(stmt, mysql);
617 }
618
619 /* {{{ mixed mysqli_stmt_fetch_mysqlnd */
mysqli_stmt_fetch_mysqlnd(INTERNAL_FUNCTION_PARAMETERS)620 void mysqli_stmt_fetch_mysqlnd(INTERNAL_FUNCTION_PARAMETERS)
621 {
622 MY_STMT *stmt;
623 zval *mysql_stmt;
624 bool fetched_anything;
625
626 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
627 RETURN_THROWS();
628 }
629 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
630
631 if (FAIL == mysqlnd_stmt_fetch(stmt->stmt, &fetched_anything)) {
632 MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
633 RETURN_FALSE;
634 } else if (fetched_anything) {
635 RETURN_TRUE;
636 } else {
637 RETURN_NULL();
638 }
639 }
640 /* }}} */
641
642 /* {{{ Fetch results from a prepared statement into the bound variables */
PHP_FUNCTION(mysqli_stmt_fetch)643 PHP_FUNCTION(mysqli_stmt_fetch)
644 {
645 mysqli_stmt_fetch_mysqlnd(INTERNAL_FUNCTION_PARAM_PASSTHRU);
646 }
647 /* }}} */
648
649 /* {{{ php_add_field_properties */
php_add_field_properties(zval * value,const MYSQL_FIELD * field)650 static void php_add_field_properties(zval *value, const MYSQL_FIELD *field)
651 {
652 add_property_str(value, "name", zend_string_copy(field->sname));
653
654 add_property_stringl(value, "orgname", (field->org_name ? field->org_name : ""), field->org_name_length);
655 add_property_stringl(value, "table", (field->table ? field->table : ""), field->table_length);
656 add_property_stringl(value, "orgtable", (field->org_table ? field->org_table : ""), field->org_table_length);
657 add_property_stringl(value, "def", (field->def ? field->def : ""), field->def_length);
658 add_property_stringl(value, "db", (field->db ? field->db : ""), field->db_length);
659
660 /* FIXME: manually set the catalog to "def" due to bug in
661 * libmysqlclient which does not initialize field->catalog
662 * and in addition, the catalog is always be "def"
663 */
664 add_property_string(value, "catalog", "def");
665
666 add_property_long(value, "max_length", 0);
667 add_property_long(value, "length", field->length);
668 add_property_long(value, "charsetnr", field->charsetnr);
669 add_property_long(value, "flags", field->flags);
670 add_property_long(value, "type", field->type);
671 add_property_long(value, "decimals", field->decimals);
672 }
673 /* }}} */
674
675 /* {{{ Get column information from a result and return as an object */
PHP_FUNCTION(mysqli_fetch_field)676 PHP_FUNCTION(mysqli_fetch_field)
677 {
678 MYSQL_RES *result;
679 zval *mysql_result;
680 const MYSQL_FIELD *field;
681
682 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
683 RETURN_THROWS();
684 }
685
686 MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
687
688 if (!(field = mysql_fetch_field(result))) {
689 RETURN_FALSE;
690 }
691
692 object_init(return_value);
693 php_add_field_properties(return_value, field);
694 }
695 /* }}} */
696
697 /* {{{ Return array of objects containing field meta-data */
PHP_FUNCTION(mysqli_fetch_fields)698 PHP_FUNCTION(mysqli_fetch_fields)
699 {
700 MYSQL_RES *result;
701 zval *mysql_result;
702 zval obj;
703
704 unsigned int i, num_fields;
705
706 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
707 RETURN_THROWS();
708 }
709
710 MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
711
712 array_init(return_value);
713 num_fields = mysql_num_fields(result);
714
715 for (i = 0; i < num_fields; i++) {
716 const MYSQL_FIELD *field = mysql_fetch_field_direct(result, i);
717
718 object_init(&obj);
719
720 php_add_field_properties(&obj, field);
721 add_index_zval(return_value, i, &obj);
722 }
723 }
724 /* }}} */
725
726 /* {{{ Fetch meta-data for a single field */
PHP_FUNCTION(mysqli_fetch_field_direct)727 PHP_FUNCTION(mysqli_fetch_field_direct)
728 {
729 MYSQL_RES *result;
730 zval *mysql_result;
731 const MYSQL_FIELD *field;
732 zend_long offset;
733
734 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &mysql_result, mysqli_result_class_entry, &offset) == FAILURE) {
735 RETURN_THROWS();
736 }
737
738 if (offset < 0) {
739 zend_argument_value_error(ERROR_ARG_POS(2), "must be greater than or equal to 0");
740 RETURN_THROWS();
741 }
742
743 MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
744
745 if (offset >= (zend_long) mysql_num_fields(result)) {
746 zend_argument_value_error(ERROR_ARG_POS(2), "must be less than the number of fields for this result set");
747 RETURN_THROWS();
748 }
749
750 if (!(field = mysql_fetch_field_direct(result,offset))) {
751 RETURN_FALSE;
752 }
753
754 object_init(return_value);
755 php_add_field_properties(return_value, field);
756 }
757 /* }}} */
758
759 /* {{{ Get the length of each output in a result */
PHP_FUNCTION(mysqli_fetch_lengths)760 PHP_FUNCTION(mysqli_fetch_lengths)
761 {
762 MYSQL_RES *result;
763 zval *mysql_result;
764 unsigned int i, num_fields;
765 const size_t *ret;
766
767 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
768 RETURN_THROWS();
769 }
770
771 MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
772
773 // TODO Warning?
774 if (!(ret = mysql_fetch_lengths(result))) {
775 RETURN_FALSE;
776 }
777
778 array_init(return_value);
779 num_fields = mysql_num_fields(result);
780
781 for (i = 0; i < num_fields; i++) {
782 add_index_long(return_value, i, ret[i]);
783 }
784 }
785 /* }}} */
786
787 /* {{{ Get a result row as an enumerated array */
PHP_FUNCTION(mysqli_fetch_row)788 PHP_FUNCTION(mysqli_fetch_row)
789 {
790 php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, MYSQLI_NUM, 0);
791 }
792 /* }}} */
793
794 /* {{{ Fetch the number of fields returned by the last query for the given link */
PHP_FUNCTION(mysqli_field_count)795 PHP_FUNCTION(mysqli_field_count)
796 {
797 MY_MYSQL *mysql;
798 zval *mysql_link;
799
800 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
801 RETURN_THROWS();
802 }
803 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
804
805 RETURN_LONG(mysql_field_count(mysql->mysql));
806 }
807 /* }}} */
808
809 /* {{{ Set result pointer to a specified field offset */
PHP_FUNCTION(mysqli_field_seek)810 PHP_FUNCTION(mysqli_field_seek)
811 {
812 MYSQL_RES *result;
813 zval *mysql_result;
814 zend_long fieldnr;
815
816 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &mysql_result, mysqli_result_class_entry, &fieldnr) == FAILURE) {
817 RETURN_THROWS();
818 }
819
820 if (fieldnr < 0) {
821 zend_argument_value_error(ERROR_ARG_POS(2), "must be greater than or equal to 0");
822 RETURN_THROWS();
823 }
824
825 MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
826
827 if ((uint32_t)fieldnr >= mysql_num_fields(result)) {
828 zend_argument_value_error(ERROR_ARG_POS(2), "must be less than the number of fields for this result set");
829 RETURN_THROWS();
830 }
831
832 mysql_field_seek(result, fieldnr);
833 RETURN_TRUE;
834 }
835 /* }}} */
836
837 /* {{{ Get current field offset of result pointer */
PHP_FUNCTION(mysqli_field_tell)838 PHP_FUNCTION(mysqli_field_tell)
839 {
840 MYSQL_RES *result;
841 zval *mysql_result;
842
843 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
844 RETURN_THROWS();
845 }
846 MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
847
848 RETURN_LONG(mysql_field_tell(result));
849 }
850 /* }}} */
851
852 /* {{{ Free query result memory for the given result handle */
PHP_FUNCTION(mysqli_free_result)853 PHP_FUNCTION(mysqli_free_result)
854 {
855 MYSQL_RES *result;
856 zval *mysql_result;
857
858 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
859 RETURN_THROWS();
860 }
861 MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
862
863 mysqli_free_result(result, false);
864 MYSQLI_CLEAR_RESOURCE(mysql_result);
865 }
866 /* }}} */
867
868 /* {{{ Get MySQL client info */
PHP_FUNCTION(mysqli_get_client_info)869 PHP_FUNCTION(mysqli_get_client_info)
870 {
871 if (getThis()) {
872 if (zend_parse_parameters_none() == FAILURE) {
873 RETURN_THROWS();
874 }
875 } else {
876 zval *mysql_link;
877
878 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|O!", &mysql_link, mysqli_link_class_entry) == FAILURE) {
879 RETURN_THROWS();
880 }
881
882 if (ZEND_NUM_ARGS()) {
883 php_error_docref(NULL, E_DEPRECATED, "Passing connection object as an argument is deprecated");
884 }
885 }
886
887 RETURN_STRING(mysql_get_client_info());
888 }
889 /* }}} */
890
891 /* {{{ Get MySQL client info */
PHP_FUNCTION(mysqli_get_client_version)892 PHP_FUNCTION(mysqli_get_client_version)
893 {
894 if (zend_parse_parameters_none() == FAILURE) {
895 RETURN_THROWS();
896 }
897
898 RETURN_LONG((zend_long)mysql_get_client_version());
899 }
900 /* }}} */
901
902 /* {{{ Get MySQL host info */
PHP_FUNCTION(mysqli_get_host_info)903 PHP_FUNCTION(mysqli_get_host_info)
904 {
905 MY_MYSQL *mysql;
906 zval *mysql_link = NULL;
907
908 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
909 RETURN_THROWS();
910 }
911 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
912 RETURN_STRING((mysql->mysql->data->host_info) ? mysql->mysql->data->host_info : "");
913 }
914 /* }}} */
915
916 /* {{{ Get MySQL protocol information */
PHP_FUNCTION(mysqli_get_proto_info)917 PHP_FUNCTION(mysqli_get_proto_info)
918 {
919 MY_MYSQL *mysql;
920 zval *mysql_link = NULL;
921
922 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
923 RETURN_THROWS();
924 }
925 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
926 RETURN_LONG(mysql_get_proto_info(mysql->mysql));
927 }
928 /* }}} */
929
930 /* {{{ Get MySQL server info */
PHP_FUNCTION(mysqli_get_server_info)931 PHP_FUNCTION(mysqli_get_server_info)
932 {
933 MY_MYSQL *mysql;
934 zval *mysql_link = NULL;
935
936 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
937 RETURN_THROWS();
938 }
939 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
940
941 RETURN_STRING(mysql_get_server_info(mysql->mysql));
942 }
943 /* }}} */
944
945 /* {{{ Return the MySQL version for the server referenced by the given link */
PHP_FUNCTION(mysqli_get_server_version)946 PHP_FUNCTION(mysqli_get_server_version)
947 {
948 MY_MYSQL *mysql;
949 zval *mysql_link = NULL;
950
951 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
952 RETURN_THROWS();
953 }
954 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
955
956 RETURN_LONG(mysql_get_server_version(mysql->mysql));
957 }
958 /* }}} */
959
960 /* {{{ Get information about the most recent query */
PHP_FUNCTION(mysqli_info)961 PHP_FUNCTION(mysqli_info)
962 {
963 MY_MYSQL *mysql;
964 zval *mysql_link = NULL;
965 const char *info;
966
967 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
968 RETURN_THROWS();
969 }
970 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
971
972 info = mysql_info(mysql->mysql);
973 if (info) {
974 RETURN_STRING(info);
975 }
976 }
977 /* }}} */
978
979 /* {{{ php_mysqli_init() */
php_mysqli_init(INTERNAL_FUNCTION_PARAMETERS,bool is_method)980 void php_mysqli_init(INTERNAL_FUNCTION_PARAMETERS, bool is_method)
981 {
982 MYSQLI_RESOURCE *mysqli_resource;
983 MY_MYSQL *mysql;
984
985 if (zend_parse_parameters_none() == FAILURE) {
986 RETURN_THROWS();
987 }
988
989 if (is_method && (Z_MYSQLI_P(getThis()))->ptr) {
990 return;
991 }
992
993 mysql = (MY_MYSQL *)ecalloc(1, sizeof(MY_MYSQL));
994
995 /*
996 We create always persistent, as if the user want to connect
997 to p:somehost, we can't convert the handle then
998 */
999 if (!(mysql->mysql = mysqlnd_init(MYSQLND_CLIENT_NO_FLAG, true)))
1000 {
1001 efree(mysql);
1002 RETURN_FALSE;
1003 }
1004
1005 mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
1006 mysqli_resource->ptr = (void *)mysql;
1007 mysqli_resource->status = MYSQLI_STATUS_INITIALIZED;
1008
1009 if (!is_method) {
1010 MYSQLI_RETVAL_RESOURCE(mysqli_resource, mysqli_link_class_entry);
1011 } else {
1012 (Z_MYSQLI_P(getThis()))->ptr = mysqli_resource;
1013 }
1014 }
1015 /* }}} */
1016
1017 /* {{{ Initialize mysqli and return a resource for use with mysql_real_connect */
PHP_FUNCTION(mysqli_init)1018 PHP_FUNCTION(mysqli_init)
1019 {
1020 php_mysqli_init(INTERNAL_FUNCTION_PARAM_PASSTHRU, false);
1021 }
1022 /* }}} */
1023
1024 /* {{{ Get the ID generated from the previous INSERT operation */
PHP_FUNCTION(mysqli_insert_id)1025 PHP_FUNCTION(mysqli_insert_id)
1026 {
1027 MY_MYSQL *mysql;
1028 my_ulonglong rc;
1029 zval *mysql_link;
1030
1031 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1032 RETURN_THROWS();
1033 }
1034 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1035 rc = mysql_insert_id(mysql->mysql);
1036 MYSQLI_RETURN_LONG_INT(rc)
1037 }
1038 /* }}} */
1039
1040 /* {{{ Kill a mysql process on the server */
PHP_FUNCTION(mysqli_kill)1041 PHP_FUNCTION(mysqli_kill)
1042 {
1043 MY_MYSQL *mysql;
1044 zval *mysql_link;
1045 zend_long processid;
1046
1047 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &mysql_link, mysqli_link_class_entry, &processid) == FAILURE) {
1048 RETURN_THROWS();
1049 }
1050
1051 if (processid <= 0) {
1052 zend_argument_value_error(ERROR_ARG_POS(2), "must be greater than 0");
1053 RETURN_THROWS();
1054 }
1055
1056 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1057
1058 if (mysql_kill(mysql->mysql, processid)) {
1059 MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
1060 RETURN_FALSE;
1061 }
1062 RETURN_TRUE;
1063 }
1064 /* }}} */
1065
1066 /* {{{ check if there any more query results from a multi query */
PHP_FUNCTION(mysqli_more_results)1067 PHP_FUNCTION(mysqli_more_results)
1068 {
1069 MY_MYSQL *mysql;
1070 zval *mysql_link;
1071
1072 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1073 RETURN_THROWS();
1074 }
1075 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1076
1077 RETURN_BOOL(mysql_more_results(mysql->mysql));
1078 }
1079 /* }}} */
1080
1081 /* {{{ read next result from multi_query */
PHP_FUNCTION(mysqli_next_result)1082 PHP_FUNCTION(mysqli_next_result) {
1083 MY_MYSQL *mysql;
1084 zval *mysql_link;
1085
1086 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1087 RETURN_THROWS();
1088 }
1089 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1090
1091 if (mysql_next_result(mysql->mysql)) {
1092 MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
1093 RETURN_FALSE;
1094 }
1095 RETURN_TRUE;
1096 }
1097 /* }}} */
1098
1099
1100 /* {{{ check if there any more query results from a multi query */
PHP_FUNCTION(mysqli_stmt_more_results)1101 PHP_FUNCTION(mysqli_stmt_more_results)
1102 {
1103 MY_STMT *stmt;
1104 zval *mysql_stmt;
1105
1106 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
1107 RETURN_THROWS();
1108 }
1109 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
1110
1111 RETURN_BOOL(mysqlnd_stmt_more_results(stmt->stmt));
1112 }
1113 /* }}} */
1114
1115 /* {{{ read next result from multi_query */
PHP_FUNCTION(mysqli_stmt_next_result)1116 PHP_FUNCTION(mysqli_stmt_next_result) {
1117 MY_STMT *stmt;
1118 zval *mysql_stmt;
1119
1120 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
1121 RETURN_THROWS();
1122 }
1123 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
1124
1125 if (mysql_stmt_next_result(stmt->stmt)) {
1126 MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
1127 RETURN_FALSE;
1128 }
1129 RETURN_TRUE;
1130 }
1131 /* }}} */
1132
1133 /* {{{ Get number of fields in result */
PHP_FUNCTION(mysqli_num_fields)1134 PHP_FUNCTION(mysqli_num_fields)
1135 {
1136 MYSQL_RES *result;
1137 zval *mysql_result;
1138
1139 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
1140 RETURN_THROWS();
1141 }
1142 MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1143
1144 RETURN_LONG(mysql_num_fields(result));
1145 }
1146 /* }}} */
1147
1148 /* {{{ Get number of rows in result */
PHP_FUNCTION(mysqli_num_rows)1149 PHP_FUNCTION(mysqli_num_rows)
1150 {
1151 MYSQL_RES *result;
1152 zval *mysql_result;
1153
1154 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
1155 RETURN_THROWS();
1156 }
1157 MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID);
1158
1159 if (mysqli_result_is_unbuffered_and_not_everything_is_fetched(result)) {
1160 zend_throw_error(NULL, "mysqli_num_rows() cannot be used in MYSQLI_USE_RESULT mode");
1161 RETURN_THROWS();
1162 }
1163
1164 MYSQLI_RETURN_LONG_INT(mysql_num_rows(result));
1165 }
1166 /* }}} */
1167
1168 /* {{{ mysqli_options_get_option_zval_type */
mysqli_options_get_option_zval_type(int option)1169 static int mysqli_options_get_option_zval_type(int option)
1170 {
1171 switch (option) {
1172 case MYSQLND_OPT_NET_CMD_BUFFER_SIZE:
1173 case MYSQLND_OPT_NET_READ_BUFFER_SIZE:
1174 case MYSQLND_OPT_INT_AND_FLOAT_NATIVE:
1175 case MYSQL_OPT_CONNECT_TIMEOUT:
1176 #ifdef MYSQL_REPORT_DATA_TRUNCATION
1177 case MYSQL_REPORT_DATA_TRUNCATION:
1178 #endif
1179 case MYSQL_OPT_LOCAL_INFILE:
1180 case MYSQL_OPT_NAMED_PIPE:
1181 #ifdef MYSQL_OPT_PROTOCOL
1182 case MYSQL_OPT_PROTOCOL:
1183 #endif /* MySQL 4.1.0 */
1184 case MYSQL_OPT_READ_TIMEOUT:
1185 case MYSQL_OPT_WRITE_TIMEOUT:
1186 #ifdef MYSQL_OPT_GUESS_CONNECTION /* removed in MySQL-8.0 */
1187 case MYSQL_OPT_GUESS_CONNECTION:
1188 case MYSQL_OPT_USE_EMBEDDED_CONNECTION:
1189 case MYSQL_OPT_USE_REMOTE_CONNECTION:
1190 case MYSQL_SECURE_AUTH:
1191 #endif
1192 #ifdef MYSQL_OPT_RECONNECT
1193 case MYSQL_OPT_RECONNECT:
1194 #endif /* MySQL 5.0.13 */
1195 #ifdef MYSQL_OPT_SSL_VERIFY_SERVER_CERT
1196 case MYSQL_OPT_SSL_VERIFY_SERVER_CERT:
1197 #endif /* MySQL 5.0.23 */
1198 #ifdef MYSQL_OPT_COMPRESS
1199 case MYSQL_OPT_COMPRESS:
1200 #endif /* mysqlnd @ PHP 5.3.2 */
1201 case MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS:
1202 return IS_LONG;
1203
1204 #ifdef MYSQL_SHARED_MEMORY_BASE_NAME
1205 case MYSQL_SHARED_MEMORY_BASE_NAME:
1206 #endif /* MySQL 4.1.0 */
1207 #ifdef MYSQL_SET_CLIENT_IP
1208 case MYSQL_SET_CLIENT_IP:
1209 #endif /* MySQL 4.1.1 */
1210 case MYSQL_READ_DEFAULT_FILE:
1211 case MYSQL_READ_DEFAULT_GROUP:
1212 case MYSQL_INIT_COMMAND:
1213 case MYSQL_SET_CHARSET_NAME:
1214 case MYSQL_SET_CHARSET_DIR:
1215 case MYSQL_SERVER_PUBLIC_KEY:
1216 case MYSQL_OPT_LOAD_DATA_LOCAL_DIR:
1217 return IS_STRING;
1218
1219 default:
1220 return IS_NULL;
1221 }
1222 }
1223 /* }}} */
1224
1225 /* {{{ Set options */
PHP_FUNCTION(mysqli_options)1226 PHP_FUNCTION(mysqli_options)
1227 {
1228 MY_MYSQL *mysql;
1229 zval *mysql_link = NULL;
1230 zval *mysql_value;
1231 zend_long mysql_option;
1232 unsigned int l_value;
1233 zend_long ret;
1234 int expected_type;
1235
1236 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Olz", &mysql_link, mysqli_link_class_entry, &mysql_option, &mysql_value) == FAILURE) {
1237 RETURN_THROWS();
1238 }
1239 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_INITIALIZED);
1240
1241 expected_type = mysqli_options_get_option_zval_type(mysql_option);
1242 if (expected_type != Z_TYPE_P(mysql_value)) {
1243 switch (expected_type) {
1244 case IS_STRING:
1245 if (!try_convert_to_string(mysql_value)) {
1246 RETURN_THROWS();
1247 }
1248 break;
1249 case IS_LONG:
1250 convert_to_long(mysql_value);
1251 break;
1252 default:
1253 break;
1254 }
1255 }
1256 switch (expected_type) {
1257 case IS_STRING:
1258 if ((ret = mysql_options(mysql->mysql, mysql_option, Z_STRVAL_P(mysql_value)))) {
1259 MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
1260 }
1261 break;
1262 case IS_LONG:
1263 l_value = Z_LVAL_P(mysql_value);
1264 if ((ret = mysql_options(mysql->mysql, mysql_option, (char *)&l_value))) {
1265 MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
1266 }
1267 break;
1268 default:
1269 ret = 1;
1270 break;
1271 }
1272
1273 RETURN_BOOL(!ret);
1274 }
1275 /* }}} */
1276
1277 /* {{{ Ping a server connection or reconnect if there is no connection */
PHP_FUNCTION(mysqli_ping)1278 PHP_FUNCTION(mysqli_ping)
1279 {
1280 MY_MYSQL *mysql;
1281 zval *mysql_link;
1282 zend_long rc;
1283
1284 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1285 RETURN_THROWS();
1286 }
1287 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1288 rc = mysql_ping(mysql->mysql);
1289 MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
1290
1291 RETURN_BOOL(!rc);
1292 }
1293 /* }}} */
1294
1295 /* {{{ Prepare a SQL statement for execution */
PHP_FUNCTION(mysqli_prepare)1296 PHP_FUNCTION(mysqli_prepare)
1297 {
1298 MY_MYSQL *mysql;
1299 MY_STMT *stmt;
1300 char *query = NULL;
1301 size_t query_len;
1302 zval *mysql_link;
1303 MYSQLI_RESOURCE *mysqli_resource;
1304
1305 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os",&mysql_link, mysqli_link_class_entry, &query, &query_len) == FAILURE) {
1306 RETURN_THROWS();
1307 }
1308 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1309
1310 stmt = (MY_STMT *)ecalloc(1,sizeof(MY_STMT));
1311
1312 if ((stmt->stmt = mysql_stmt_init(mysql->mysql))) {
1313 if (mysql_stmt_prepare(stmt->stmt, query, query_len)) {
1314 /* mysql_stmt_close() clears errors, so we have to store them temporarily */
1315 MYSQLND_ERROR_INFO error_info = *mysql->mysql->data->error_info;
1316 mysql->mysql->data->error_info->error_list.head = NULL;
1317 mysql->mysql->data->error_info->error_list.tail = NULL;
1318 mysql->mysql->data->error_info->error_list.count = 0;
1319 mysqli_stmt_close(stmt->stmt, false);
1320 stmt->stmt = NULL;
1321
1322 /* restore error messages */
1323 zend_llist_clean(&mysql->mysql->data->error_info->error_list);
1324 *mysql->mysql->data->error_info = error_info;
1325 }
1326 }
1327
1328 /* don't initialize stmt->query with NULL, we ecalloc()-ed the memory */
1329 /* Get performance boost if reporting is switched off */
1330 if (stmt->stmt && query_len && (MyG(report_mode) & MYSQLI_REPORT_INDEX)) {
1331 stmt->query = estrdup(query);
1332 }
1333
1334 /* don't join to the previous if because it won't work if mysql_stmt_prepare_fails */
1335 if (!stmt->stmt) {
1336 MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
1337 efree(stmt);
1338 RETURN_FALSE;
1339 }
1340
1341 mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
1342 mysqli_resource->ptr = (void *)stmt;
1343
1344 /* change status */
1345 mysqli_resource->status = MYSQLI_STATUS_VALID;
1346 MYSQLI_RETVAL_RESOURCE(mysqli_resource, mysqli_stmt_class_entry);
1347 }
1348 /* }}} */
1349
1350 /* {{{ Open a connection to a mysql server */
PHP_FUNCTION(mysqli_real_connect)1351 PHP_FUNCTION(mysqli_real_connect)
1352 {
1353 mysqli_common_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, true, false);
1354 }
1355 /* }}} */
1356
1357 /* {{{ Binary-safe version of mysql_query() */
PHP_FUNCTION(mysqli_real_query)1358 PHP_FUNCTION(mysqli_real_query)
1359 {
1360 MY_MYSQL *mysql;
1361 zval *mysql_link;
1362 char *query = NULL;
1363 size_t query_len;
1364
1365 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &mysql_link, mysqli_link_class_entry, &query, &query_len) == FAILURE) {
1366 RETURN_THROWS();
1367 }
1368 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1369
1370 MYSQLI_DISABLE_MQ; /* disable multi statements/queries */
1371
1372 if (mysql_real_query(mysql->mysql, query, query_len)) {
1373 MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
1374 RETURN_FALSE;
1375 }
1376
1377 if (!mysql_field_count(mysql->mysql)) {
1378 if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
1379 php_mysqli_report_index(query, mysqli_server_status(mysql->mysql));
1380 }
1381 }
1382
1383 RETURN_TRUE;
1384 }
1385 /* }}} */
1386
1387 # define mysql_real_escape_string_quote(mysql, to, from, length, quote) \
1388 mysql_real_escape_string(mysql, to, from, length)
1389
PHP_FUNCTION(mysqli_real_escape_string)1390 PHP_FUNCTION(mysqli_real_escape_string) {
1391 MY_MYSQL *mysql;
1392 zval *mysql_link = NULL;
1393 char *escapestr;
1394 size_t escapestr_len;
1395 zend_string *newstr;
1396
1397 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &mysql_link, mysqli_link_class_entry, &escapestr, &escapestr_len) == FAILURE) {
1398 RETURN_THROWS();
1399 }
1400 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1401
1402 newstr = zend_string_safe_alloc(2, escapestr_len, 0, 0);
1403 ZSTR_LEN(newstr) = mysql_real_escape_string_quote(mysql->mysql, ZSTR_VAL(newstr), escapestr, escapestr_len, '\'');
1404 newstr = zend_string_truncate(newstr, ZSTR_LEN(newstr), 0);
1405
1406 RETURN_NEW_STR(newstr);
1407 }
1408
1409 /* {{{ Undo actions from current transaction */
PHP_FUNCTION(mysqli_rollback)1410 PHP_FUNCTION(mysqli_rollback)
1411 {
1412 MY_MYSQL *mysql;
1413 zval *mysql_link;
1414 zend_long flags = TRANS_COR_NO_OPT;
1415 char * name = NULL;
1416 size_t name_len = 0;
1417
1418 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|ls!", &mysql_link, mysqli_link_class_entry, &flags, &name, &name_len) == FAILURE) {
1419 RETURN_THROWS();
1420 }
1421 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1422
1423
1424 if (FAIL == mysqlnd_rollback(mysql->mysql, flags, name)) {
1425 MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
1426 RETURN_FALSE;
1427 }
1428 RETURN_TRUE;
1429 }
1430 /* }}} */
1431
1432 /* {{{ */
PHP_FUNCTION(mysqli_stmt_send_long_data)1433 PHP_FUNCTION(mysqli_stmt_send_long_data)
1434 {
1435 MY_STMT *stmt;
1436 zval *mysql_stmt;
1437 char *data;
1438 zend_long param_nr;
1439 size_t data_len;
1440
1441 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ols", &mysql_stmt, mysqli_stmt_class_entry, ¶m_nr, &data, &data_len) == FAILURE) {
1442 RETURN_THROWS();
1443 }
1444
1445 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
1446
1447 if (param_nr < 0) {
1448 zend_argument_value_error(ERROR_ARG_POS(2), "must be greater than or equal to 0");
1449 RETURN_THROWS();
1450 }
1451
1452 if (mysql_stmt_send_long_data(stmt->stmt, param_nr, data, data_len)) {
1453 RETURN_FALSE;
1454 }
1455 RETURN_TRUE;
1456 }
1457 /* }}} */
1458
1459 /* {{{ Return the number of rows affected in the last query for the given link. */
PHP_FUNCTION(mysqli_stmt_affected_rows)1460 PHP_FUNCTION(mysqli_stmt_affected_rows)
1461 {
1462 MY_STMT *stmt;
1463 zval *mysql_stmt;
1464 my_ulonglong rc;
1465
1466 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
1467 RETURN_THROWS();
1468 }
1469 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
1470
1471 rc = mysql_stmt_affected_rows(stmt->stmt);
1472 if (rc == (my_ulonglong) -1) {
1473 RETURN_LONG(-1);
1474 }
1475 MYSQLI_RETURN_LONG_INT(rc)
1476 }
1477 /* }}} */
1478
1479 /* {{{ Close statement */
PHP_FUNCTION(mysqli_stmt_close)1480 PHP_FUNCTION(mysqli_stmt_close)
1481 {
1482 MY_STMT *stmt;
1483 zval *mysql_stmt;
1484
1485 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
1486 RETURN_THROWS();
1487 }
1488 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
1489
1490 mysqli_stmt_close(stmt->stmt, false);
1491 stmt->stmt = NULL;
1492 php_clear_stmt_bind(stmt);
1493 MYSQLI_CLEAR_RESOURCE(mysql_stmt);
1494 RETURN_TRUE;
1495 }
1496 /* }}} */
1497
1498 /* {{{ Move internal result pointer */
PHP_FUNCTION(mysqli_stmt_data_seek)1499 PHP_FUNCTION(mysqli_stmt_data_seek)
1500 {
1501 MY_STMT *stmt;
1502 zval *mysql_stmt;
1503 zend_long offset;
1504
1505 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &mysql_stmt, mysqli_stmt_class_entry, &offset) == FAILURE) {
1506 RETURN_THROWS();
1507 }
1508
1509 if (offset < 0) {
1510 zend_argument_value_error(ERROR_ARG_POS(2), "must be greater than or equal to 0");
1511 RETURN_THROWS();
1512 }
1513
1514 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
1515
1516 mysql_stmt_data_seek(stmt->stmt, offset);
1517 }
1518 /* }}} */
1519
1520 /* {{{ Return the number of result columns for the given statement */
PHP_FUNCTION(mysqli_stmt_field_count)1521 PHP_FUNCTION(mysqli_stmt_field_count)
1522 {
1523 MY_STMT *stmt;
1524 zval *mysql_stmt;
1525
1526 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
1527 RETURN_THROWS();
1528 }
1529 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
1530
1531 RETURN_LONG(mysql_stmt_field_count(stmt->stmt));
1532 }
1533 /* }}} */
1534
1535 /* {{{ Free stored result memory for the given statement handle */
PHP_FUNCTION(mysqli_stmt_free_result)1536 PHP_FUNCTION(mysqli_stmt_free_result)
1537 {
1538 MY_STMT *stmt;
1539 zval *mysql_stmt;
1540
1541 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
1542 RETURN_THROWS();
1543 }
1544
1545 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
1546
1547 mysql_stmt_free_result(stmt->stmt);
1548 }
1549 /* }}} */
1550
1551 /* {{{ Get the ID generated from the previous INSERT operation */
PHP_FUNCTION(mysqli_stmt_insert_id)1552 PHP_FUNCTION(mysqli_stmt_insert_id)
1553 {
1554 MY_STMT *stmt;
1555 my_ulonglong rc;
1556 zval *mysql_stmt;
1557
1558 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
1559 RETURN_THROWS();
1560 }
1561 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
1562 rc = mysql_stmt_insert_id(stmt->stmt);
1563 MYSQLI_RETURN_LONG_INT(rc)
1564 }
1565 /* }}} */
1566
1567 /* {{{ Return the number of parameter for the given statement */
PHP_FUNCTION(mysqli_stmt_param_count)1568 PHP_FUNCTION(mysqli_stmt_param_count)
1569 {
1570 MY_STMT *stmt;
1571 zval *mysql_stmt;
1572
1573 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
1574 RETURN_THROWS();
1575 }
1576 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
1577
1578 RETURN_LONG(mysql_stmt_param_count(stmt->stmt));
1579 }
1580 /* }}} */
1581
1582 /* {{{ reset a prepared statement */
PHP_FUNCTION(mysqli_stmt_reset)1583 PHP_FUNCTION(mysqli_stmt_reset)
1584 {
1585 MY_STMT *stmt;
1586 zval *mysql_stmt;
1587
1588 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
1589 RETURN_THROWS();
1590 }
1591
1592 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
1593
1594 if (mysql_stmt_reset(stmt->stmt)) {
1595 RETURN_FALSE;
1596 }
1597 RETURN_TRUE;
1598 }
1599 /* }}} */
1600
1601 /* {{{ Return the number of rows in statements result set */
PHP_FUNCTION(mysqli_stmt_num_rows)1602 PHP_FUNCTION(mysqli_stmt_num_rows)
1603 {
1604 MY_STMT *stmt;
1605 zval *mysql_stmt;
1606 my_ulonglong rc;
1607
1608 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
1609 RETURN_THROWS();
1610 }
1611
1612 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
1613
1614 rc = mysql_stmt_num_rows(stmt->stmt);
1615 MYSQLI_RETURN_LONG_INT(rc)
1616 }
1617 /* }}} */
1618
1619 /* {{{ Select a MySQL database */
PHP_FUNCTION(mysqli_select_db)1620 PHP_FUNCTION(mysqli_select_db)
1621 {
1622 MY_MYSQL *mysql;
1623 zval *mysql_link;
1624 char *dbname;
1625 size_t dbname_len;
1626
1627 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &mysql_link, mysqli_link_class_entry, &dbname, &dbname_len) == FAILURE) {
1628 RETURN_THROWS();
1629 }
1630 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1631
1632 if (mysql_select_db(mysql->mysql, dbname)) {
1633 MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
1634 RETURN_FALSE;
1635 }
1636 RETURN_TRUE;
1637 }
1638 /* }}} */
1639
1640 /* {{{ Returns the SQLSTATE error from previous MySQL operation */
PHP_FUNCTION(mysqli_sqlstate)1641 PHP_FUNCTION(mysqli_sqlstate)
1642 {
1643 MY_MYSQL *mysql;
1644 zval *mysql_link;
1645
1646 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1647 RETURN_THROWS();
1648 }
1649 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1650 RETURN_STRING(mysql_sqlstate(mysql->mysql));
1651 }
1652 /* }}} */
1653
1654 /* {{{ */
PHP_FUNCTION(mysqli_ssl_set)1655 PHP_FUNCTION(mysqli_ssl_set)
1656 {
1657 MY_MYSQL *mysql;
1658 zval *mysql_link;
1659 char *ssl_parm[5];
1660 size_t ssl_parm_len[5], i;
1661
1662 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os!s!s!s!s!", &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) {
1663 RETURN_THROWS();
1664 }
1665 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_INITIALIZED);
1666
1667 for (i = 0; i < 5; i++) {
1668 if (!ssl_parm_len[i]) {
1669 ssl_parm[i] = NULL;
1670 }
1671 }
1672
1673 mysql_ssl_set(mysql->mysql, ssl_parm[0], ssl_parm[1], ssl_parm[2], ssl_parm[3], ssl_parm[4]);
1674
1675 RETURN_TRUE;
1676 }
1677 /* }}} */
1678
1679 /* {{{ Get current system status */
PHP_FUNCTION(mysqli_stat)1680 PHP_FUNCTION(mysqli_stat)
1681 {
1682 MY_MYSQL *mysql;
1683 zval *mysql_link;
1684 zend_string *stat;
1685
1686 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1687 RETURN_THROWS();
1688 }
1689 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1690
1691 if (mysqlnd_stat(mysql->mysql, &stat) == PASS)
1692 {
1693 RETURN_STR(stat);
1694 } else {
1695 RETURN_FALSE;
1696 }
1697 }
1698
1699 /* }}} */
1700
1701 /* {{{ Flush tables or caches, or reset replication server information */
PHP_FUNCTION(mysqli_refresh)1702 PHP_FUNCTION(mysqli_refresh)
1703 {
1704 MY_MYSQL *mysql;
1705 zval *mysql_link = NULL;
1706 zend_long options;
1707
1708 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &mysql_link, mysqli_link_class_entry, &options) == FAILURE) {
1709 RETURN_THROWS();
1710 }
1711 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_INITIALIZED);
1712 RETURN_BOOL(!mysql_refresh(mysql->mysql, (uint8_t) options));
1713 }
1714 /* }}} */
1715
1716 /* {{{ */
PHP_FUNCTION(mysqli_stmt_attr_set)1717 PHP_FUNCTION(mysqli_stmt_attr_set)
1718 {
1719 MY_STMT *stmt;
1720 zval *mysql_stmt;
1721 zend_long mode_in;
1722 my_bool mode_b;
1723 unsigned long mode;
1724 zend_long attr;
1725 void *mode_p;
1726
1727 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Oll", &mysql_stmt, mysqli_stmt_class_entry, &attr, &mode_in) == FAILURE) {
1728 RETURN_THROWS();
1729 }
1730
1731 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
1732
1733 switch (attr) {
1734 case STMT_ATTR_UPDATE_MAX_LENGTH:
1735 if (mode_in != 0 && mode_in != 1) {
1736 zend_argument_value_error(ERROR_ARG_POS(3), "must be 0 or 1 for attribute MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH");
1737 RETURN_THROWS();
1738 }
1739 mode_b = (my_bool) mode_in;
1740 mode_p = &mode_b;
1741 break;
1742 case STMT_ATTR_CURSOR_TYPE:
1743 switch (mode_in) {
1744 case CURSOR_TYPE_NO_CURSOR:
1745 case CURSOR_TYPE_READ_ONLY:
1746 case CURSOR_TYPE_FOR_UPDATE:
1747 case CURSOR_TYPE_SCROLLABLE:
1748 break;
1749 default:
1750 zend_argument_value_error(ERROR_ARG_POS(3), "must be one of the MYSQLI_CURSOR_TYPE_* constants "
1751 "for attribute MYSQLI_STMT_ATTR_CURSOR_TYPE");
1752 RETURN_THROWS();
1753 }
1754 mode = mode_in;
1755 mode_p = &mode;
1756 break;
1757 case STMT_ATTR_PREFETCH_ROWS:
1758 if (mode_in < 1) {
1759 zend_argument_value_error(ERROR_ARG_POS(3), "must be greater than 0 for attribute MYSQLI_STMT_ATTR_PREFETCH_ROWS");
1760 RETURN_THROWS();
1761 }
1762 mode = mode_in;
1763 mode_p = &mode;
1764 break;
1765 default:
1766 zend_argument_value_error(ERROR_ARG_POS(2), "must be one of "
1767 "MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH, "
1768 "MYSQLI_STMT_ATTR_PREFETCH_ROWS, or STMT_ATTR_CURSOR_TYPE");
1769 RETURN_THROWS();
1770 }
1771
1772 if (FAIL == mysql_stmt_attr_set(stmt->stmt, attr, mode_p)) {
1773 MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
1774 RETURN_FALSE;
1775 }
1776 RETURN_TRUE;
1777 }
1778 /* }}} */
1779
1780 /* {{{ */
PHP_FUNCTION(mysqli_stmt_attr_get)1781 PHP_FUNCTION(mysqli_stmt_attr_get)
1782 {
1783 MY_STMT *stmt;
1784 zval *mysql_stmt;
1785 unsigned long value = 0;
1786 zend_long attr;
1787 int rc;
1788
1789 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &mysql_stmt, mysqli_stmt_class_entry, &attr) == FAILURE) {
1790 RETURN_THROWS();
1791 }
1792
1793 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
1794
1795 if ((rc = mysql_stmt_attr_get(stmt->stmt, attr, &value))) {
1796 /* Success corresponds to 0 return value and a non-zero value
1797 * should only happen if the attr/option is unknown */
1798 zend_argument_value_error(ERROR_ARG_POS(2), "must be one of "
1799 "MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH, "
1800 "MYSQLI_STMT_ATTR_PREFETCH_ROWS, or STMT_ATTR_CURSOR_TYPE");
1801 RETURN_THROWS();
1802 }
1803
1804
1805 if (attr == STMT_ATTR_UPDATE_MAX_LENGTH)
1806 value = *((my_bool *)&value);
1807 RETURN_LONG((unsigned long)value);
1808 }
1809 /* }}} */
1810
1811 /* {{{ */
PHP_FUNCTION(mysqli_stmt_errno)1812 PHP_FUNCTION(mysqli_stmt_errno)
1813 {
1814 MY_STMT *stmt;
1815 zval *mysql_stmt;
1816
1817 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
1818 RETURN_THROWS();
1819 }
1820 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_INITIALIZED);
1821
1822 RETURN_LONG(mysql_stmt_errno(stmt->stmt));
1823 }
1824 /* }}} */
1825
1826 /* {{{ */
PHP_FUNCTION(mysqli_stmt_error)1827 PHP_FUNCTION(mysqli_stmt_error)
1828 {
1829 MY_STMT *stmt;
1830 zval *mysql_stmt;
1831
1832 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
1833 RETURN_THROWS();
1834 }
1835 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_INITIALIZED);
1836
1837 RETURN_STRING(mysql_stmt_error(stmt->stmt));
1838 }
1839 /* }}} */
1840
1841 /* {{{ Initialize statement object */
PHP_FUNCTION(mysqli_stmt_init)1842 PHP_FUNCTION(mysqli_stmt_init)
1843 {
1844 MY_MYSQL *mysql;
1845 MY_STMT *stmt;
1846 zval *mysql_link;
1847 MYSQLI_RESOURCE *mysqli_resource;
1848
1849 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O",&mysql_link, mysqli_link_class_entry) == FAILURE) {
1850 RETURN_THROWS();
1851 }
1852 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1853
1854 stmt = (MY_STMT *)ecalloc(1,sizeof(MY_STMT));
1855
1856 if (!(stmt->stmt = mysql_stmt_init(mysql->mysql))) {
1857 efree(stmt);
1858 RETURN_FALSE;
1859 }
1860
1861 mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
1862 mysqli_resource->status = MYSQLI_STATUS_INITIALIZED;
1863 mysqli_resource->ptr = (void *)stmt;
1864 MYSQLI_RETVAL_RESOURCE(mysqli_resource, mysqli_stmt_class_entry);
1865 }
1866 /* }}} */
1867
1868 /* {{{ prepare server side statement with query */
PHP_FUNCTION(mysqli_stmt_prepare)1869 PHP_FUNCTION(mysqli_stmt_prepare)
1870 {
1871 MY_STMT *stmt;
1872 zval *mysql_stmt;
1873 char *query;
1874 size_t query_len;
1875
1876 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &mysql_stmt, mysqli_stmt_class_entry, &query, &query_len) == FAILURE) {
1877 RETURN_THROWS();
1878 }
1879 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_INITIALIZED);
1880
1881 if (mysql_stmt_prepare(stmt->stmt, query, query_len)) {
1882 MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
1883 RETURN_FALSE;
1884 }
1885 /* change status */
1886 MYSQLI_SET_STATUS(mysql_stmt, MYSQLI_STATUS_VALID);
1887 RETURN_TRUE;
1888 }
1889 /* }}} */
1890
1891 /* {{{ return result set from statement */
PHP_FUNCTION(mysqli_stmt_result_metadata)1892 PHP_FUNCTION(mysqli_stmt_result_metadata)
1893 {
1894 MY_STMT *stmt;
1895 MYSQL_RES *result;
1896 zval *mysql_stmt;
1897 MYSQLI_RESOURCE *mysqli_resource;
1898
1899 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
1900 RETURN_THROWS();
1901 }
1902 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
1903
1904 if (!(result = mysql_stmt_result_metadata(stmt->stmt))){
1905 MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
1906 RETURN_FALSE;
1907 }
1908
1909 mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
1910 mysqli_resource->ptr = (void *)result;
1911 mysqli_resource->status = MYSQLI_STATUS_VALID;
1912 MYSQLI_RETVAL_RESOURCE(mysqli_resource, mysqli_result_class_entry);
1913 }
1914 /* }}} */
1915
1916 /* {{{ */
PHP_FUNCTION(mysqli_stmt_store_result)1917 PHP_FUNCTION(mysqli_stmt_store_result)
1918 {
1919 MY_STMT *stmt;
1920 zval *mysql_stmt;
1921
1922 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
1923 RETURN_THROWS();
1924 }
1925 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
1926
1927 if (mysql_stmt_store_result(stmt->stmt)){
1928 MYSQLI_REPORT_STMT_ERROR(stmt->stmt);
1929 RETURN_FALSE;
1930 }
1931 RETURN_TRUE;
1932 }
1933 /* }}} */
1934
1935 /* {{{ */
PHP_FUNCTION(mysqli_stmt_sqlstate)1936 PHP_FUNCTION(mysqli_stmt_sqlstate)
1937 {
1938 MY_STMT *stmt;
1939 zval *mysql_stmt;
1940
1941 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) {
1942 RETURN_THROWS();
1943 }
1944 MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID);
1945
1946 RETURN_STRING(mysql_stmt_sqlstate(stmt->stmt));
1947 }
1948 /* }}} */
1949
1950 /* {{{ Buffer result set on client */
PHP_FUNCTION(mysqli_store_result)1951 PHP_FUNCTION(mysqli_store_result)
1952 {
1953 MY_MYSQL *mysql;
1954 MYSQL_RES *result;
1955 zval *mysql_link;
1956 MYSQLI_RESOURCE *mysqli_resource;
1957 zend_long flags = 0;
1958
1959
1960 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|l", &mysql_link, mysqli_link_class_entry, &flags) == FAILURE) {
1961 RETURN_THROWS();
1962 }
1963 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1964 result = mysql_store_result(mysql->mysql);
1965 if (!result) {
1966 MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
1967 RETURN_FALSE;
1968 }
1969 if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
1970 php_mysqli_report_index("from previous query", mysqli_server_status(mysql->mysql));
1971 }
1972
1973 mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
1974 mysqli_resource->ptr = (void *)result;
1975 mysqli_resource->status = MYSQLI_STATUS_VALID;
1976 MYSQLI_RETVAL_RESOURCE(mysqli_resource, mysqli_result_class_entry);
1977 }
1978 /* }}} */
1979
1980 /* {{{ Return the current thread ID */
PHP_FUNCTION(mysqli_thread_id)1981 PHP_FUNCTION(mysqli_thread_id)
1982 {
1983 MY_MYSQL *mysql;
1984 zval *mysql_link;
1985
1986 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
1987 RETURN_THROWS();
1988 }
1989 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
1990
1991 RETURN_LONG((zend_long) mysql_thread_id(mysql->mysql));
1992 }
1993 /* }}} */
1994
1995 /* {{{ Return whether thread safety is given or not */
PHP_FUNCTION(mysqli_thread_safe)1996 PHP_FUNCTION(mysqli_thread_safe)
1997 {
1998 if (zend_parse_parameters_none() == FAILURE) {
1999 RETURN_THROWS();
2000 }
2001
2002 RETURN_BOOL(mysql_thread_safe());
2003 }
2004 /* }}} */
2005
2006 /* {{{ Directly retrieve query results - do not buffer results on client side */
PHP_FUNCTION(mysqli_use_result)2007 PHP_FUNCTION(mysqli_use_result)
2008 {
2009 MY_MYSQL *mysql;
2010 MYSQL_RES *result;
2011 zval *mysql_link;
2012 MYSQLI_RESOURCE *mysqli_resource;
2013
2014 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
2015 RETURN_THROWS();
2016 }
2017 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
2018
2019 if (!(result = mysql_use_result(mysql->mysql))) {
2020 MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
2021 RETURN_FALSE;
2022 }
2023
2024 if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
2025 php_mysqli_report_index("from previous query", mysqli_server_status(mysql->mysql));
2026 }
2027 mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
2028 mysqli_resource->ptr = (void *)result;
2029 mysqli_resource->status = MYSQLI_STATUS_VALID;
2030 MYSQLI_RETVAL_RESOURCE(mysqli_resource, mysqli_result_class_entry);
2031 }
2032 /* }}} */
2033
2034 /* {{{ Return number of warnings from the last query for the given link */
PHP_FUNCTION(mysqli_warning_count)2035 PHP_FUNCTION(mysqli_warning_count)
2036 {
2037 MY_MYSQL *mysql;
2038 zval *mysql_link;
2039
2040 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
2041 RETURN_THROWS();
2042 }
2043 MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID);
2044
2045 RETURN_LONG(mysql_warning_count(mysql->mysql));
2046 }
2047 /* }}} */
2048