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