summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/mysqli/config.m42
-rw-r--r--ext/mysqli/mysqli.c1
-rw-r--r--ext/mysqli/mysqli_fe.c1
-rw-r--r--ext/mysqli/mysqli_nonapi.c23
-rw-r--r--ext/mysqli/mysqli_profiler.c124
-rw-r--r--ext/mysqli/php_mysqli.h67
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 */