diff options
-rw-r--r-- | ext/mysqli/config.m4 | 2 | ||||
-rw-r--r-- | ext/mysqli/mysqli.c | 1 | ||||
-rw-r--r-- | ext/mysqli/mysqli_fe.c | 1 | ||||
-rw-r--r-- | ext/mysqli/mysqli_nonapi.c | 23 | ||||
-rw-r--r-- | ext/mysqli/mysqli_profiler.c | 124 | ||||
-rw-r--r-- | ext/mysqli/php_mysqli.h | 67 |
6 files changed, 201 insertions, 17 deletions
diff --git a/ext/mysqli/config.m4 b/ext/mysqli/config.m4 index e7c34850b7..4934cb7819 100644 --- a/ext/mysqli/config.m4 +++ b/ext/mysqli/config.m4 @@ -54,5 +54,5 @@ if test "$PHP_MYSQLI" != "no"; then ]) PHP_SUBST(MYSQLI_SHARED_LIBADD) - PHP_NEW_EXTENSION(mysqli, mysqli.c mysqli_api.c mysqli_nonapi.c mysqli_fe.c, $ext_shared) + PHP_NEW_EXTENSION(mysqli, mysqli.c mysqli_api.c mysqli_nonapi.c mysqli_fe.c mysqli_profiler.c, $ext_shared) fi diff --git a/ext/mysqli/mysqli.c b/ext/mysqli/mysqli.c index 361132784d..4d6a98f626 100644 --- a/ext/mysqli/mysqli.c +++ b/ext/mysqli/mysqli.c @@ -176,6 +176,7 @@ static void php_mysqli_init_globals(zend_mysqli_globals *mysqli_globals) mysqli_globals->default_user = NULL; mysqli_globals->default_pw = NULL; mysqli_globals->default_socket = NULL; + memset(&mysqli_globals->profiler, '\0', sizeof(PROFILER)); } /* }}} */ diff --git a/ext/mysqli/mysqli_fe.c b/ext/mysqli/mysqli_fe.c index b7e00e0b80..7c1e1569fb 100644 --- a/ext/mysqli/mysqli_fe.c +++ b/ext/mysqli/mysqli_fe.c @@ -102,6 +102,7 @@ function_entry mysqli_functions[] = { PHP_FE(mysqli_send_long_data, NULL) PHP_FE(mysqli_send_query, NULL) PHP_FALIAS(mysqli_set_opt, mysqli_options, NULL) + PHP_FE(mysqli_set_profiler_opt, NULL) PHP_FE(mysqli_slave_query, NULL) PHP_FE(mysqli_ssl_set, NULL) PHP_FE(mysqli_stat, NULL) diff --git a/ext/mysqli/mysqli_nonapi.c b/ext/mysqli/mysqli_nonapi.c index a988926173..0c824f02bd 100644 --- a/ext/mysqli/mysqli_nonapi.c +++ b/ext/mysqli/mysqli_nonapi.c @@ -1,8 +1,8 @@ /* +----------------------------------------------------------------------+ - | PHP Version 4 | + | PHP Version 5 | +----------------------------------------------------------------------+ - | Copyright (c) 1997-2002 The PHP Group | + | Copyright (c) 1997-2003 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 2.02 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | @@ -121,8 +121,20 @@ PHP_FUNCTION(mysqli_query) { } MYSQLI_FETCH_RESOURCE(mysql, MYSQL *, &mysql_link, "mysqli_link"); - if (mysql_real_query(mysql, query, query_len)) { - RETURN_FALSE; + /* profiler reports */ + if (MyG(profiler.active)) { + MYSQLI_PROFILER_HEADER(query); + MYSQLI_PROFILER_EXPLAIN(mysql,query); + MYSQLI_PROFILER_GETTIME; + if (mysql_real_query(mysql, query, query_len)){ + RETURN_FALSE; + } + MYSQLI_PROFILER_REPORTTIME; + } + else { + if (mysql_real_query(mysql, query, query_len)) { + RETURN_FALSE; + } } if (!mysql_field_count(mysql)) { @@ -133,6 +145,9 @@ PHP_FUNCTION(mysqli_query) { if (!result) { RETURN_FALSE; } + if (MyG(profiler.active)) { + MYSQLI_PROFILER_REPORT_RESULT(result); + } MYSQLI_RETURN_RESOURCE(result, mysqli_result_class_entry); } /* }}} */ diff --git a/ext/mysqli/mysqli_profiler.c b/ext/mysqli/mysqli_profiler.c new file mode 100644 index 0000000000..8eddad34f1 --- /dev/null +++ b/ext/mysqli/mysqli_profiler.c @@ -0,0 +1,124 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2003 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.02 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.php.net/license/2_02.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. | + +----------------------------------------------------------------------+ + | Author: Georg Richter <georg@php.net> | + +----------------------------------------------------------------------+ + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php.h" +#include "php_ini.h" +#include "ext/standard/info.h" +#include "php_mysqli.h" + +#define DIVIDER "************************************************************" +#define DIVIDER1 "------------------------------------------------------------" + +/* {{{ void php_mysqli_profiler_header(char *query) */ +void php_mysqli_profiler_header(char *query) +{ + printf("%s\n", DIVIDER); + printf("File: %s\nLine: %d\n", zend_get_executed_filename(TSRMLS_C), zend_get_executed_lineno(TSRMLS_C)); + printf("Function: %s\n", get_active_function_name(TSRMLS_C)); + if (query) { + printf("SQL: %s\n", query); + } +} +/* }}} */ + +/* {{{ void php_mysqli_profiler_result(MYSQL_RES *) */ +void php_mysqli_profiler_result_info(MYSQL_RES *res) +{ + printf("%s\nRows returned: %d\n", DIVIDER1, mysql_num_rows(res)); +} +/* }}} */ + +/* {{{ void php_mysqli_profiler_explain(MYSQL *, char *) */ +void php_mysqli_profiler_explain(MYSQL *mysql, char *query) +{ + MYSQL_RES *res; + MYSQL_ROW row; + MYSQL_FIELD *fields; + unsigned int i; + char *newquery = (char *)emalloc(strlen(query) + 10); + sprintf (newquery, "EXPLAIN %s", query); + + mysql_real_query(mysql, newquery, strlen(newquery)); + efree (newquery); + + if (mysql_errno(mysql)) { + printf ("%s\nError (%d): %s\n", DIVIDER1, mysql_errno(mysql), mysql_error(mysql)); + return; + } + + res = mysql_use_result(mysql); + + printf ("%s\nEXPLAIN:\n", DIVIDER1); + fields = mysql_fetch_fields(res); + while ((row = mysql_fetch_row(res))) { + for (i=0; i < mysql_num_fields(res); i++) { + printf ("%20s: %s\n", fields[i].name, row[i]); + } + printf("\n"); + } + + mysql_free_result(res); + return; +} +/* }}} */ + +/* {{{ void php_mysqli_profiler_elapsed_time() */ +void php_mysqli_profiler_elapsed_time() +{ + struct timeval end, elapsed; + + gettimeofday(&end, NULL); + + elapsed.tv_sec = end.tv_sec - MyG(profiler.start.tv_sec); + elapsed.tv_usec = end.tv_usec - MyG(profiler.start.tv_usec); + if (elapsed.tv_usec < 0) { + --(elapsed.tv_sec); + elapsed.tv_usec = 1000000; + } + printf("%s\nElapsed time: %3d.%06d seconds\n", DIVIDER1, elapsed.tv_sec, elapsed.tv_usec); +} +/* }}} */ + +/* {{{ proto void mysqli_set_profiler_opt (bool profiler) +*/ +PHP_FUNCTION(mysqli_set_profiler_opt) +{ + int flags; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &flags) == FAILURE) { + return; + } + MyG(profiler.active) = flags; + + return; +} +/* }}} */ +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ diff --git a/ext/mysqli/php_mysqli.h b/ext/mysqli/php_mysqli.h index be3c67d439..36424b3aa0 100644 --- a/ext/mysqli/php_mysqli.h +++ b/ext/mysqli/php_mysqli.h @@ -25,11 +25,21 @@ #undef LIST #endif +#ifdef PHP_WIN32 +#include "win32/time.h" +#else +#include "sys/time.h" +#endif + #include <mysql.h> #ifndef PHP_MYSQLI_H #define PHP_MYSQLI_H +#define MYSQLI_PR_TYPE_QUERY 0 +#define MYSQLI_PR_TYPE_PREPARE 1 + + typedef struct { ulong buflen; char *buffer; @@ -45,6 +55,18 @@ typedef struct { char type; } STMT; +typedef struct { + char active; + struct timeval start; + unsigned int count[2]; + ulong min_row_val[2]; + ulong max_row_val[2]; + ulong row_val[2]; + double min_elapsed[2]; + double max_elapsed[2]; + double elapsed[2]; +} PROFILER; + typedef struct _mysqli_object { zend_object zo; void *ptr; @@ -71,6 +93,13 @@ extern function_entry mysqli_stmt_methods[]; extern function_entry mysqli_result_methods[]; extern void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int flag); extern void php_clear_stmt_bind(STMT *stmt); + +/* Profiler functions */ +extern void php_mysqli_profiler_result_info(MYSQL_RES *res); +void php_mysqli_profiler_explain(MYSQL *mysql, char *query); +void php_mysqli_profiler_header(char *query); +void php_mysqli_profiler_elapsed_time(); + zend_class_entry *mysqli_link_class_entry; zend_class_entry *mysqli_stmt_class_entry; zend_class_entry *mysqli_result_class_entry; @@ -153,8 +182,8 @@ PHP_MYSQLI_EXPORT(zend_object_value) mysqli_objects_new(zend_class_entry * TSRML #define MYSQLI_BIND_SEND_DATA 4 /* fetch types */ -#define FETCH_SIMPLE 0 -#define FETCH_RESULT 1 +#define FETCH_SIMPLE 1 +#define FETCH_RESULT 2 PHP_MYSQLI_API void mysqli_register_link(zval *return_value, void *link TSRMLS_DC); PHP_MYSQLI_API void mysqli_register_stmt(zval *return_value, void *stmt TSRMLS_DC); @@ -230,6 +259,7 @@ PHP_FUNCTION(mysqli_rpl_query_type); PHP_FUNCTION(mysqli_select_db); PHP_FUNCTION(mysqli_send_long_data); PHP_FUNCTION(mysqli_send_query); +PHP_FUNCTION(mysqli_set_profiler_opt); PHP_FUNCTION(mysqli_slave_query); PHP_FUNCTION(mysqli_ssl_set); PHP_FUNCTION(mysqli_stat); @@ -245,16 +275,17 @@ PHP_FUNCTION(mysqli_use_result); PHP_FUNCTION(mysqli_warning_count); ZEND_BEGIN_MODULE_GLOBALS(mysqli) - long default_link; - long num_links; - long max_links; - unsigned int default_port; - char *default_host; - char *default_user; - char *default_pw; - char *default_socket; - long error_no; - char *error_msg; + long default_link; + long num_links; + long max_links; + unsigned int default_port; + char *default_host; + char *default_user; + char *default_pw; + char *default_socket; + long error_no; + char *error_msg; + PROFILER profiler; ZEND_END_MODULE_GLOBALS(mysqli) #ifdef ZTS @@ -263,6 +294,18 @@ ZEND_END_MODULE_GLOBALS(mysqli) #define MyG(v) (mysqli_globals.v) #endif +#define MYSQLI_PROFILER_GETTIME gettimeofday(&MyG(profiler.start), NULL) +#define MYSQLI_PROFILER_REPORTTIME php_mysqli_profiler_elapsed_time() +#define MYSQLI_PROFILER_HEADER(query) php_mysqli_profiler_header(query) +#define MYSQLI_PROFILER_REPORT_RESULT(res) php_mysqli_profiler_result_info(res) +#define MYSQLI_PROFILER_EXPLAIN(mysql,query) \ +if (!strncasecmp("select", Z_STRVAL_PP(query), 6)){ \ + php_mysqli_profiler_explain(mysql,query); \ + if (mysql_errno(mysql)) { \ + RETURN_FALSE; \ + } \ +} + ZEND_EXTERN_MODULE_GLOBALS(mysqli); #endif /* PHP_MYSQLI.H */ |