📄 mysqli_api.c
字号:
/* +----------------------------------------------------------------------+ | PHP Version 6 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2007 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Georg Richter <georg@php.net> | | Andrey Hristov <andrey@php.net> | | Ulf Wendel <uw@php.net> | +----------------------------------------------------------------------+ $Id: mysqli_api.c,v 1.143 2007/01/12 20:26:35 andrey Exp $ */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <signal.h>#include "php.h"#include "php_ini.h"#include "ext/standard/info.h"#include "php_mysqli.h"/* {{{ proto mixed mysqli_affected_rows(object link) U Get number of affected rows in previous MySQL operation */PHP_FUNCTION(mysqli_affected_rows){ MY_MYSQL *mysql; zval *mysql_link; my_ulonglong rc; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) { return; } MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link", MYSQLI_STATUS_VALID); rc = mysql_affected_rows(mysql->mysql); if (rc == (my_ulonglong) -1) { RETURN_LONG(-1); } MYSQLI_RETURN_LONG_LONG(rc);}/* }}} *//* {{{ proto bool mysqli_autocommit(object link, bool mode) U Turn auto commit on or of */PHP_FUNCTION(mysqli_autocommit){ MY_MYSQL *mysql; zval *mysql_link; zend_bool automode; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ob", &mysql_link, mysqli_link_class_entry, &automode) == FAILURE) { return; } MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link", MYSQLI_STATUS_VALID); if (mysql_autocommit(mysql->mysql, automode)) { RETURN_FALSE; } RETURN_TRUE;}/* }}} *//* {{{ mysqli_stmt_bind_param_do_bind */#ifndef HAVE_MYSQLNDstaticint 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){ int i, ofs; MYSQL_BIND *bind; unsigned long rc; /* prevent leak if variables are already bound */ if (stmt->param.var_cnt) { php_free_stmt_bind_buffer(stmt->param, FETCH_SIMPLE); } stmt->param.is_null = ecalloc(num_vars, sizeof(char)); bind = (MYSQL_BIND *) ecalloc(num_vars, sizeof(MYSQL_BIND)); ofs = 0; for (i = start; i < argc; i++) { /* set specified type */ switch (types[ofs]) { case 'd': /* Double */ bind[ofs].buffer_type = MYSQL_TYPE_DOUBLE; bind[ofs].buffer = (gptr)&Z_DVAL_PP(args[i]); bind[ofs].is_null = &stmt->param.is_null[ofs]; break; case 'i': /* Integer */ bind[ofs].buffer_type = (sizeof(long) > 4) ? MYSQL_TYPE_LONGLONG : MYSQL_TYPE_LONG; bind[ofs].buffer = (gptr)&Z_LVAL_PP(args[i]); bind[ofs].is_null = &stmt->param.is_null[ofs]; break; case 'b': /* Blob (send data) */ bind[ofs].buffer_type = MYSQL_TYPE_LONG_BLOB; /* don't initialize is_null and length to 0 because we use ecalloc */ break; case 's': /* string */ bind[ofs].buffer_type = MYSQL_TYPE_VAR_STRING; /* don't initialize buffer and buffer_length because we use ecalloc */ bind[ofs].is_null = &stmt->param.is_null[ofs]; break; default: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Undefined fieldtype %c (parameter %d)", types[ofs], i+1); rc = 1; goto end_1; } ofs++; } rc = mysql_stmt_bind_param(stmt->stmt, bind);end_1: if (rc) { efree(stmt->param.is_null); } else { stmt->param.var_cnt = num_vars; stmt->param.vars = (zval **)safe_emalloc(num_vars, sizeof(zval), 0); for (i = 0; i < num_vars; i++) { if (bind[i].buffer_type != MYSQL_TYPE_LONG_BLOB) { ZVAL_ADDREF(*args[i+start]); stmt->param.vars[i] = *args[i+start]; } else { stmt->param.vars[i] = NULL; } } } efree(bind); return rc;}#elsestaticint 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){ int i; MYSQLND_PARAM_BIND *params; enum_func_status ret = FAIL; /* If no params -> skip binding and return directly */ if (argc == start) { return PASS; } params = emalloc((argc - start) * sizeof(MYSQLND_PARAM_BIND)); for (i = 0; i < (argc - start); i++) { zend_uchar type; switch (types[i]) { case 'd': /* Double */ type = MYSQL_TYPE_DOUBLE; break; case 'i': /* Integer */#if SIZEOF_LONG==8 type = MYSQL_TYPE_LONGLONG;#elif SIZEOF_LONG==4 type = MYSQL_TYPE_LONG;#endif break; case 'b': /* Blob (send data) */ type = MYSQL_TYPE_LONG_BLOB; break; case 's': /* string */ type = MYSQL_TYPE_VAR_STRING; break; default: /* We count parameters from 1 */ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Undefined fieldtype %c (parameter %d)", types[i], i + start + 1); ret = FAIL; efree(params); goto end; } params[i].zv = *(args[i + start]); params[i].type = type; } ret = mysqlnd_stmt_bind_param(stmt->stmt, params);end: return ret;}#endif/* }}} *//* {{{ proto bool mysqli_stmt_bind_param(object stmt, string types, mixed variable [,mixed,....]) U Bind variables to a prepared statement as parameters */PHP_FUNCTION(mysqli_stmt_bind_param){ zval ***args; int argc = ZEND_NUM_ARGS(); int num_vars; int start = 2; MY_STMT *stmt; zval *mysql_stmt; char *types; int types_len; unsigned long rc; /* calculate and check number of parameters */ if (argc < 2) { /* there has to be at least one pair */ WRONG_PARAM_COUNT; } if (zend_parse_method_parameters((getThis()) ? 1:2 TSRMLS_CC, getThis(), "Os&", &mysql_stmt, mysqli_stmt_class_entry, &types, &types_len, UG(utf8_conv)) == FAILURE) { return; } MYSQLI_FETCH_RESOURCE(stmt, MY_STMT *, &mysql_stmt, "mysqli_stmt", MYSQLI_STATUS_VALID); num_vars = argc - 1; if (getThis()) { start = 1; } else { /* ignore handle parameter in procedural interface*/ --num_vars; } if (!types_len) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid type or no types specified"); RETURN_FALSE; } if (types_len != argc - start) { /* number of bind variables doesn't match number of elements in type definition string */ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number of elements in type definition string doesn't match number of bind variables"); RETURN_FALSE; } if (types_len != mysql_stmt_param_count(stmt->stmt)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number of variables doesn't match number of parameters in prepared statement"); RETURN_FALSE; } args = (zval ***)safe_emalloc(argc, sizeof(zval **), 0); if (zend_get_parameters_array_ex(argc, args) == FAILURE) { zend_wrong_param_count(TSRMLS_C); rc = 1; } else { rc = mysqli_stmt_bind_param_do_bind(stmt, argc, num_vars, args, start, types TSRMLS_CC); MYSQLI_REPORT_STMT_ERROR(stmt->stmt); } efree(args); RETURN_BOOL(!rc);}/* }}} *//* {{{ */#ifndef HAVE_MYSQLND/* TODO: do_alloca, free_alloca*/static intmysqli_stmt_bind_result_do_bind(MY_STMT *stmt, zval ***args, unsigned int argc, unsigned int start TSRMLS_DC){ MYSQL_BIND *bind; int i, ofs; int var_cnt = argc - start; long col_type; ulong rc; /* prevent leak if variables are already bound */ if (stmt->result.var_cnt) { php_free_stmt_bind_buffer(stmt->result, FETCH_RESULT); } bind = (MYSQL_BIND *)ecalloc(var_cnt, sizeof(MYSQL_BIND)); { int size; char *p= emalloc(size= var_cnt * (sizeof(char) + sizeof(VAR_BUFFER))); stmt->result.buf = (VAR_BUFFER *) p; stmt->result.is_null = p + var_cnt * sizeof(VAR_BUFFER); memset(p, 0, size); } for (i=start; i < var_cnt + start ; i++) { ofs = i - start; col_type = (stmt->stmt->fields) ? stmt->stmt->fields[ofs].type : MYSQL_TYPE_STRING; switch (col_type) { case MYSQL_TYPE_DOUBLE: case MYSQL_TYPE_FLOAT: convert_to_double_ex(args[i]); stmt->result.buf[ofs].type = IS_DOUBLE; stmt->result.buf[ofs].buflen = sizeof(double); /* allocate buffer for double */ stmt->result.buf[ofs].val = (char *)emalloc(sizeof(double)); bind[ofs].buffer_type = MYSQL_TYPE_DOUBLE; bind[ofs].buffer = stmt->result.buf[ofs].val; bind[ofs].is_null = &stmt->result.is_null[ofs]; break; case MYSQL_TYPE_NULL: stmt->result.buf[ofs].type = IS_NULL; /* don't initialize to 0 : 1. stmt->result.buf[ofs].buflen 2. bind[ofs].buffer 3. bind[ofs].buffer_length because memory was allocated with ecalloc */ bind[ofs].buffer_type = MYSQL_TYPE_NULL; bind[ofs].is_null = &stmt->result.is_null[ofs]; break; case MYSQL_TYPE_SHORT: case MYSQL_TYPE_TINY: case MYSQL_TYPE_LONG: case MYSQL_TYPE_INT24: case MYSQL_TYPE_YEAR: convert_to_long_ex(args[i]); stmt->result.buf[ofs].type = IS_LONG; /* don't set stmt->result.buf[ofs].buflen to 0, we used ecalloc */ stmt->result.buf[ofs].val = (char *)emalloc(sizeof(int)); bind[ofs].buffer_type = MYSQL_TYPE_LONG; bind[ofs].buffer = stmt->result.buf[ofs].val; bind[ofs].is_null = &stmt->result.is_null[ofs]; bind[ofs].is_unsigned = (stmt->stmt->fields[ofs].flags & UNSIGNED_FLAG) ? 1 : 0; break; case MYSQL_TYPE_LONGLONG:#if MYSQL_VERSION_ID > 50002 case MYSQL_TYPE_BIT:#endif stmt->result.buf[ofs].type = IS_STRING; stmt->result.buf[ofs].buflen = sizeof(my_ulonglong); stmt->result.buf[ofs].val = (char *)emalloc(stmt->result.buf[ofs].buflen); bind[ofs].buffer_type = col_type; bind[ofs].buffer = stmt->result.buf[ofs].val; bind[ofs].is_null = &stmt->result.is_null[ofs]; bind[ofs].buffer_length = stmt->result.buf[ofs].buflen; bind[ofs].is_unsigned = (stmt->stmt->fields[ofs].flags & UNSIGNED_FLAG) ? 1 : 0; break; case MYSQL_TYPE_DATE: case MYSQL_TYPE_TIME: case MYSQL_TYPE_DATETIME: case MYSQL_TYPE_NEWDATE: case MYSQL_TYPE_VAR_STRING: case MYSQL_TYPE_STRING: case MYSQL_TYPE_BLOB: case MYSQL_TYPE_TIMESTAMP: case MYSQL_TYPE_DECIMAL:#ifdef FIELD_TYPE_NEWDECIMAL case MYSQL_TYPE_NEWDECIMAL:#endif {#if MYSQL_VERSION_ID > 50099 /* Changed to my_bool in MySQL 5.1. See MySQL Bug #16144 */ my_bool tmp;#else ulong tmp = 0;#endif stmt->result.buf[ofs].type = IS_STRING; /* If the user has called $stmt->store_result() then we have asked max_length to be updated. this is done only for BLOBS because we don't want to allocate big chunkgs of memory 2^16 or 2^24 */ if (stmt->stmt->fields[ofs].max_length == 0 && !mysql_stmt_attr_get(stmt->stmt, STMT_ATTR_UPDATE_MAX_LENGTH, &tmp) && !tmp) { stmt->result.buf[ofs].buflen = (stmt->stmt->fields) ? (stmt->stmt->fields[ofs].length) ? stmt->stmt->fields[ofs].length + 1: 256: 256; } else { /* the user has called store_result(). if he does not there is no way to determine the libmysql does not allow us to allocate 0 bytes for a buffer so we try 1 */ if (!(stmt->result.buf[ofs].buflen = stmt->stmt->fields[ofs].max_length)) ++stmt->result.buf[ofs].buflen; } stmt->result.buf[ofs].val = (char *)emalloc(stmt->result.buf[ofs].buflen); bind[ofs].buffer_type = MYSQL_TYPE_STRING; bind[ofs].buffer = stmt->result.buf[ofs].val; bind[ofs].is_null = &stmt->result.is_null[ofs]; bind[ofs].buffer_length = stmt->result.buf[ofs].buflen; bind[ofs].length = &stmt->result.buf[ofs].buflen; break; } default: 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); break; } } rc = mysql_stmt_bind_result(stmt->stmt, bind); MYSQLI_REPORT_STMT_ERROR(stmt->stmt); if (rc) { /* dont close the statement or subsequent usage (for example ->execute()) will lead to crash */ for (i=0; i < var_cnt ; i++) { if (stmt->result.buf[i].val) { efree(stmt->result.buf[i].val); } } /* Don't free stmt->result.is_null because is_null & buf are one block of memory */ efree(stmt->result.buf); } else { stmt->result.var_cnt = var_cnt; stmt->result.vars = (zval **)safe_emalloc((var_cnt), sizeof(zval), 0); for (i = start; i < var_cnt+start; i++) { ofs = i-start; ZVAL_ADDREF(*args[i]); stmt->result.vars[ofs] = *args[i]; } } efree(bind); return rc;}#elsestatic intmysqli_stmt_bind_result_do_bind(MY_STMT *stmt, zval ***args, unsigned int argc, unsigned int start TSRMLS_DC){ unsigned int i; MYSQLND_RESULT_BIND *params; params = emalloc((argc - start) * sizeof(MYSQLND_RESULT_BIND)); for (i = 0; i < (argc - start); i++) { params[i].zv = *(args[i + start]); } return mysqlnd_stmt_bind_result(stmt->stmt, params);}#endif/* }}} */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -