summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.bzrignore6
-rwxr-xr-xCMakeLists.txt48
-rw-r--r--configure.in2
-rw-r--r--include/mysql/plugin.h24
-rw-r--r--libmysqld/CMakeLists.txt27
-rw-r--r--mysql-test/include/default_mysqld.cnf2
-rw-r--r--mysql-test/r/feedback_plugin_install.result13
-rw-r--r--mysql-test/r/feedback_plugin_load.result11
-rw-r--r--mysql-test/r/feedback_plugin_send.result15
-rw-r--r--mysql-test/r/trigger.result19
-rw-r--r--mysql-test/t/feedback_plugin_install.opt1
-rw-r--r--mysql-test/t/feedback_plugin_install.test15
-rw-r--r--mysql-test/t/feedback_plugin_load.opt2
-rw-r--r--mysql-test/t/feedback_plugin_load.test10
-rw-r--r--mysql-test/t/feedback_plugin_send.test24
-rw-r--r--mysql-test/t/fulltext_plugin.test3
-rw-r--r--mysql-test/t/trigger.test25
-rw-r--r--mysys/CMakeLists.txt1
-rw-r--r--mysys/my_gethwaddr.c106
-rw-r--r--plugin/feedback/CMakeLists.txt11
-rw-r--r--plugin/feedback/Makefile.am18
-rw-r--r--plugin/feedback/feedback.cc373
-rw-r--r--plugin/feedback/feedback.h67
-rw-r--r--plugin/feedback/plug.in28
-rw-r--r--plugin/feedback/sender_thread.cc301
-rw-r--r--plugin/feedback/url_base.cc51
-rw-r--r--plugin/feedback/url_http.cc303
-rw-r--r--plugin/feedback/utils.cc392
-rw-r--r--plugin/fulltext/CMakeLists.txt3
-rw-r--r--sql/CMakeLists.txt4
-rw-r--r--sql/sp.cc45
-rw-r--r--sql/sp.h16
-rw-r--r--sql/sp_head.h22
-rw-r--r--sql/sql_db.cc1
-rw-r--r--sql/sql_lex.cc2
-rw-r--r--sql/sql_parse.cc18
-rw-r--r--sql/sql_plugin.cc17
-rw-r--r--sql/sql_show.cc2
-rw-r--r--sql/sql_view.cc2
-rw-r--r--storage/blackhole/plug.in1
-rw-r--r--storage/csv/plug.in1
-rw-r--r--storage/heap/plug.in1
-rw-r--r--storage/innobase/plug.in.disabled1
-rw-r--r--storage/innodb_plugin/plug.in1
-rw-r--r--storage/maria/CMakeLists.txt22
-rw-r--r--storage/maria/plug.in1
-rw-r--r--storage/maria/unittest/CMakeLists.txt3
-rw-r--r--storage/myisam/CMakeLists.txt18
-rw-r--r--storage/myisam/plug.in1
-rw-r--r--storage/myisammrg/plug.in1
-rw-r--r--storage/mysql_storage_engine.cmake48
-rw-r--r--storage/ndb/plug.in1
-rw-r--r--storage/pbxt/plug.in1
-rw-r--r--storage/xtradb/CMakeLists.txt4
-rw-r--r--storage/xtradb/plug.in1
-rw-r--r--win/README12
-rw-r--r--win/configure-mariadb.bat3
-rw-r--r--win/configure-mariadb.sh1
-rw-r--r--win/configure.js8
59 files changed, 1979 insertions, 181 deletions
diff --git a/.bzrignore b/.bzrignore
index 720918c46a8..8ce761624b8 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -702,7 +702,6 @@ ma_test_recovery.output
man/*.1
maria-win.patch
maria_log.00000*
-maria_log_control
merge/*.ds?
merge/*.vcproj
missing
@@ -1971,3 +1970,8 @@ libmysql/strings_def.h
libmysql_r/strings_def.h
storage/maria/aria_log_control
scripts/mytop
+CPackConfig.cmake
+CPackSourceConfig.cmake
+win/nmake_cache.txt
+*.manifest
+*.resource.txt
diff --git a/CMakeLists.txt b/CMakeLists.txt
index fd98586c359..5ed8dedb574 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -114,6 +114,9 @@ ENDIF(ENABLED_DEBUG_SYNC)
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DENABLED_DEBUG_SYNC")
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DENABLED_DEBUG_SYNC")
+SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
+SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
+
# in some places we use DBUG_OFF
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DDBUG_OFF")
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DDBUG_OFF")
@@ -247,16 +250,15 @@ IF(WITHOUT_DYNAMIC_PLUGINS)
MESSAGE("Dynamic plugins are disabled.")
ENDIF(WITHOUT_DYNAMIC_PLUGINS)
-FILE(GLOB STORAGE_SUBDIRS storage/*)
+FILE(GLOB STORAGE_SUBDIRS storage/* plugin/*)
FOREACH(SUBDIR ${STORAGE_SUBDIRS})
- FILE(RELATIVE_PATH DIRNAME ${PROJECT_SOURCE_DIR}/storage ${SUBDIR})
IF (EXISTS ${SUBDIR}/CMakeLists.txt)
# Check MYSQL_STORAGE_ENGINE macro is present
- FILE(STRINGS ${SUBDIR}/CMakeLists.txt HAVE_STORAGE_ENGINE REGEX MYSQL_STORAGE_ENGINE)
+ FILE(STRINGS ${SUBDIR}/CMakeLists.txt HAVE_STORAGE_ENGINE REGEX "MYSQL_(STORAGE_ENGINE|PLUGIN)")
IF(HAVE_STORAGE_ENGINE)
# Extract name of engine from HAVE_STORAGE_ENGINE
- STRING(REGEX REPLACE ".*MYSQL_STORAGE_ENGINE\\((.*\)\\).*"
- "\\1" ENGINE_NAME ${HAVE_STORAGE_ENGINE})
+ STRING(REGEX REPLACE ".*MYSQL_(STORAGE_ENGINE|PLUGIN)\\((.*\)\\).*"
+ "\\2" ENGINE_NAME ${HAVE_STORAGE_ENGINE})
STRING(TOUPPER ${ENGINE_NAME} ENGINE)
STRING(TOLOWER ${ENGINE_NAME} ENGINE_LOWER)
@@ -265,21 +267,23 @@ FOREACH(SUBDIR ${STORAGE_SUBDIRS})
# build as shared library (dynamic).
IF(EXISTS ${SUBDIR}/plug.in)
FILE(READ ${SUBDIR}/plug.in PLUGIN_FILE_CONTENT)
- STRING (REGEX MATCH "MYSQL_PLUGIN_DYNAMIC" MYSQL_PLUGIN_DYNAMIC ${PLUGIN_FILE_CONTENT})
+ IF (PLUGIN_FILE_CONTENT MATCHES "MYSQL_PLUGIN_DYNAMIC\\(${ENGINE_LOWER}")
+ STRING (REGEX REPLACE
+ ".*MYSQL_PLUGIN_DYNAMIC\\(${ENGINE_LOWER},[ \\t]*\\[?([a-zA-Z0-9_]+/)*([a-zA-Z0-9_]+).*"
+ "\\2" MYSQL_PLUGIN_DYNAMIC ${PLUGIN_FILE_CONTENT})
+ ELSE (PLUGIN_FILE_CONTENT MATCHES "MYSQL_PLUGIN_DYNAMIC\\(${ENGINE_LOWER}")
+ SET (MYSQL_PLUGIN_DYNAMIC "")
+ ENDIF(PLUGIN_FILE_CONTENT MATCHES "MYSQL_PLUGIN_DYNAMIC\\(${ENGINE_LOWER}")
+ IF (PLUGIN_FILE_CONTENT MATCHES "MYSQL_PLUGIN_STATIC\\(${ENGINE_LOWER}")
+ STRING (REGEX REPLACE
+ ".*MYSQL_PLUGIN_STATIC\\(${ENGINE_LOWER},[ \\t]*\\[?([a-zA-Z0-9_]+/)*([a-zA-Z0-9_]+).*"
+ "\\2"
+ MYSQL_PLUGIN_STATIC ${PLUGIN_FILE_CONTENT})
+ ELSE (PLUGIN_FILE_CONTENT MATCHES "MYSQL_PLUGIN_STATIC\\(${ENGINE_LOWER}")
+ SET (MYSQL_PLUGIN_STATIC "")
+ ENDIF(PLUGIN_FILE_CONTENT MATCHES "MYSQL_PLUGIN_STATIC\\(${ENGINE_LOWER}")
STRING (REGEX MATCH "MYSQL_PLUGIN_MANDATORY" MYSQL_PLUGIN_MANDATORY ${PLUGIN_FILE_CONTENT})
- STRING (REGEX MATCH "MYSQL_PLUGIN_STATIC" MYSQL_PLUGIN_STATIC ${PLUGIN_FILE_CONTENT})
-
- #
- # XTRADB is located in storage/xtradb, but it says everywhere it is 'innobase' (e.g.
- # it declares 'builtin_innobase_plugin', not builtin_xtradb_plugin).
- # Extract the intended plugin name from MYSQL_STORAGE_ENGINE definition and use it
- # where appropriate.
- STRING (REGEX MATCH "MYSQL_STORAGE_ENGINE.[a-z]*" PLUGIN_NAME ${PLUGIN_FILE_CONTENT})
- STRING (REGEX REPLACE "MYSQL_STORAGE_ENGINE.(.*)" "\\1" PLUGIN_NAME ${PLUGIN_NAME})
- # Also remember this "xtradb"/"innobase" name discrepancy for libmysqld/CMakeLists.txt:
- SET (plugin_dir_${PLUGIN_NAME} ${DIRNAME})
-
IF(MYSQL_PLUGIN_MANDATORY)
SET(WITH_${ENGINE}_STORAGE_ENGINE TRUE)
ENDIF(MYSQL_PLUGIN_MANDATORY)
@@ -293,15 +297,17 @@ FOREACH(SUBDIR ${STORAGE_SUBDIRS})
ENDIF(WITH_${ENGINE}_STORAGE_ENGINE AND MYSQL_PLUGIN_STATIC)
IF (ENGINE_BUILD_TYPE STREQUAL "STATIC")
- SET (maria_plugin_defs "${maria_plugin_defs},builtin_maria_${PLUGIN_NAME}_plugin")
- SET (MYSQLD_STATIC_ENGINE_LIBS ${MYSQLD_STATIC_ENGINE_LIBS} ${PLUGIN_NAME})
+ SET (maria_plugin_defs "${maria_plugin_defs},builtin_maria_${ENGINE_LOWER}_plugin")
+ SET (MYSQLD_STATIC_ENGINE_LIBS ${MYSQLD_STATIC_ENGINE_LIBS} ${MYSQL_PLUGIN_STATIC})
+ SET (MYSQLD_STATIC_ENGINES ${MYSQLD_STATIC_ENGINES} ${ENGINE})
SET (STORAGE_ENGINE_DEFS "${STORAGE_ENGINE_DEFS} -DWITH_${ENGINE}_STORAGE_ENGINE")
SET (WITH_${ENGINE}_STORAGE_ENGINE TRUE)
- SET (${ENGINE}_DIR ${DIRNAME})
+ SET (${ENGINE}_DIR ${SUBDIR})
ENDIF (ENGINE_BUILD_TYPE STREQUAL "STATIC")
ENDIF(EXISTS ${SUBDIR}/plug.in)
IF(NOT ENGINE_BUILD_TYPE STREQUAL "NONE")
+ SET (${ENGINE}_LIB ${MYSQL_PLUGIN_${ENGINE_BUILD_TYPE}})
LIST(APPEND ${ENGINE_BUILD_TYPE}_ENGINE_DIRECTORIES ${SUBDIR})
ENDIF(NOT ENGINE_BUILD_TYPE STREQUAL "NONE")
diff --git a/configure.in b/configure.in
index 2d6dc127130..96cb19fc6a9 100644
--- a/configure.in
+++ b/configure.in
@@ -870,7 +870,7 @@ AC_HEADER_STDC
AC_HEADER_SYS_WAIT
AC_CHECK_HEADERS(fcntl.h fenv.h float.h floatingpoint.h fpu_control.h \
ieeefp.h limits.h memory.h pwd.h select.h fnmatch.h \
- stdlib.h stddef.h sys/stat.h \
+ stdlib.h stddef.h sys/stat.h sys/sockio.h \
strings.h string.h synch.h sys/mman.h sys/socket.h netinet/in.h arpa/inet.h \
sys/timeb.h sys/types.h sys/un.h sys/vadvise.h sys/wait.h term.h \
unistd.h utime.h sys/utime.h termio.h termios.h sched.h crypt.h alloca.h \
diff --git a/include/mysql/plugin.h b/include/mysql/plugin.h
index 4437f5e94ef..83e2aceaf1e 100644
--- a/include/mysql/plugin.h
+++ b/include/mysql/plugin.h
@@ -17,13 +17,27 @@
#ifndef _my_plugin_h
#define _my_plugin_h
-
/*
On Windows, exports from DLL need to be declared
-*/
-#if (defined(_WIN32) && defined(MYSQL_DYNAMIC_PLUGIN))
-#define MYSQL_PLUGIN_EXPORT extern "C" __declspec(dllexport)
-#else
+ Also, plugin needs to be declared as extern "C" because MSVC
+ unlike other compilers, uses C++ mangling for variables not only
+ for functions.
+*/
+#if defined(_MSC_VER)
+#if defined(MYSQL_DYNAMIC_PLUGIN)
+ #ifdef __cplusplus
+ #define MYSQL_PLUGIN_EXPORT extern "C" __declspec(dllexport)
+ #else
+ #define MYSQL_PLUGIN_EXPORT __declspec(dllexport)
+ #endif
+#else /* MYSQL_DYNAMIC_PLUGIN */
+ #ifdef __cplusplus
+ #define MYSQL_PLUGIN_EXPORT extern "C"
+ #else
+ #define MYSQL_PLUGIN_EXPORT
+ #endif
+#endif /*MYSQL_DYNAMIC_PLUGIN */
+#else /*_MSC_VER */
#define MYSQL_PLUGIN_EXPORT
#endif
diff --git a/libmysqld/CMakeLists.txt b/libmysqld/CMakeLists.txt
index 7c5b6bd5917..9a3627da606 100644
--- a/libmysqld/CMakeLists.txt
+++ b/libmysqld/CMakeLists.txt
@@ -86,15 +86,13 @@ FOREACH(rpath ${VIO_SOURCES})
SET(LIB_SOURCES ${LIB_SOURCES} ../vio/${rpath})
ENDFOREACH(rpath)
-FOREACH (ENGINE_LIB ${MYSQLD_STATIC_ENGINE_LIBS})
- INCLUDE(${CMAKE_SOURCE_DIR}/storage/${plugin_dir_${ENGINE_LIB}}/CMakeLists.txt)
- STRING(TOUPPER ${ENGINE_LIB} ENGINE_LIB_UPPER)
- SET(ENGINE_DIR ${${ENGINE_LIB_UPPER}_DIR})
- INCLUDE(${CMAKE_SOURCE_DIR}/storage/${ENGINE_DIR}/CMakeLists.txt)
- FOREACH(rpath ${${ENGINE_LIB_UPPER}_SOURCES})
- SET(LIB_SOURCES ${LIB_SOURCES} ${CMAKE_SOURCE_DIR}/storage/${ENGINE_DIR}/${rpath})
+SET (ENGINE_BUILD_TYPE "STATIC")
+FOREACH (ENGINE ${MYSQLD_STATIC_ENGINES})
+ INCLUDE(${${ENGINE}_DIR}/CMakeLists.txt)
+ FOREACH(rpath ${${ENGINE}_SOURCES})
+ SET(LIB_SOURCES ${LIB_SOURCES} ${${ENGINE}_DIR}/${rpath})
ENDFOREACH(rpath)
-ENDFOREACH(ENGINE_LIB)
+ENDFOREACH(ENGINE)
SET(SOURCE_SUBLIBS FALSE)
@@ -168,15 +166,14 @@ IF(MSVC AND CMAKE_SIZEOF_VOID_P MATCHES 8)
ENDIF()
# Add any additional libraries requested by engine(s)
-FOREACH (ENGINE_LIB ${MYSQLD_STATIC_ENGINE_LIBS})
- STRING(TOUPPER ${ENGINE_LIB} ENGINE_LIB_UPPER)
- IF(${ENGINE_LIB_UPPER}_LIBS)
- TARGET_LINK_LIBRARIES(mysqlserver ${${ENGINE_LIB_UPPER}_LIBS})
- ENDIF(${ENGINE_LIB_UPPER}_LIBS)
-ENDFOREACH(ENGINE_LIB)
+FOREACH (ENGINE ${MYSQLD_STATIC_ENGINES})
+ IF(${ENGINE}_LIBS)
+ TARGET_LINK_LIBRARIES(mysqlserver ${${ENGINE}_LIBS})
+ ENDIF(${ENGINE}_LIBS)
+ENDFOREACH(ENGINE)
ADD_LIBRARY(libmysqld SHARED cmake_dummy.c libmysqld.def)
ADD_DEPENDENCIES(libmysqld mysqlserver)
-TARGET_LINK_LIBRARIES(libmysqld mysqlserver wsock32)
+TARGET_LINK_LIBRARIES(libmysqld mysqlserver wsock32 iphlpapi)
MYSQL_INSTALL_TARGETS(mysqlserver libmysqld DESTINATION lib COMPONENT Embedded)
diff --git a/mysql-test/include/default_mysqld.cnf b/mysql-test/include/default_mysqld.cnf
index e46c3bc3c17..a1b477c51dd 100644
--- a/mysql-test/include/default_mysqld.cnf
+++ b/mysql-test/include/default_mysqld.cnf
@@ -15,6 +15,8 @@ max_heap_table_size= 1M
loose-skip-innodb
loose-skip-pbxt
+loose-skip-feedback
+loose-feedback-user-info= mysql-test
loose-innodb_data_file_path= ibdata1:10M:autoextend
diff --git a/mysql-test/r/feedback_plugin_install.result b/mysql-test/r/feedback_plugin_install.result
new file mode 100644
index 00000000000..4b3b0226fae
--- /dev/null
+++ b/mysql-test/r/feedback_plugin_install.result
@@ -0,0 +1,13 @@
+install plugin feedback soname 'feedback.so';
+select plugin_status from information_schema.plugins where plugin_name='feedback';
+plugin_status
+ACTIVE
+select * from information_schema.feedback where variable_name like 'feed%'
+ and variable_name not like '%_uid';
+VARIABLE_NAME VARIABLE_VALUE
+FEEDBACK 1.0
+FEEDBACK_SEND_RETRY_WAIT 60
+FEEDBACK_SEND_TIMEOUT 60
+FEEDBACK_URL http://mariadb.org/feedback_plugin/post
+FEEDBACK_USER_INFO mysql-test
+uninstall plugin feedback;
diff --git a/mysql-test/r/feedback_plugin_load.result b/mysql-test/r/feedback_plugin_load.result
new file mode 100644
index 00000000000..bc02b920a11
--- /dev/null
+++ b/mysql-test/r/feedback_plugin_load.result
@@ -0,0 +1,11 @@
+select plugin_status from information_schema.plugins where plugin_name='feedback';
+plugin_status
+ACTIVE
+select * from information_schema.feedback where variable_name like 'feed%'
+ and variable_name not like '%_uid';
+VARIABLE_NAME VARIABLE_VALUE
+FEEDBACK 1.0
+FEEDBACK_SEND_RETRY_WAIT 60
+FEEDBACK_SEND_TIMEOUT 60
+FEEDBACK_URL http://mariadb.org/feedback_plugin/post
+FEEDBACK_USER_INFO mysql-test
diff --git a/mysql-test/r/feedback_plugin_send.result b/mysql-test/r/feedback_plugin_send.result
new file mode 100644
index 00000000000..22379e26248
--- /dev/null
+++ b/mysql-test/r/feedback_plugin_send.result
@@ -0,0 +1,15 @@
+select plugin_status from information_schema.plugins where plugin_name='feedback';
+plugin_status
+ACTIVE
+select * from information_schema.feedback where variable_name like 'feed%'
+ and variable_name not like '%_uid';
+VARIABLE_NAME VARIABLE_VALUE
+FEEDBACK 1.0
+FEEDBACK_SEND_RETRY_WAIT 60
+FEEDBACK_SEND_TIMEOUT 60
+FEEDBACK_URL http://mariadb.org/feedback_plugin/post
+FEEDBACK_USER_INFO mysql-test
+feedback plugin: report to 'http://mariadb.org/feedback_plugin/post' was sent
+feedback plugin: server replied 'ok'
+feedback plugin: report to 'http://mariadb.org/feedback_plugin/post' was sent
+feedback plugin: server replied 'ok'
diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result
index 089845560ed..efe63285c9c 100644
--- a/mysql-test/r/trigger.result
+++ b/mysql-test/r/trigger.result
@@ -2117,3 +2117,22 @@ b
DROP DATABASE db1;
USE test;
End of 5.1 tests.
+create table t1 (i int);
+create table t2 (i int);
+flush tables;
+flush status;
+CREATE DEFINER=`root`@`localhost` TRIGGER trg AFTER DELETE ON t1 FOR EACH ROW BEGIN DELETE FROM t2 WHERE t2.i = OLD.i; END //
+insert into t1 values (1),(2);
+insert into t2 values (1),(2);
+delete from t1 where i=1;
+show status like 'Opened_tables';
+Variable_name Value
+Opened_tables 3
+select * from t1;
+i
+2
+select * from t2;
+i
+2
+drop table t1,t2;
+End of 5.2 tests.
diff --git a/mysql-test/t/feedback_plugin_install.opt b/mysql-test/t/feedback_plugin_install.opt
new file mode 100644
index 00000000000..a711ae94e69
--- /dev/null
+++ b/mysql-test/t/feedback_plugin_install.opt
@@ -0,0 +1 @@
+--loose-feedback
diff --git a/mysql-test/t/feedback_plugin_install.test b/mysql-test/t/feedback_plugin_install.test
new file mode 100644
index 00000000000..81343c436c3
--- /dev/null
+++ b/mysql-test/t/feedback_plugin_install.test
@@ -0,0 +1,15 @@
+--source include/not_embedded.inc
+
+if (`select length('$FEEDBACK_SO') = 0`) {
+ skip No feedback plugin;
+}
+
+--replace_regex /\.dll/.so/
+eval install plugin feedback soname '$FEEDBACK_SO';
+select plugin_status from information_schema.plugins where plugin_name='feedback';
+--replace_result https http
+--sorted_result
+select * from information_schema.feedback where variable_name like 'feed%'
+ and variable_name not like '%_uid';
+uninstall plugin feedback;
+
diff --git a/mysql-test/t/feedback_plugin_load.opt b/mysql-test/t/feedback_plugin_load.opt
new file mode 100644
index 00000000000..5fbb2f83954
--- /dev/null
+++ b/mysql-test/t/feedback_plugin_load.opt
@@ -0,0 +1,2 @@
+--loose-feedback
+--plugin-load=$FEEDBACK_SO
diff --git a/mysql-test/t/feedback_plugin_load.test b/mysql-test/t/feedback_plugin_load.test
new file mode 100644
index 00000000000..5ad301667b4
--- /dev/null
+++ b/mysql-test/t/feedback_plugin_load.test
@@ -0,0 +1,10 @@
+if (`select count(*) = 0 from information_schema.plugins where plugin_name = 'feedback' and plugin_status='active'`)
+{
+ --skip Feedback plugin is not active
+}
+
+select plugin_status from information_schema.plugins where plugin_name='feedback';
+--replace_result https http
+--sorted_result
+select * from information_schema.feedback where variable_name like 'feed%'
+ and variable_name not like '%_uid';
diff --git a/mysql-test/t/feedback_plugin_send.test b/mysql-test/t/feedback_plugin_send.test
new file mode 100644
index 00000000000..b49c0d0e252
--- /dev/null
+++ b/mysql-test/t/feedback_plugin_send.test
@@ -0,0 +1,24 @@
+source t/feedback_plugin_load.test;
+source include/big_test.inc;
+
+if (!$MTR_FEEDBACK_PLUGIN) {
+ skip MTR_FEEDBACK_PLUGIN is not set;
+}
+
+#
+# Yep. The plugin waits 5 minutes before sending anything,
+# and there's no way to force it to send anything sooner.
+# Let's wait, and hope that mtr is started with --parallel and
+# is doing some work in other workers.
+#
+sleep 310;
+source include/restart_mysqld.inc;
+
+replace_result https http;
+perl;
+ $log_error= $ENV{'MYSQLTEST_VARDIR'} . '/log/mysqld.1.err';
+ open(LOG, '<', $log_error) or die "open(< $log_error): $!";
+ /feedback plugin:.*/ && print "$&\n" while $_=<LOG>;
+ close LOG;
+EOF
+
diff --git a/mysql-test/t/fulltext_plugin.test b/mysql-test/t/fulltext_plugin.test
index 31978dadc51..0e2f53d5b15 100644
--- a/mysql-test/t/fulltext_plugin.test
+++ b/mysql-test/t/fulltext_plugin.test
@@ -3,7 +3,8 @@
#
# BUG#39746 - Debug flag breaks struct definition (server crash)
#
-INSTALL PLUGIN simple_parser SONAME 'mypluglib.so';
+--replace_result .dll .so
+eval INSTALL PLUGIN simple_parser SONAME '$MYPLUGLIB_SO';
CREATE TABLE t1(a TEXT, b TEXT, FULLTEXT(a) WITH PARSER simple_parser);
ALTER TABLE t1 ADD FULLTEXT(b) WITH PARSER simple_parser;
DROP TABLE t1;
diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test
index a968e146d20..8d84330ec44 100644
--- a/mysql-test/t/trigger.test
+++ b/mysql-test/t/trigger.test
@@ -2409,3 +2409,28 @@ DROP DATABASE db1;
USE test;
--echo End of 5.1 tests.
+
+#
+# Test that using a trigger will not open mysql.proc
+#
+
+create table t1 (i int);
+create table t2 (i int);
+flush tables;
+flush status;
+delimiter //;
+CREATE DEFINER=`root`@`localhost` TRIGGER trg AFTER DELETE ON t1 FOR EACH ROW BEGIN DELETE FROM t2 WHERE t2.i = OLD.i; END //
+delimiter ;//
+insert into t1 values (1),(2);
+insert into t2 values (1),(2);
+delete from t1 where i=1;
+#
+# If mysql.proc would be used we would have 4 here. 3 is the correct number.
+# (CREATE TRIGGER will open t1 and then flush it)
+#
+show status like 'Opened_tables';
+select * from t1;
+select * from t2;
+drop table t1,t2;
+
+--echo End of 5.2 tests.
diff --git a/mysys/CMakeLists.txt b/mysys/CMakeLists.txt
index 87f40af2fe8..ce424dd51a5 100644
--- a/mysys/CMakeLists.txt
+++ b/mysys/CMakeLists.txt
@@ -48,4 +48,5 @@ SET(MYSYS_SOURCES array.c charset-def.c charset.c checksum.c default.c default_
IF(NOT SOURCE_SUBLIBS)
ADD_LIBRARY(mysys ${MYSYS_SOURCES})
+ TARGET_LINK_LIBRARIES(mysys IPHLPAPI)
ENDIF(NOT SOURCE_SUBLIBS)
diff --git a/mysys/my_gethwaddr.c b/mysys/my_gethwaddr.c
index 90908bd1c0d..bcc231eaf7e 100644
--- a/mysys/my_gethwaddr.c
+++ b/mysys/my_gethwaddr.c
@@ -16,11 +16,22 @@
/* get hardware address for an interface */
/* if there are many available, any non-zero one can be used */
+#define DONT_DEFINE_VOID /* windows includes break if we do */
#include "mysys_priv.h"
#include <m_string.h>
#ifndef MAIN
+static my_bool memcpy_and_test(uchar *to, uchar *from, uint len)
+{
+ uint i, res= 1;
+
+ for (i= 0; i < len; i++)
+ if ((*to++= *from++))
+ res= 0;
+ return res;
+}
+
#ifdef __FreeBSD__
#include <net/ethernet.h>
@@ -32,11 +43,10 @@
my_bool my_gethwaddr(uchar *to)
{
size_t len;
- char *buf, *next, *end;
+ uchar *buf, *next, *end, *addr;
struct if_msghdr *ifm;
struct sockaddr_dl *sdl;
- int res=1, mib[6]={CTL_NET, AF_ROUTE, 0, AF_LINK, NET_RT_IFLIST, 0};
- char zero_array[ETHER_ADDR_LEN] = {0};
+ int res= 1, mib[6]= {CTL_NET, AF_ROUTE, 0, AF_LINK, NET_RT_IFLIST, 0};
if (sysctl(mib, 6, NULL, &len, NULL, 0) == -1)
goto err;
@@ -52,9 +62,9 @@ my_bool my_gethwaddr(uchar *to)
ifm = (struct if_msghdr *)next;
if (ifm->ifm_type == RTM_IFINFO)
{
- sdl= (struct sockaddr_dl *)(ifm + 1);
- memcpy(to, LLADDR(sdl), ETHER_ADDR_LEN);
- res= memcmp(to, zero_array, ETHER_ADDR_LEN) ? 0 : 1;
+ sdl = (struct sockaddr_dl *)(ifm + 1);
+ addr= LLADDR(sdl);
+ res= memcpy_and_test(to, addr, ETHER_ADDR_LEN);
}
}
@@ -62,40 +72,94 @@ err:
return res;
}
-#elif __linux__
-
+#elif defined(__linux__) || defined(__sun__)
#include <net/if.h>
#include <sys/ioctl.h>
-#include <net/ethernet.h>
+#include <net/if_arp.h>
+#ifdef HAVE_SYS_SOCKIO_H
+#include <sys/sockio.h>
+#endif
+
+#define ETHER_ADDR_LEN 6
my_bool my_gethwaddr(uchar *to)
{
int fd, res= 1;
- struct ifreq ifr;
- char zero_array[ETHER_ADDR_LEN] = {0};
+ struct ifreq ifr[32];
+ struct ifconf ifc;
+
+ ifc.ifc_req= ifr;
+ ifc.ifc_len= sizeof(ifr);
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0)
goto err;
- bzero(&ifr, sizeof(ifr));
- strnmov(ifr.ifr_name, "eth0", sizeof(ifr.ifr_name) - 1);
-
- do
+ if (ioctl(fd, SIOCGIFCONF, (char*)&ifc) >= 0)
{
- if (ioctl(fd, SIOCGIFHWADDR, &ifr) >= 0)
+ uint i;
+ for (i= 0; res && i < ifc.ifc_len / sizeof(ifr[0]); i++)
{
- memcpy(to, &ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
- res= memcmp(to, zero_array, ETHER_ADDR_LEN) ? 0 : 1;
+#ifdef SIOCGIFHWADDR
+ if (ioctl(fd, SIOCGIFHWADDR, &ifr[i]) >= 0)
+ res= memcpy_and_test(to, (uchar *)&ifr[i].ifr_hwaddr.sa_data,
+ ETHER_ADDR_LEN);
+#else
+ /*
+ A bug in OpenSolaris prevents non-root from getting a mac address:
+ http://bugs.opensolaris.org/bugdatabase/view_bug.do?bug_id=4720634
+
+ Thus, we'll use an alternative method and extract the address from the
+ arp table.
+ */
+ struct arpreq arpr;
+ arpr.arp_pa= ifr[i].ifr_addr;
+
+ if (ioctl(fd, SIOCGARP, (char*)&arpr) >= 0)
+ res= memcpy_and_test(to, (uchar *)&arpr.arp_ha.sa_data,
+ ETHER_ADDR_LEN);
+#endif
}
- } while (res && (errno == 0 || errno == ENODEV) && ifr.ifr_name[3]++ < '6');
+ }
close(fd);
err:
return res;
}
-#else /* FreeBSD elif linux */
+#elif defined(_WIN32)
+#include <winsock2.h>
+#include <iphlpapi.h>
+
+#define ETHER_ADDR_LEN 6
+
+my_bool my_gethwaddr(uchar *to)
+{
+ my_bool res= 1;
+
+ IP_ADAPTER_INFO *info= NULL;
+ ULONG info_len= 0;
+
+ if (GetAdaptersInfo(info, &info_len) != ERROR_BUFFER_OVERFLOW)
+ goto err;
+
+ info= alloca(info_len);
+
+ if (GetAdaptersInfo(info, &info_len) != NO_ERROR)
+ goto err;
+
+ while (info && res)
+ {
+ if (info->Type == MIB_IF_TYPE_ETHERNET &&
+ info->AddressLength == ETHER_ADDR_LEN)
+ res= memcpy_and_test(to, info->Address, ETHER_ADDR_LEN);
+ }
+
+err:
+ return res;
+}
+
+#else /* neither FreeBSD nor linux not Windows */
/* just fail */
my_bool my_gethwaddr(uchar *to __attribute__((unused)))
{
@@ -114,7 +178,7 @@ int main(int argc __attribute__((unused)),char **argv)
printf("my_gethwaddr failed with errno %d\n", errno);
exit(1);
}
- for (i=0; i < sizeof(mac); i++)
+ for (i= 0; i < sizeof(mac); i++)
{
if (i) printf(":");
printf("%02x", mac[i]);
diff --git a/plugin/feedback/CMakeLists.txt b/plugin/feedback/CMakeLists.txt
new file mode 100644
index 00000000000..a94232a4698
--- /dev/null
+++ b/plugin/feedback/CMakeLists.txt
@@ -0,0 +1,11 @@
+INCLUDE("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake")
+
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/sql ${CMAKE_SOURCE_DIR}/regex
+ ${CMAKE_SOURCE_DIR}/extra/yassl/include)
+
+SET(FEEDBACK_SOURCES feedback.cc sender_thread.cc
+ url_base.cc url_http.cc utils.cc)
+
+SET(FEEDBACK_LIBS Ws2_32)
+
+MYSQL_PLUGIN(FEEDBACK)
diff --git a/plugin/feedback/Makefile.am b/plugin/feedback/Makefile.am
new file mode 100644
index 00000000000..7d2a61d593f
--- /dev/null
+++ b/plugin/feedback/Makefile.am
@@ -0,0 +1,18 @@
+pkgplugindir = $(pkglibdir)/plugin
+INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include \
+ -I$(top_srcdir)/regex -I$(top_srcdir)/sql
+
+EXTRA_LTLIBRARIES = feedback.la libfeedback.la
+pkgplugin_LTLIBRARIES = @plugin_feedback_shared_target@
+feedback_la_LDFLAGS = -module -rpath $(pkgplugindir) -L$(top_builddir)/libservices -lmysqlservices
+feedback_la_CXXFLAGS = -shared -DMYSQL_DYNAMIC_PLUGIN
+feedback_la_SOURCES = feedback.cc utils.cc url_base.cc url_http.cc \
+ sender_thread.cc
+
+noinst_LTLIBRARIES = @plugin_feedback_static_target@
+libfeedback_la_SOURCES= feedback.cc utils.cc url_base.cc url_http.cc \
+ sender_thread.cc
+
+noinst_HEADERS = feedback.h
+EXTRA_DIST = CMakeLists.txt plug.in
+
diff --git a/plugin/feedback/feedback.cc b/plugin/feedback/feedback.cc
new file mode 100644
index 00000000000..08464aec386
--- /dev/null
+++ b/plugin/feedback/feedback.cc
@@ -0,0 +1,373 @@
+/* Copyright (C) 2010 Sergei Golubchik and Monty Program Ab
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "feedback.h"
+
+/* MySQL functions/variables not declared in mysql_priv.h */
+int fill_variables(THD *thd, TABLE_LIST *tables, COND *cond);
+int fill_status(THD *thd, TABLE_LIST *tables, COND *cond);
+extern ST_SCHEMA_TABLE schema_tables[];
+
+namespace feedback {
+
+char server_uid_buf[SERVER_UID_SIZE+1]; ///< server uid will be written here
+
+/* backing store for system variables */
+static char *server_uid= server_uid_buf, *url;
+char *user_info;
+ulong send_timeout, send_retry_wait;
+
+/**
+ these three are used to communicate the shutdown signal to the
+ background thread
+*/
+pthread_mutex_t sleep_mutex;
+pthread_cond_t sleep_condition;
+volatile bool shutdown_plugin;
+static pthread_t sender_thread;
+
+Url **urls; ///< list of urls to send the report to
+uint url_count;
+
+ST_SCHEMA_TABLE *i_s_feedback; ///< table descriptor for our I_S table
+
+/*
+ the column names *must* match column names in GLOBAL_VARIABLES and
+ GLOBAL_STATUS tables otherwise condition pushdown below will not work
+*/
+static ST_FIELD_INFO feedback_fields[] =
+{
+ {"VARIABLE_NAME", 255, MYSQL_TYPE_STRING, 0, 0, 0, 0},
+ {"VARIABLE_VALUE", 1024, MYSQL_TYPE_STRING, 0, 0, 0, 0},
+ {0, 0, MYSQL_TYPE_NULL, 0, 0, 0, 0}
+};
+
+static COND * const OOM= (COND*)1;
+
+/**
+ Generate the COND tree for the condition pushdown
+
+ This function takes a list of strings and generates an Item tree
+ corresponding to the following expression:
+
+ field LIKE str1 OR field LIKE str2 OR field LIKE str3 OR ...
+
+ where 'field' is the first field in the table - VARIABLE_NAME field -
+ and str1, str2... are strings from the list.
+
+ This condition is used to filter the selected rows, emulating
+
+ SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE ...
+*/
+static COND* make_cond(THD *thd, TABLE_LIST *tables, LEX_STRING *filter)
+{
+ Item_cond_or *res= NULL;
+ Name_resolution_context nrc;
+ const char *db= tables->db, *table= tables->alias,
+ *field= tables->table->field[0]->field_name;
+ CHARSET_INFO *cs= &my_charset_latin1;
+
+ if (!filter->str)
+ return 0;
+
+ nrc.init();
+ nrc.resolve_in_table_list_only(tables);
+
+ res= new Item_cond_or();
+ if (!res)
+ return OOM;
+
+ for (; filter->str; filter++)
+ {
+ Item_field *fld= new Item_field(&nrc, db, table, field);
+ Item_string *pattern= new Item_string(filter->str, filter->length, cs);
+ Item_string *escape= new Item_string("\\", 1, cs);
+
+ if (!fld || !pattern || !escape)
+ return OOM;
+
+ Item_func_like *like= new Item_func_like(fld, pattern, escape, 0);
+
+ if (!like)
+ return OOM;
+
+ res->add(like);
+ }
+
+ if (res->fix_fields(thd, (Item**)&res))
+ return OOM;
+
+ return res;
+}
+
+/**
+ System variables that we want to see in the feedback report
+*/
+static LEX_STRING vars_filter[]= {
+ {C_STRING_WITH_LEN("auto\\_increment%")},
+ {C_STRING_WITH_LEN("binlog\\_format")},
+ {C_STRING_WITH_LEN("character\\_set\\_%")},
+ {C_STRING_WITH_LEN("collation%")},
+ {C_STRING_WITH_LEN("engine\\_condition\\_pushdown")},
+ {C_STRING_WITH_LEN("event\\_scheduler")},
+ {C_STRING_WITH_LEN("feedback\\_%")},
+ {C_STRING_WITH_LEN("ft\\_m%")},
+ {C_STRING_WITH_LEN("have\\_%")},
+ {C_STRING_WITH_LEN("%\\_size")},
+ {C_STRING_WITH_LEN("%\\_length%")},
+ {C_STRING_WITH_LEN("%\\_timeout")},
+ {C_STRING_WITH_LEN("large\\_%")},
+ {C_STRING_WITH_LEN("lc_time_names")},
+ {C_STRING_WITH_LEN("log")},
+ {C_STRING_WITH_LEN("log_bin")},
+ {C_STRING_WITH_LEN("log_output")},
+ {C_STRING_WITH_LEN("log_slow_queries")},
+ {C_STRING_WITH_LEN("log_slow_time")},
+ {C_STRING_WITH_LEN("lower_case%")},
+ {C_STRING_WITH_LEN("max_allowed_packet")},
+ {C_STRING_WITH_LEN("max_connections")},
+ {C_STRING_WITH_LEN("max_prepared_stmt_count")},
+ {C_STRING_WITH_LEN("max_sp_recursion_depth")},
+ {C_STRING_WITH_LEN("max_user_connections")},
+ {C_STRING_WITH_LEN("max_write_lock_count")},
+ {C_STRING_WITH_LEN("myisam_recover_options")},
+ {C_STRING_WITH_LEN("myisam_repair_threads")},
+ {C_STRING_WITH_LEN("myisam_stats_method")},
+ {C_STRING_WITH_LEN("myisam_use_mmap")},
+ {C_STRING_WITH_LEN("net\\_%")},
+ {C_STRING_WITH_LEN("new")},
+ {C_STRING_WITH_LEN("old%")},
+ {C_STRING_WITH_LEN("optimizer%")},
+ {C_STRING_WITH_LEN("profiling")},
+ {C_STRING_WITH_LEN("query_cache%")},
+ {C_STRING_WITH_LEN("secure_auth")},
+ {C_STRING_WITH_LEN("slow_launch_time")},
+ {C_STRING_WITH_LEN("sql%")},
+ {C_STRING_WITH_LEN("storage_engine")},
+ {C_STRING_WITH_LEN("sync_binlog")},
+ {C_STRING_WITH_LEN("table_definition_cache")},
+ {C_STRING_WITH_LEN("table_open_cache")},
+ {C_STRING_WITH_LEN("thread_handling")},
+ {C_STRING_WITH_LEN("time_zone")},
+ {C_STRING_WITH_LEN("timed_mutexes")},
+ {C_STRING_WITH_LEN("version%")},
+ {0, 0}
+};
+
+/**
+ Status variables that we want to see in the feedback report
+
+ (empty list = no WHERE condition)
+*/
+static LEX_STRING status_filter[]= {{0, 0}};
+
+/**
+ Fill our I_S table with data
+
+ This function works by invoking fill_variables() and
+ fill_status() of the corresponding I_S tables - to have
+ their data UNION-ed in the same target table.
+ After that it invokes our own fill_* functions
+ from the utils.cc - to get the data that aren't available in the
+ I_S.GLOBAL_VARIABLES and I_S.GLOBAL_STATUS.
+*/
+int fill_feedback(THD *thd, TABLE_LIST *tables, COND *unused)
+{
+ int res;
+ COND *cond;
+
+ tables->schema_table= schema_tables + SCH_GLOBAL_VARIABLES;
+ cond= make_cond(thd, tables, vars_filter);
+ res= (cond == OOM) ? 1 : fill_variables(thd, tables, cond);
+
+ tables->schema_table= schema_tables + SCH_GLOBAL_STATUS;
+ if (!res)
+ {
+ cond= make_cond(thd, tables, status_filter);
+ res= (cond == OOM) ? 1 : fill_status(thd, tables, cond);
+ }
+
+ tables->schema_table= i_s_feedback;
+ res= res || fill_plugin_version(thd, tables)
+ || fill_misc_data(thd, tables)
+ || fill_linux_info(thd, tables);
+
+ return res;
+}
+
+/**
+ plugin initialization function
+*/
+static int init(void *p)
+{
+ i_s_feedback= (ST_SCHEMA_TABLE*) p;
+ /* initialize the I_S descriptor structure */
+ i_s_feedback->fields_info= feedback_fields; ///< field descriptor
+ i_s_feedback->fill_table= fill_feedback; ///< how to fill the I_S table
+ i_s_feedback->idx_field1 = 0; ///< virtual index on the 1st col
+
+ if (calculate_server_uid(server_uid_buf))
+ return 1;
+
+ prepare_linux_info();
+
+ url_count= 0;
+ if (*url)
+ {
+ // now we split url on spaces and store them in Url objects
+ int slot;
+ char *s, *e;
+
+ for (s= url, url_count= 1; *s; s++)
+ if (*s == ' ')
+ url_count++;
+
+ urls= (Url **)my_malloc(url_count*sizeof(Url*), MYF(MY_WME));
+ if (!urls)
+ return 1;
+
+ for (s= url, e = url+1, slot= 0; e[-1]; e++)
+ if (*e == 0 || *e == ' ')
+ {
+ if (e > s && (urls[slot]= Url::create(s, e - s)))
+ slot++;
+ else
+ {
+ if (e > s)
+ sql_print_error("feedback plugin: invalid url '%.*s'", (int)(e-s), s);
+ url_count--;
+ }
+ s= e + 1;
+ }
+
+ // create a background thread to handle urls, if any
+ if (url_count)
+ {
+ pthread_mutex_init(&sleep_mutex, 0);
+ pthread_cond_init(&sleep_condition, 0);
+ shutdown_plugin= false;
+
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+ if (pthread_create(&sender_thread, &attr, background_thread, 0) != 0)
+ {
+ sql_print_error("feedback plugin: failed to start a background thread");
+ return 1;
+ }
+ }
+ else
+ my_free(urls, MYF(0));
+ }
+
+ return 0;
+}
+
+/**
+ plugin deinitialization function
+*/
+static int free(void *p)
+{
+ if (url_count)
+ {
+ pthread_mutex_lock(&sleep_mutex);
+ shutdown_plugin= true;
+ pthread_cond_signal(&sleep_condition);
+ pthread_mutex_unlock(&sleep_mutex);
+ pthread_join(sender_thread, NULL);
+
+ pthread_mutex_destroy(&sleep_mutex);
+ pthread_cond_destroy(&sleep_condition);
+
+ for (uint i= 0; i < url_count; i++)
+ delete urls[i];
+ my_free(urls, MYF(0));
+ }
+ return 0;
+}
+
+#ifdef HAVE_OPENSSL
+#define DEFAULT_PROTO "https://"
+#else
+#define DEFAULT_PROTO "http://"
+#endif
+
+static MYSQL_SYSVAR_STR(server_uid, server_uid,
+ PLUGIN_VAR_READONLY | PLUGIN_VAR_NOCMDOPT,
+ "Automatically calculated server unique id hash.", NULL, NULL, 0);
+static MYSQL_SYSVAR_STR(user_info, user_info,
+ PLUGIN_VAR_READONLY | PLUGIN_VAR_RQCMDARG,
+ "User specified string that will be included in the feedback report.",
+ NULL, NULL, "");
+static MYSQL_SYSVAR_STR(url, url, PLUGIN_VAR_READONLY | PLUGIN_VAR_RQCMDARG,
+ "Space separated URLs to send the feedback report to.", NULL, NULL,
+ DEFAULT_PROTO "mariadb.org/feedback_plugin/post");
+static MYSQL_SYSVAR_ULONG(send_timeout, send_timeout, PLUGIN_VAR_RQCMDARG,
+ "Timeout (in seconds) for the sending the report.",
+ NULL, NULL, 60, 1, 60*60*24, 1);
+static MYSQL_SYSVAR_ULONG(send_retry_wait, send_retry_wait, PLUGIN_VAR_RQCMDARG,
+ "Wait this many seconds before retrying a failed send.",
+ NULL, NULL, 60, 1, 60*60*24, 1);
+
+static struct st_mysql_sys_var* settings[] = {
+ MYSQL_SYSVAR(server_uid),
+ MYSQL_SYSVAR(user_info),
+ MYSQL_SYSVAR(url),
+ MYSQL_SYSVAR(send_timeout),
+ MYSQL_SYSVAR(send_retry_wait),
+ NULL
+};
+
+
+static struct st_mysql_information_schema feedback =
+{ MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION };
+
+} // namespace feedback
+
+mysql_declare_plugin(feedback)
+{
+ MYSQL_INFORMATION_SCHEMA_PLUGIN,
+ &feedback::feedback,
+ "FEEDBACK",
+ "Sergei Golubchik",
+ "MariaDB User Feedback Plugin",
+ PLUGIN_LICENSE_GPL,
+ feedback::init,
+ feedback::free,
+ 0x0100,
+ NULL,
+ feedback::settings,
+ NULL
+}
+mysql_declare_plugin_end;
+#ifdef MARIA_PLUGIN_INTERFACE_VERSION
+maria_declare_plugin(feedback)
+{
+ MYSQL_INFORMATION_SCHEMA_PLUGIN,
+ &feedback::feedback,
+ "FEEDBACK",
+ "Sergei Golubchik",
+ "MariaDB User Feedback Plugin",
+ PLUGIN_LICENSE_GPL,
+ feedback::init,
+ feedback::free,
+ 0x0100,
+ NULL,
+ feedback::settings,
+ "1.0",
+ MariaDB_PLUGIN_MATURITY_BETA
+}
+mysql_declare_plugin_end;
+#endif
diff --git a/plugin/feedback/feedback.h b/plugin/feedback/feedback.h
new file mode 100644
index 00000000000..60ef72eed84
--- /dev/null
+++ b/plugin/feedback/feedback.h
@@ -0,0 +1,67 @@
+/* Copyright (C) 2010 Sergei Golubchik and Monty Program Ab
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#define MYSQL_SERVER
+#include <mysql_priv.h>
+
+namespace feedback {
+
+int fill_feedback(THD *thd, TABLE_LIST *tables, COND *cond);
+int fill_plugin_version(THD *thd, TABLE_LIST *tables);
+int fill_misc_data(THD *thd, TABLE_LIST *tables);
+int fill_linux_info(THD *thd, TABLE_LIST *tables);
+
+static const int SERVER_UID_SIZE= 29;
+extern char server_uid_buf[SERVER_UID_SIZE+1], *user_info;
+int calculate_server_uid(char *);
+int prepare_linux_info();
+
+extern ST_SCHEMA_TABLE *i_s_feedback;
+
+extern ulong send_timeout, send_retry_wait;
+
+pthread_handler_t background_thread(void *arg);
+
+/**
+ The class for storing urls to send report data to.
+
+ Constructors are private, the object should be created with create() method.
+ send() method does the actual sending.
+*/
+class Url {
+ protected:
+ Url(LEX_STRING &url_arg) : full_url(url_arg) {}
+ const LEX_STRING full_url;
+
+ public:
+ virtual ~Url() { my_free(full_url.str, MYF(0)); }
+
+ const char *url() { return full_url.str; }
+ size_t url_length() { return full_url.length; }
+ virtual int send(const char* data, size_t data_length) = 0;
+
+ static Url* create(const char *url, size_t url_length);
+};
+
+extern Url **urls;
+extern uint url_count;
+
+/* these are used to communicate with the background thread */
+extern pthread_mutex_t sleep_mutex;
+extern pthread_cond_t sleep_condition;
+extern volatile bool shutdown_plugin;
+
+} // namespace feedback
+
diff --git a/plugin/feedback/plug.in b/plugin/feedback/plug.in
new file mode 100644
index 00000000000..88a4448321d
--- /dev/null
+++ b/plugin/feedback/plug.in
@@ -0,0 +1,28 @@
+MYSQL_PLUGIN(feedback,[MariaDB User Feedback Plugin],
+ [MariaDB User Feedback Plugin])
+
+dnl Although it's not exactly obvious, top-level CMakeLists.txt parses plug.in
+dnl files, in particular looking for what the library name should be. It uses
+dnl regexp that matches MYSQL_PLUGIN_DYNAMIC or MYSQL_PLUGIN_STATIC, followed
+dnl by an open parenthesys, and the plugin name. Having engine name enclosed in
+dnl square brackets below causes this regexp to fail and as a result feedback
+dnl plugin will not be considered for dynamic builds on Windows.
+dnl Unfortunately, feedback cannot be built dynamically on Windows, because it
+dnl needs to access server internals that aren't designed for plugin use and
+dnl aren't marked with MYSQL_PLUGIN_IMPORT.
+MYSQL_PLUGIN_DYNAMIC([feedback], [feedback.la])
+ifelse(index(AC_PACKAGE_NAME, [MariaDB]), -1, [], [
+
+dnl MariaDB and MySQL define static plugins differently.
+dnl I only support MariaDB here, for now.
+MYSQL_PLUGIN_STATIC(feedback, [libfeedback.la])
+
+])
+
+dnl MariaDB before 5.5 needs this define:
+MYSQL_PLUGIN_DEFINE(feedback, [WITH_FEEDBACK_PLUGIN])
+
+MYSQL_PLUGIN_ACTIONS(feedback, [
+ AC_CHECK_HEADERS([netdb.h sys/utsname.h])
+])
+
diff --git a/plugin/feedback/sender_thread.cc b/plugin/feedback/sender_thread.cc
new file mode 100644
index 00000000000..bcfb0348e11
--- /dev/null
+++ b/plugin/feedback/sender_thread.cc
@@ -0,0 +1,301 @@
+/* Copyright (C) 2010 Sergei Golubchik and Monty Program Ab
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "feedback.h"
+#include <time.h>
+
+namespace feedback {
+
+static THD *thd= 0; ///< background thread thd
+static my_thread_id thd_thread_id; ///< its thread_id
+
+static size_t needed_size= 20480;
+
+static const time_t startup_interval= 60*5; ///< in seconds (5 minutes)
+static const time_t first_interval= 60*60*24; ///< in seconds (one day)
+static const time_t interval= 60*60*24*7; ///< in seconds (one week)
+
+/**
+ reads the rows from a table and puts them, concatenated, in a String
+
+ @note
+ 1. only supports two column tables - no less, no more.
+ 2. it emulates mysql -e "select * from..." and thus it separates
+ columns with \t and starts the output with column names.
+*/
+static int table_to_string(TABLE *table, String *result)
+{
+ bool res;
+ char buff1[MAX_FIELD_WIDTH], buff2[MAX_FIELD_WIDTH];
+ String str1(buff1, sizeof(buff1), system_charset_info);
+ String str2(buff2, sizeof(buff2), system_charset_info);
+
+ res= table->file->ha_rnd_init(1);
+
+ dbug_tmp_use_all_columns(table, table->read_set);
+
+ while(!res && !table->file->ha_rnd_next(table->record[0]))
+ {
+ table->field[0]->val_str(&str1);
+ table->field[1]->val_str(&str2);
+ if (result->reserve(str1.length() + str2.length() + 3))
+ res= 1;
+ else
+ {
+ result->qs_append(str1.ptr(), str1.length());
+ result->qs_append('\t');
+ result->qs_append(str2.ptr(), str2.length());
+ result->qs_append('\n');
+ }
+ }
+
+ res = res || result->append('\n');
+
+ /*
+ Note, "|=" and not "||" - because we want to call ha_rnd_end()
+ even if res is already 1.
+ */
+ res |= table->file->ha_rnd_end();
+
+ return res;
+}
+
+/**
+ Initialize the THD and TABLE_LIST
+
+ The structures must be sufficiently initialized for create_tmp_table()
+ and fill_feedback() to work.
+*/
+static int prepare_for_fill(TABLE_LIST *tables)
+{
+ /*
+ Add our thd to the list, for it to be visible in SHOW PROCESSLIST.
+ But don't generate thread_id every time - use the saved value
+ (every increment of global thread_id counts as a new connection
+ in SHOW STATUS and we want to avoid skewing the statistics)
+ */
+ thd->thread_id= thd->variables.pseudo_thread_id= thd_thread_id;
+ pthread_mutex_lock(&LOCK_thread_count);
+ thread_count++;
+ threads.append(thd);
+ pthread_mutex_unlock(&LOCK_thread_count);
+ thd->thread_stack= (char*) &tables;
+ if (thd->store_globals())
+ return 1;
+
+ thd->mysys_var->current_cond= &sleep_condition;
+ thd->mysys_var->current_mutex= &sleep_mutex;
+ thd->proc_info="feedback";
+ thd->command=COM_SLEEP;
+ thd->version=refresh_version;
+ thd->system_thread= SYSTEM_THREAD_EVENT_WORKER; // whatever
+ thd->set_time();
+ thd->init_for_queries();
+ thd->real_id= pthread_self();
+ thd->db= NULL;
+ thd->db_length= 0;
+ thd->security_ctx->host_or_ip= "";
+ thd->security_ctx->db_access= DB_ACLS;
+ thd->security_ctx->master_access= ~NO_ACCESS;
+ bzero((char*) &thd->net, sizeof(thd->net));
+ lex_start(thd);
+ mysql_init_select(thd->lex);
+
+ tables->init_one_table(INFORMATION_SCHEMA_NAME.str,
+ i_s_feedback->table_name, TL_READ);
+ tables->schema_table= i_s_feedback;
+ tables->table= i_s_feedback->create_table(thd, tables);
+ if (!tables->table)
+ return 1;
+
+ tables->table->pos_in_table_list= tables;
+
+ return 0;
+}
+
+/**
+ Try to detect if this thread is going down
+
+ which can happen for different reasons:
+ * plugin is being unloaded
+ * mysqld server is being shut down
+ * the thread is being killed
+
+*/
+static bool going_down()
+{
+ return shutdown_plugin || shutdown_in_progress || (thd && thd->killed);
+}
+
+/**
+ just like sleep, but waits on a condition and checks "plugin shutdown" status
+*/
+static int slept_ok(time_t sec)
+{
+ struct timespec abstime;
+ int ret= 0;
+
+ set_timespec(abstime, sec);
+
+ pthread_mutex_lock(&sleep_mutex);
+ while (!going_down() && ret != ETIMEDOUT)
+ ret= pthread_cond_timedwait(&sleep_condition, &sleep_mutex, &abstime);
+ pthread_mutex_unlock(&sleep_mutex);
+
+ return !going_down();
+}
+
+/**
+ create a feedback report and send it to all specified urls
+
+ If "when" argument is not null, only it and the server uid are sent.
+ Otherwise a full report is generated.
+*/
+static void send_report(const char *when)
+{
+ TABLE_LIST tables;
+ String str;
+ int i, last_todo;
+ Url **todo= (Url**)alloca(url_count*sizeof(Url*));
+
+ str.alloc(needed_size); // preallocate it to avoid many small mallocs
+
+ /*
+ on startup and shutdown the server may not be completely
+ initialized, and full report won't work.
+ We send a short status notice only.
+ */
+ if (when)
+ {
+ str.length(0);
+ str.append(STRING_WITH_LEN("FEEDBACK_SERVER_UID"));
+ str.append('\t');
+ str.append(server_uid_buf);
+ str.append('\n');
+ str.append(STRING_WITH_LEN("FEEDBACK_WHEN"));
+ str.append('\t');
+ str.append(when);
+ str.append('\n');
+ str.append(STRING_WITH_LEN("FEEDBACK_USER_INFO"));
+ str.append('\t');
+ str.append(user_info);
+ str.append('\n');
+ str.append('\n');
+ }
+ else
+ {
+ /*
+ otherwise, prepare the THD and TABLE_LIST,
+ create and fill the temporary table with data just like
+ SELECT * FROM IFROEMATION_SCHEMA.feedback is doing,
+ read and concatenate table data into a String.
+ */
+ if (!(thd= new THD()))
+ return;
+
+ if (prepare_for_fill(&tables))
+ goto ret;
+
+ if (fill_feedback(thd, &tables, NULL))
+ goto ret;
+
+ if (table_to_string(tables.table, &str))
+ goto ret;
+
+ needed_size= (size_t)(str.length() * 1.1);
+
+ free_tmp_table(thd, tables.table);
+ tables.table= 0;
+ }
+
+ /*
+ Try to send the report on every url from the list, remove url on success,
+ keep failed in the list. Repeat until the list is empty.
+ */
+ memcpy(todo, urls, url_count*sizeof(Url*));
+ last_todo= url_count - 1;
+ do
+ {
+ for (i= 0; i <= last_todo;)
+ {
+ Url *url= todo[i];
+
+ if (thd) // for nicer SHOW PROCESSLIST
+ thd->set_query(const_cast<char*>(url->url()), url->url_length());
+
+ if (url->send(str.ptr(), str.length()))
+ i++;
+ else
+ todo[i]= todo[last_todo--];
+ }
+ if (last_todo < 0)
+ break;
+ } while (slept_ok(send_retry_wait)); // wait a little bit before retrying
+
+ret:
+ if (thd)
+ {
+ if (tables.table)
+ free_tmp_table(thd, tables.table);
+ /*
+ clean up, free the thd.
+ reset all thread local status variables to minimize
+ the effect of the background thread on SHOW STATUS.
+ */
+ pthread_mutex_lock(&LOCK_thread_count);
+ bzero(&thd->status_var, sizeof(thd->status_var));
+ thread_count--;
+ thd->killed= KILL_CONNECTION;
+ pthread_cond_broadcast(&COND_thread_count);
+ pthread_mutex_unlock(&LOCK_thread_count);
+ delete thd;
+ thd= 0;
+ }
+}
+
+/**
+ background sending thread
+*/
+pthread_handler_t background_thread(void *arg __attribute__((unused)))
+{
+ if (my_thread_init())
+ return 0;
+
+ pthread_mutex_lock(&LOCK_thread_count);
+ thd_thread_id= thread_id++;
+ pthread_mutex_unlock(&LOCK_thread_count);
+
+ if (slept_ok(startup_interval))
+ {
+ send_report("startup");
+
+ if (slept_ok(first_interval))
+ {
+ send_report(NULL);
+
+ while(slept_ok(interval))
+ send_report(NULL);
+ }
+
+ send_report("shutdown");
+ }
+
+ my_thread_end();
+ pthread_exit(0);
+ return 0;
+}
+
+} // namespace feedback
+
diff --git a/plugin/feedback/url_base.cc b/plugin/feedback/url_base.cc
new file mode 100644
index 00000000000..38b2ca86e9f
--- /dev/null
+++ b/plugin/feedback/url_base.cc
@@ -0,0 +1,51 @@
+/* Copyright (C) 2010 Sergei Golubchik and Monty Program Ab
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "feedback.h"
+
+namespace feedback {
+
+Url* http_create(const char *url, size_t url_length);
+
+/**
+ creates an Url object out of an url, if possible.
+
+ This is done by invoking corresponding creator functions
+ of the derived classes, until the first not NULL result.
+*/
+Url* Url::create(const char *url, size_t url_length)
+{
+ url= my_strndup(url, url_length, MYF(MY_WME));
+
+ if (!url)
+ return NULL;
+
+ Url *self= http_create(url, url_length);
+
+ /*
+ here we can add
+
+ if (!self) self= smtp_create(url, url_length);
+ if (!self) self= tftp_create(url, url_length);
+ etc
+ */
+
+ if (!self)
+ my_free(const_cast<char*>(url), MYF(0));
+
+ return self;
+}
+
+} // namespace feedback
diff --git a/plugin/feedback/url_http.cc b/plugin/feedback/url_http.cc
new file mode 100644
index 00000000000..de2877b0274
--- /dev/null
+++ b/plugin/feedback/url_http.cc
@@ -0,0 +1,303 @@
+/* Copyright (C) 2010 Sergei Golubchik and Monty Program Ab
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "feedback.h"
+
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+
+#ifdef _WIN32
+#undef VOID
+#define VOID void
+#include <ws2tcpip.h>
+#define addrinfo ADDRINFOA
+#endif
+
+namespace feedback {
+
+static const uint FOR_READING= 0;
+static const uint FOR_WRITING= 1;
+
+#ifdef MARIADB_BASE_VERSION
+#define ssl_connect(A,B,C,D) sslconnect(A,B,C,D)
+#else
+#define ssl_connect(A,B,C,D) sslconnect(A,B,C)
+#endif
+
+/**
+ implementation of the Url class that sends the data via HTTP POST request.
+
+ Both http:// and https:// protocols are supported.
+*/
+class Url_http: public Url {
+ protected:
+ const LEX_STRING host, port, path;
+ bool ssl;
+
+ Url_http(LEX_STRING &url_arg, LEX_STRING &host_arg,
+ LEX_STRING &port_arg, LEX_STRING &path_arg, bool ssl_arg) :
+ Url(url_arg), host(host_arg), port(port_arg), path(path_arg), ssl(ssl_arg)
+ {}
+ ~Url_http()
+ {
+ my_free(host.str, MYF(0));
+ my_free(port.str, MYF(0));
+ my_free(path.str, MYF(0));
+ }
+
+ public:
+ int send(const char* data, size_t data_length);
+
+ friend Url* http_create(const char *url, size_t url_length);
+};
+
+/**
+ create a Url_http object out of the url, if possible.
+
+ @note
+ Arbitrary limitations here.
+
+ The url must be http[s]://hostname[:port]/path
+ No username:password@ or ?script=parameters are supported.
+
+ But it's ok. This is not a generic purpose www browser - it only needs to be
+ good enough to POST the data to mariadb.org.
+*/
+Url* http_create(const char *url, size_t url_length)
+{
+ const char *s;
+ LEX_STRING full_url= {const_cast<char*>(url), url_length};
+ LEX_STRING host, port, path;
+ bool ssl= false;
+
+ if (is_prefix(url, "http://"))
+ s= url + 7;
+#ifdef HAVE_OPENSSL
+ else if (is_prefix(url, "https://"))
+ {
+ ssl= true;
+ s= url + 8;
+ }
+#endif
+ else
+ return NULL;
+
+ for (url= s; *s && *s != ':' && *s != '/'; s++) /* no-op */;
+ host.str= const_cast<char*>(url);
+ host.length= s-url;
+
+ if (*s == ':')
+ {
+ for (url= ++s; *s && *s >= '0' && *s <= '9'; s++) /* no-op */;
+ port.str= const_cast<char*>(url);
+ port.length= s-url;
+ }
+ else
+ {
+ if (ssl)
+ {
+ port.str= const_cast<char*>("443");
+ port.length=3;
+ }
+ else
+ {
+ port.str= const_cast<char*>("80");
+ port.length=2;
+ }
+ }
+
+ if (*s == 0)
+ {
+ path.str= const_cast<char*>("/");
+ path.length= 1;
+ }
+ else
+ {
+ path.str= const_cast<char*>(s);
+ path.length= strlen(s);
+ }
+ if (!host.length || !port.length || path.str[0] != '/')
+ return NULL;
+
+ host.str= my_strndup(host.str, host.length, MYF(MY_WME));
+ port.str= my_strndup(port.str, port.length, MYF(MY_WME));
+ path.str= my_strndup(path.str, path.length, MYF(MY_WME));
+
+ if (!host.str || !port.str || !path.str)
+ {
+ my_free(host.str, MYF(MY_ALLOW_ZERO_PTR));
+ my_free(port.str, MYF(MY_ALLOW_ZERO_PTR));
+ my_free(path.str, MYF(MY_ALLOW_ZERO_PTR));
+ return NULL;
+ }
+
+ return new Url_http(full_url, host, port, path, ssl);
+}
+
+/* do the vio_write and check that all data were sent ok */
+#define write_check(VIO, DATA, LEN) \
+ (vio_write((VIO), (uchar*)(DATA), (LEN)) != (LEN))
+
+int Url_http::send(const char* data, size_t data_length)
+{
+ my_socket fd= INVALID_SOCKET;
+ char buf[1024];
+ uint len;
+
+ addrinfo *addrs, *addr, filter= {0, AF_UNSPEC, SOCK_STREAM, 6, 0, 0, 0, 0};
+ int res= getaddrinfo(host.str, port.str, &filter, &addrs);
+
+ if (res)
+ {
+ sql_print_error("feedback plugin: getaddrinfo() failed for url '%s': %s",
+ full_url.str, gai_strerror(res));
+ return 1;
+ }
+
+ for (addr= addrs; addr != NULL; addr= addr->ai_next)
+ {
+ fd= socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
+ if (fd == INVALID_SOCKET)
+ continue;
+
+ if (connect(fd, addr->ai_addr, addr->ai_addrlen) == 0)
+ break;
+
+ closesocket(fd);
+ }
+
+ freeaddrinfo(addrs);
+
+ if (fd == INVALID_SOCKET)
+ {
+ sql_print_error("feedback plugin: could not connect for url '%s'",
+ full_url.str);
+ return 1;
+ }
+
+ Vio *vio= vio_new(fd, VIO_TYPE_TCPIP, 0);
+ if (!vio)
+ {
+ sql_print_error("feedback plugin: vio_new failed for url '%s'",
+ full_url.str);
+ closesocket(fd);
+ return 1;
+ }
+
+#ifdef HAVE_OPENSSL
+ struct st_VioSSLFd *ssl_fd;
+ if (ssl)
+ {
+ buf[0]= 0;
+ if (!(ssl_fd= new_VioSSLConnectorFd(0, 0, 0, 0, 0)) ||
+ ssl_connect(ssl_fd, vio, send_timeout, buf))
+ {
+ sql_print_error("feedback plugin: ssl failed for url '%s' %s",
+ full_url.str, buf);
+ if (ssl_fd)
+ free_vio_ssl_acceptor_fd(ssl_fd);
+ closesocket(fd);
+ vio_delete(vio);
+ return 1;
+ }
+ }
+#endif
+
+ static const LEX_STRING boundary=
+ { C_STRING_WITH_LEN("----------------------------ba4f3696b39f") };
+ static const LEX_STRING header=
+ { C_STRING_WITH_LEN("\r\n"
+ "Content-Disposition: form-data; name=\"data\"; filename=\"-\"\r\n"
+ "Content-Type: application/octet-stream\r\n\r\n")
+ };
+
+ len= my_snprintf(buf, sizeof(buf),
+ "POST %s HTTP/1.0\r\n"
+ "User-Agent: MariaDB User Feedback Plugin\r\n"
+ "Host: %s:%s\r\n"
+ "Accept: */*\r\n"
+ "Content-Length: %u\r\n"
+ "Content-Type: multipart/form-data; boundary=%s\r\n"
+ "\r\n",
+ path.str, host.str, port.str,
+ (uint)(2*boundary.length + header.length + data_length + 4),
+ boundary.str + 2);
+
+ vio_timeout(vio, FOR_READING, send_timeout);
+ vio_timeout(vio, FOR_WRITING, send_timeout);
+ res = write_check(vio, buf, len)
+ || write_check(vio, boundary.str, boundary.length)
+ || write_check(vio, header.str, header.length)
+ || write_check(vio, data, data_length)
+ || write_check(vio, boundary.str, boundary.length)
+ || write_check(vio, "--\r\n", 4);
+
+ if (res)
+ sql_print_error("feedback plugin: failed to send report to '%s'",
+ full_url.str);
+ else
+ {
+ sql_print_information("feedback plugin: report to '%s' was sent",
+ full_url.str);
+
+ /*
+ if the data were send successfully, read the reply.
+ Extract the first string between <h1>...</h1> tags
+ and put it as a server reply into the error log.
+ */
+ len= vio_read(vio, (uchar*)buf, sizeof(buf)-1);
+ if (len && len < sizeof(buf))
+ {
+ char *from;
+
+ buf[len+1]= 0; // safety
+
+ if ((from= strstr(buf, "<h1>")))
+ {
+ from+= 4;
+ char *to= strstr(from, "</h1>");
+ if (to)
+ *to= 0;
+ else
+ from= NULL;
+ }
+ if (from)
+ sql_print_information("feedback plugin: server replied '%s'", from);
+ else
+ sql_print_warning("feedback plugin: failed to parse server reply");
+ }
+ else
+ {
+ res= 1;
+ sql_print_error("feedback plugin: failed to read server reply");
+ }
+ }
+
+ vio_delete(vio);
+
+#ifdef HAVE_OPENSSL
+ if (ssl)
+ {
+ SSL_CTX_free(ssl_fd->ssl_context);
+ my_free(ssl_fd, MYF(0));
+ }
+#endif
+
+ return res;
+}
+
+} // namespace feedback
+
diff --git a/plugin/feedback/utils.cc b/plugin/feedback/utils.cc
new file mode 100644
index 00000000000..f32b527c052
--- /dev/null
+++ b/plugin/feedback/utils.cc
@@ -0,0 +1,392 @@
+/* Copyright (C) 2010 Sergei Golubchik and Monty Program Ab
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "feedback.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <base64.h>
+#include <sha1.h>
+
+#if defined (_WIN32)
+#define HAVE_SYS_UTSNAME_H
+
+#ifndef VER_SUITE_WH_SERVER
+#define VER_SUITE_WH_SERVER 0x00008000
+#endif
+
+struct utsname {
+ char sysname[16]; // Name of this implementation of the operating system.
+ char nodename[16]; // Name of this node within the communications
+ // network to which this node is attached, if any.
+ char release[16]; // Current release level of this implementation.
+ char version[256]; // Current version level of this release.
+ char machine[16]; // Name of the hardware type on which the system is running.
+};
+
+/* Get commonly used name for Windows version */
+static const char *get_os_version_name(OSVERSIONINFOEX *ver)
+{
+ DWORD major = ver->dwMajorVersion;
+ DWORD minor = ver->dwMinorVersion;
+
+ if (major == 6 && minor == 1)
+ {
+ return (ver->wProductType == VER_NT_WORKSTATION)?
+ "Windows 7":"Windows Server 2008 R2";
+ }
+ if (major == 6 && minor == 0)
+ {
+ return (ver->wProductType == VER_NT_WORKSTATION)?
+ "Windows Vista":"Windows Server 2008";
+ }
+ if (major == 5 && minor == 2)
+ {
+ if (GetSystemMetrics(SM_SERVERR2) != 0)
+ return "Windows Server 2003 R2";
+ if (ver->wSuiteMask & VER_SUITE_WH_SERVER)
+ return "Windows Home Server";
+ SYSTEM_INFO sysinfo;
+ GetSystemInfo(&sysinfo);
+ if (ver->wProductType == VER_NT_WORKSTATION &&
+ sysinfo.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64)
+ return "Windows XP Professional x64 Edition";
+
+ return "Windows Server 2003";
+ }
+ if (major == 5 && minor == 1)
+ return "Windows XP";
+ if (major == 5 && minor == 0)
+ return "Windows 2000";
+
+ return "";
+}
+
+
+static int uname(struct utsname *buf)
+{
+ OSVERSIONINFOEX ver;
+ ver.dwOSVersionInfoSize = (DWORD)sizeof(ver);
+ if (!GetVersionEx((OSVERSIONINFO *)&ver))
+ return -1;
+
+ buf->nodename[0]= 0;
+ strcpy(buf->sysname, "Windows");
+ sprintf(buf->release, "%d.%d", ver.dwMajorVersion, ver.dwMinorVersion);
+
+ const char *version_str= get_os_version_name(&ver);
+ if(version_str && version_str[0])
+ sprintf(buf->version, "%s %s",version_str, ver.szCSDVersion);
+ else
+ sprintf(buf->version, "%s", ver.szCSDVersion);
+
+#ifdef _WIN64
+ strcpy(buf->machine, "x64");
+#else
+ BOOL isX64;
+ if (IsWow64Process(GetCurrentProcess(), &isX64) && isX64)
+ strcpy(buf->machine, "x64");
+ else
+ strcpy(buf->machine,"x86");
+#endif
+ return 0;
+}
+
+#elif defined(HAVE_SYS_UTSNAME_H)
+#include <sys/utsname.h>
+#endif
+
+#ifdef HAVE_SYS_UTSNAME_H
+static bool have_ubuf= false;
+static struct utsname ubuf;
+#endif
+
+#ifdef TARGET_OS_LINUX
+#include <glob.h>
+static bool have_distribution= false;
+static char distribution[256];
+
+static const char *masks[]= {
+ "/etc/*-version", "/etc/*-release",
+ "/etc/*_version", "/etc/*_release"
+};
+#endif
+
+bool schema_table_store_record(THD *thd, TABLE *table);
+
+namespace feedback {
+
+/*
+ convenience macros for inserting rows into I_S table.
+*/
+#define INSERT2(NAME,LEN,VALUE) \
+ do { \
+ table->field[0]->store(NAME, LEN, system_charset_info); \
+ table->field[1]->store VALUE; \
+ if (schema_table_store_record(thd, table)) \
+ return 1; \
+ } while (0)
+
+#define INSERT1(NAME,VALUE) \
+ do { \
+ table->field[0]->store(NAME, sizeof(NAME)-1, system_charset_info); \
+ table->field[1]->store VALUE; \
+ if (schema_table_store_record(thd, table)) \
+ return 1; \
+ } while (0)
+
+static const bool UNSIGNED= true; ///< used below when inserting integers
+
+/**
+ callback for fill_plugin_version() - insert a plugin name and its version
+*/
+static my_bool show_plugins(THD *thd, plugin_ref plugin, void *arg)
+{
+ TABLE *table= (TABLE*) arg;
+ char version[20];
+ size_t version_len;
+
+ version_len= my_snprintf(version, sizeof(version), "%d.%d",
+ (plugin_decl(plugin)->version) >> 8,
+ (plugin_decl(plugin)->version) & 0xff);
+
+ INSERT2(plugin_name(plugin)->str, plugin_name(plugin)->length,
+ (version, version_len, system_charset_info));
+
+ return 0;
+}
+
+/**
+ inserts all plugins and their versions into I_S.FEEDBACK
+*/
+int fill_plugin_version(THD *thd, TABLE_LIST *tables)
+{
+ return plugin_foreach_with_mask(thd, show_plugins, MYSQL_ANY_PLUGIN,
+ ~PLUGIN_IS_FREED, tables->table);
+}
+
+#if defined(_SC_PAGE_SIZE) && !defined(_SC_PAGESIZE)
+#define _SC_PAGESIZE _SC_PAGE_SIZE
+#endif
+
+/**
+ return the amount of physical memory
+*/
+static ulonglong my_getphysmem()
+{
+ ulonglong pages= 0;
+#ifdef _SC_PHYS_PAGES
+ pages= sysconf(_SC_PHYS_PAGES);
+#else
+ return 0;
+#endif
+
+#ifdef _SC_PAGESIZE
+ return pages * sysconf(_SC_PAGESIZE);
+#endif
+#ifdef _WIN32
+ MEMORYSTATUSEX memstatus;
+ memstatus.dwLength= sizeof(memstatus);
+ GlobalMemoryStatusEx(&memstatus);
+ return memstatus.ullTotalPhys;
+#else
+ return pages * my_getpagesize();
+#endif
+}
+
+/* get the number of (online) CPUs */
+int my_getncpus()
+{
+#ifdef _SC_NPROCESSORS_ONLN
+ return sysconf(_SC_NPROCESSORS_ONLN);
+#elif defined(__WIN__)
+ SYSTEM_INFO sysinfo;
+ GetSystemInfo(&sysinfo);
+ return sysinfo.dwNumberOfProcessors;
+#else
+ return 0;
+#endif
+}
+
+/**
+ Find the version of the kernel and the linux distribution
+*/
+int prepare_linux_info()
+{
+#ifdef HAVE_SYS_UTSNAME_H
+ have_ubuf= (uname(&ubuf) != -1);
+#endif
+
+#ifdef TARGET_OS_LINUX
+ /*
+ let's try to find what linux distribution it is
+ we read *[-_]{release,version} file in /etc.
+
+ Either it will be /etc/lsb-release, such as
+
+ ==> /etc/lsb-release <==
+ DISTRIB_ID=Ubuntu
+ DISTRIB_RELEASE=8.04
+ DISTRIB_CODENAME=hardy
+ DISTRIB_DESCRIPTION="Ubuntu 8.04.4 LTS"
+
+ Or a one-liner with the description (/etc/SuSE-release has more
+ than one line, but the description is the first, so it can be
+ treated as a one-liner).
+
+ We'll read lsb-release first, and if it's not found will search
+ for other files (*-version *-release *_version *_release)
+*/
+ int fd;
+ have_distribution= false;
+ if ((fd= my_open("/etc/lsb-release", O_RDONLY, MYF(0))) != -1)
+ {
+ /* Cool, LSB-compliant distribution! */
+ size_t len= my_read(fd, (uchar*)distribution, sizeof(distribution)-1, MYF(0));
+ my_close(fd, MYF(0));
+ if (len != (size_t)-1)
+ {
+ distribution[len]= 0; // safety
+ char *found= strstr(distribution, "DISTRIB_DESCRIPTION=");
+ if (found)
+ {
+ have_distribution= true;
+ char *end= strstr(found, "\n");
+ if (end == NULL)
+ end= distribution + len;
+ found+= 20;
+
+ if (*found == '"' && end[-1] == '"')
+ {
+ found++;
+ end--;
+ }
+ *end= 0;
+
+ char *to= strmov(distribution, "lsb: ");
+ memmove(to, found, end - found + 1);
+ }
+ }
+ }
+
+ /* if not an LSB-compliant distribution */
+ for (uint i= 0; !have_distribution && i < array_elements(masks); i++)
+ {
+ glob_t found;
+ if (glob(masks[i], GLOB_NOSORT, NULL, &found) == 0)
+ {
+ int fd;
+ if ((fd= my_open(found.gl_pathv[0], O_RDONLY, MYF(0))) != -1)
+ {
+ /*
+ +5 and -8 below cut the file name part out of the
+ full pathname that corresponds to the mask as above.
+ */
+ char *to= strmov(distribution, found.gl_pathv[0] + 5) - 8;
+ *to++= ':';
+ *to++= ' ';
+
+ size_t to_len= distribution + sizeof(distribution) - 1 - to;
+ size_t len= my_read(fd, (uchar*)to, to_len, MYF(0));
+ my_close(fd, MYF(0));
+ if (len != (size_t)-1)
+ {
+ to[len]= 0; // safety
+ char *end= strstr(to, "\n");
+ if (end)
+ *end= 0;
+ have_distribution= true;
+ }
+ }
+ }
+ globfree(&found);
+ }
+#endif
+ return 0;
+}
+
+/**
+ Add the linux distribution and the kernel version
+*/
+int fill_linux_info(THD *thd, TABLE_LIST *tables)
+{
+ TABLE *table= tables->table;
+ CHARSET_INFO *cs= system_charset_info;
+
+#ifdef HAVE_SYS_UTSNAME_H
+ if (have_ubuf)
+ {
+ INSERT1("Uname_sysname", (ubuf.sysname, strlen(ubuf.sysname), cs));
+ INSERT1("Uname_release", (ubuf.release, strlen(ubuf.release), cs));
+ INSERT1("Uname_version", (ubuf.version, strlen(ubuf.version), cs));
+ INSERT1("Uname_machine", (ubuf.machine, strlen(ubuf.machine), cs));
+ }
+#endif
+
+#ifdef TARGET_OS_LINUX
+ if (have_distribution)
+ INSERT1("Uname_distribution", (distribution, strlen(distribution), cs));
+#endif
+
+ return 0;
+}
+
+/**
+ Adds varios bits of information to the I_S.FEEDBACK
+*/
+int fill_misc_data(THD *thd, TABLE_LIST *tables)
+{
+ TABLE *table= tables->table;
+
+#ifdef MY_ATOMIC_OK
+ INSERT1("Cpu_count", (my_getncpus(), UNSIGNED));
+#endif
+ INSERT1("Mem_total", (my_getphysmem(), UNSIGNED));
+
+ return 0;
+}
+
+/**
+ calculates the server unique identifier
+
+ UID is a base64 encoded SHA1 hash of the MAC address of one of
+ the interfaces, and the tcp port that the server is listening on
+*/
+int calculate_server_uid(char *dest)
+{
+ uchar rawbuf[2 + 6];
+ uchar shabuf[SHA1_HASH_SIZE];
+ SHA1_CONTEXT ctx;
+
+ int2store(rawbuf, mysqld_port);
+ if (my_gethwaddr(rawbuf + 2))
+ {
+ sql_print_error("feedback plugin: failed to retrieve the MAC address");
+ return 1;
+ }
+
+ mysql_sha1_reset(&ctx);
+ mysql_sha1_input(&ctx, rawbuf, sizeof(rawbuf));
+ mysql_sha1_result(&ctx, shabuf);
+
+ assert(base64_needed_encoded_length(sizeof(shabuf)) <= SERVER_UID_SIZE);
+ base64_encode(shabuf, sizeof(shabuf), dest);
+
+ return 0;
+}
+
+} // namespace feedback
diff --git a/plugin/fulltext/CMakeLists.txt b/plugin/fulltext/CMakeLists.txt
new file mode 100644
index 00000000000..cf696c19e61
--- /dev/null
+++ b/plugin/fulltext/CMakeLists.txt
@@ -0,0 +1,3 @@
+INCLUDE("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake")
+SET(FTEXAMPLE_SOURCES plugin_example.c)
+MYSQL_PLUGIN(FTEXAMPLE)
diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt
index 8d2aeca17db..a98fb4fd8c0 100644
--- a/sql/CMakeLists.txt
+++ b/sql/CMakeLists.txt
@@ -37,7 +37,9 @@ SET_SOURCE_FILES_PROPERTIES(${CMAKE_BINARY_DIR}/sql/sql_yacc.h
PROPERTIES GENERATED 1)
ADD_DEFINITIONS(-DMYSQL_SERVER -D_CONSOLE -DHAVE_DLOPEN -DHAVE_EVENT_SCHEDULER)
-
+IF(WITH_FEEDBACK_STORAGE_ENGINE)
+ ADD_DEFINITIONS(-DWITH_FEEDBACK_PLUGIN)
+ENDIF()
SET (SQL_SOURCE
../sql-common/client.c derror.cc des_key_file.cc
diff --git a/sql/sp.cc b/sql/sp.cc
index d2c732c2100..57dbc04be4e 100644
--- a/sql/sp.cc
+++ b/sql/sp.cc
@@ -14,8 +14,8 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "mysql_priv.h"
-#include "sp.h"
#include "sp_head.h"
+#include "sp.h"
#include "sp_cache.h"
#include "sql_trigger.h"
@@ -23,7 +23,7 @@
static bool
create_string(THD *thd, String *buf,
- int sp_type,
+ stored_procedure_type sp_type,
const char *db, ulong dblen,
const char *name, ulong namelen,
const char *params, ulong paramslen,
@@ -33,7 +33,8 @@ create_string(THD *thd, String *buf,
const LEX_STRING *definer_user,
const LEX_STRING *definer_host);
static int
-db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp,
+db_load_routine(THD *thd, stored_procedure_type type, sp_name *name,
+ sp_head **sphp,
ulong sql_mode, const char *params, const char *returns,
const char *body, st_sp_chistics &chistics,
const char *definer, longlong created, longlong modified,
@@ -490,7 +491,8 @@ static TABLE *open_proc_table_for_update(THD *thd)
*/
static int
-db_find_routine_aux(THD *thd, int type, sp_name *name, TABLE *table)
+db_find_routine_aux(THD *thd, stored_procedure_type type, sp_name *name,
+ TABLE *table)
{
uchar key[MAX_KEY_LENGTH]; // db, name, optional key length type
DBUG_ENTER("db_find_routine_aux");
@@ -543,7 +545,8 @@ db_find_routine_aux(THD *thd, int type, sp_name *name, TABLE *table)
*/
static int
-db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp)
+db_find_routine(THD *thd, stored_procedure_type type, sp_name *name,
+ sp_head **sphp)
{
TABLE *table;
const char *params, *returns, *body;
@@ -711,7 +714,8 @@ Silence_deprecated_warning::handle_error(uint sql_errno, const char *message,
static int
-db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp,
+db_load_routine(THD *thd, stored_procedure_type type,
+ sp_name *name, sp_head **sphp,
ulong sql_mode, const char *params, const char *returns,
const char *body, st_sp_chistics &chistics,
const char *definer, longlong created, longlong modified,
@@ -890,7 +894,7 @@ sp_returns_type(THD *thd, String &result, sp_head *sp)
*/
int
-sp_create_routine(THD *thd, int type, sp_head *sp)
+sp_create_routine(THD *thd, stored_procedure_type type, sp_head *sp)
{
int ret;
TABLE *table;
@@ -906,7 +910,8 @@ sp_create_routine(THD *thd, int type, sp_head *sp)
bool save_binlog_row_based;
DBUG_ENTER("sp_create_routine");
- DBUG_PRINT("enter", ("type: %d name: %.*s",type, (int) sp->m_name.length,
+ DBUG_PRINT("enter", ("type: %d name: %.*s", (int) type,
+ (int) sp->m_name.length,
sp->m_name.str));
String retstr(64);
retstr.set_charset(system_charset_info);
@@ -1151,7 +1156,7 @@ done:
*/
int
-sp_drop_routine(THD *thd, int type, sp_name *name)
+sp_drop_routine(THD *thd, stored_procedure_type type, sp_name *name)
{
TABLE *table;
int ret;
@@ -1211,14 +1216,16 @@ sp_drop_routine(THD *thd, int type, sp_name *name)
*/
int
-sp_update_routine(THD *thd, int type, sp_name *name, st_sp_chistics *chistics)
+sp_update_routine(THD *thd, stored_procedure_type type, sp_name *name,
+ st_sp_chistics *chistics)
{
TABLE *table;
int ret;
bool save_binlog_row_based;
DBUG_ENTER("sp_update_routine");
DBUG_PRINT("enter", ("type: %d name: %.*s",
- type, (int) name->m_name.length, name->m_name.str));
+ (int) type,
+ (int) name->m_name.length, name->m_name.str));
DBUG_ASSERT(type == TYPE_ENUM_PROCEDURE ||
type == TYPE_ENUM_FUNCTION);
@@ -1346,7 +1353,7 @@ err:
*/
bool
-sp_show_create_routine(THD *thd, int type, sp_name *name)
+sp_show_create_routine(THD *thd, stored_procedure_type type, sp_name *name)
{
bool err_status= TRUE;
sp_head *sp;
@@ -1404,8 +1411,8 @@ sp_show_create_routine(THD *thd, int type, sp_name *name)
*/
sp_head *
-sp_find_routine(THD *thd, int type, sp_name *name, sp_cache **cp,
- bool cache_only)
+sp_find_routine(THD *thd, stored_procedure_type type, sp_name *name,
+ sp_cache **cp, bool cache_only)
{
sp_head *sp;
ulong depth= (type == TYPE_ENUM_PROCEDURE ?
@@ -1562,7 +1569,7 @@ sp_exist_routines(THD *thd, TABLE_LIST *routines, bool any)
*/
int
-sp_routine_exists_in_table(THD *thd, int type, sp_name *name)
+sp_routine_exists_in_table(THD *thd, stored_procedure_type type, sp_name *name)
{
TABLE *table;
int ret;
@@ -1729,7 +1736,7 @@ static bool add_used_routine(LEX *lex, Query_arena *arena,
*/
void sp_add_used_routine(LEX *lex, Query_arena *arena,
- sp_name *rt, char rt_type)
+ sp_name *rt, enum stored_procedure_type rt_type)
{
rt->set_routine_type(rt_type);
(void)add_used_routine(lex, arena, &rt->m_sroutines_key, 0);
@@ -1885,9 +1892,11 @@ sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex,
for (Sroutine_hash_entry *rt= start; rt; rt= rt->next)
{
sp_name name(thd, rt->key.str, rt->key.length);
- int type= rt->key.str[0];
+ stored_procedure_type type= (stored_procedure_type) rt->key.str[0];
sp_head *sp;
+ if (type == TYPE_ENUM_TRIGGER)
+ continue;
if (!(sp= sp_cache_lookup((type == TYPE_ENUM_FUNCTION ?
&thd->sp_func_cache : &thd->sp_proc_cache),
&name)))
@@ -2076,7 +2085,7 @@ sp_cache_routines_and_add_tables_for_triggers(THD *thd, LEX *lex,
*/
static bool
create_string(THD *thd, String *buf,
- int type,
+ stored_procedure_type type,
const char *db, ulong dblen,
const char *name, ulong namelen,
const char *params, ulong paramslen,
diff --git a/sql/sp.h b/sql/sp.h
index 876287d9704..4e3252392f7 100644
--- a/sql/sp.h
+++ b/sql/sp.h
@@ -39,26 +39,28 @@ int
sp_drop_db_routines(THD *thd, char *db);
sp_head *
-sp_find_routine(THD *thd, int type, sp_name *name,
+sp_find_routine(THD *thd, stored_procedure_type type, sp_name *name,
sp_cache **cp, bool cache_only);
bool
sp_exist_routines(THD *thd, TABLE_LIST *procs, bool any);
int
-sp_routine_exists_in_table(THD *thd, int type, sp_name *name);
+sp_routine_exists_in_table(THD *thd, stored_procedure_type type,
+ sp_name *name);
bool
-sp_show_create_routine(THD *thd, int type, sp_name *name);
+sp_show_create_routine(THD *thd, stored_procedure_type type, sp_name *name);
int
-sp_create_routine(THD *thd, int type, sp_head *sp);
+sp_create_routine(THD *thd, stored_procedure_type type, sp_head *sp);
int
-sp_update_routine(THD *thd, int type, sp_name *name, st_sp_chistics *chistics);
+sp_update_routine(THD *thd, stored_procedure_type type, sp_name *name,
+ st_sp_chistics *chistics);
int
-sp_drop_routine(THD *thd, int type, sp_name *name);
+sp_drop_routine(THD *thd, stored_procedure_type type, sp_name *name);
/*
Procedures for pre-caching of stored routines and building table list
@@ -67,7 +69,7 @@ sp_drop_routine(THD *thd, int type, sp_name *name);
void sp_get_prelocking_info(THD *thd, bool *need_prelocking,
bool *first_no_prelocking);
void sp_add_used_routine(LEX *lex, Query_arena *arena,
- sp_name *rt, char rt_type);
+ sp_name *rt, stored_procedure_type rt_type);
void sp_remove_not_own_routines(LEX *lex);
bool sp_update_sp_used_routines(HASH *dst, HASH *src);
int sp_cache_routines_and_add_tables(THD *thd, LEX *lex,
diff --git a/sql/sp_head.h b/sql/sp_head.h
index d422adc8927..dc237163716 100644
--- a/sql/sp_head.h
+++ b/sql/sp_head.h
@@ -28,11 +28,16 @@
@ingroup Runtime_Environment
@{
*/
-// Values for the type enum. This reflects the order of the enum declaration
-// in the CREATE TABLE command.
-#define TYPE_ENUM_FUNCTION 1
-#define TYPE_ENUM_PROCEDURE 2
-#define TYPE_ENUM_TRIGGER 3
+/*
+ Values for the type enum. This reflects the order of the enum declaration
+ in the CREATE TABLE command.
+*/
+enum stored_procedure_type
+{
+ TYPE_ENUM_FUNCTION=1,
+ TYPE_ENUM_PROCEDURE=2,
+ TYPE_ENUM_TRIGGER=3
+};
Item_result
sp_map_result_type(enum enum_field_types type);
@@ -134,9 +139,9 @@ public:
// Init. the qualified name from the db and name.
void init_qname(THD *thd); // thd for memroot allocation
- void set_routine_type(char type)
+ void set_routine_type(stored_procedure_type type)
{
- m_sroutines_key.str[0]= type;
+ m_sroutines_key.str[0]= (char) type;
}
~sp_name()
@@ -170,8 +175,7 @@ public:
HAS_SQLCOM_FLUSH= 4096
};
- /** TYPE_ENUM_FUNCTION, TYPE_ENUM_PROCEDURE or TYPE_ENUM_TRIGGER */
- int m_type;
+ stored_procedure_type m_type;
uint m_flags; // Boolean attributes of a stored routine
Create_field m_return_field_def; /**< This is used for FUNCTIONs only. */
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index c788d324743..d5579827d1e 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -18,6 +18,7 @@
#include "mysql_priv.h"
#include <mysys_err.h>
+#include "sp_head.h"
#include "sp.h"
#include "events.h"
#include "sql_handler.h"
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 72cf0179449..7f39d4ad7f3 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -21,8 +21,8 @@
#include "item_create.h"
#include <m_ctype.h>
#include <hash.h>
-#include "sp.h"
#include "sp_head.h"
+#include "sp.h"
#include "sql_select.h"
/*
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index acdd6b76df4..6202b9d888a 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -4515,9 +4515,10 @@ create_sp_error:
*/
/* Conditionally writes to binlog */
- int type= lex->sql_command == SQLCOM_ALTER_PROCEDURE ?
- TYPE_ENUM_PROCEDURE :
- TYPE_ENUM_FUNCTION;
+ stored_procedure_type type;
+ type= (lex->sql_command == SQLCOM_ALTER_PROCEDURE ?
+ TYPE_ENUM_PROCEDURE :
+ TYPE_ENUM_FUNCTION);
sp_result= sp_update_routine(thd,
type,
@@ -4545,8 +4546,8 @@ create_sp_error:
case SQLCOM_DROP_FUNCTION:
{
int sp_result;
- int type= (lex->sql_command == SQLCOM_DROP_PROCEDURE ?
- TYPE_ENUM_PROCEDURE : TYPE_ENUM_FUNCTION);
+ stored_procedure_type type= (lex->sql_command == SQLCOM_DROP_PROCEDURE ?
+ TYPE_ENUM_PROCEDURE : TYPE_ENUM_FUNCTION);
sp_result= sp_routine_exists_in_table(thd, type, lex->spname);
mysql_reset_errors(thd, 0);
@@ -4573,9 +4574,10 @@ create_sp_error:
#endif
/* Conditionally writes to binlog */
- int type= lex->sql_command == SQLCOM_DROP_PROCEDURE ?
- TYPE_ENUM_PROCEDURE :
- TYPE_ENUM_FUNCTION;
+ stored_procedure_type type;
+ type= (lex->sql_command == SQLCOM_DROP_PROCEDURE ?
+ TYPE_ENUM_PROCEDURE :
+ TYPE_ENUM_FUNCTION);
sp_result= sp_drop_routine(thd, type, lex->spname);
}
diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc
index 58eddf42f26..8e6f065c1c4 100644
--- a/sql/sql_plugin.cc
+++ b/sql/sql_plugin.cc
@@ -3384,6 +3384,19 @@ static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp,
opt->name, plugin_name);
}
}
+ /*
+ PLUGIN_VAR_STR command-line options without PLUGIN_VAR_MEMALLOC, point
+ directly to values in the argv[] array. For plugins started at the
+ server startup, argv[] array is allocated with load_defaults(), and
+ freed when the server is shut down. But for plugins loaded with
+ INSTALL PLUGIN, the memory allocated with load_defaults() is freed with
+ freed() at the end of mysql_install_plugin(). Which means we cannot
+ allow any pointers into that area.
+ Thus, for all plugins loaded after the server was started,
+ we force all command-line options to be PLUGIN_VAR_MEMALLOC
+ */
+ if (mysqld_server_started && !(opt->flags & PLUGIN_VAR_NOCMDOPT))
+ opt->flags|= PLUGIN_VAR_MEMALLOC;
break;
case PLUGIN_VAR_ENUM:
if (!opt->check)
@@ -3540,6 +3553,10 @@ static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp,
if (!my_strcasecmp(&my_charset_latin1, tmp->name.str, "ndbcluster"))
plugin_load_policy= PLUGIN_OFF;
#endif
+#ifdef WITH_FEEDBACK_PLUGIN
+ if (!my_strcasecmp(&my_charset_latin1, tmp->name.str, "feedback"))
+ plugin_load_policy= PLUGIN_OFF;
+#endif
for (opt= tmp->plugin->system_vars; opt && *opt; opt++)
count+= 2; /* --{plugin}-{optname} and --plugin-{plugin}-{optname} */
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 062bfc347b3..08cdf7459fd 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -22,8 +22,8 @@
#include "create_options.h"
#include "sql_show.h"
#include "repl_failsafe.h"
-#include "sp.h"
#include "sp_head.h"
+#include "sp.h"
#include "sql_trigger.h"
#include "authors.h"
#include "contributors.h"
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index 535cc30e3e8..9d71a61f411 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -18,8 +18,8 @@
#include "mysql_priv.h"
#include "sql_select.h"
#include "parse_file.h"
-#include "sp.h"
#include "sp_head.h"
+#include "sp.h"
#include "sp_cache.h"
#define MD5_BUFF_LENGTH 33
diff --git a/storage/blackhole/plug.in b/storage/blackhole/plug.in
index 2f3b120fa5d..84b7299969b 100644
--- a/storage/blackhole/plug.in
+++ b/storage/blackhole/plug.in
@@ -1,6 +1,5 @@
MYSQL_STORAGE_ENGINE(blackhole,,[Blackhole Storage Engine],
[Basic Write-only Read-never tables], [max,max-no-ndb])
-MYSQL_PLUGIN_DIRECTORY(blackhole, [storage/blackhole])
MYSQL_PLUGIN_STATIC(blackhole, [libblackhole.la])
MYSQL_PLUGIN_DYNAMIC(blackhole, [ha_blackhole.la])
diff --git a/storage/csv/plug.in b/storage/csv/plug.in
index 4ff32959fa2..eb4bd4d9883 100644
--- a/storage/csv/plug.in
+++ b/storage/csv/plug.in
@@ -1,5 +1,4 @@
MYSQL_STORAGE_ENGINE(csv,, [CSV Storage Engine],
[Stores tables in text CSV format])
-MYSQL_PLUGIN_DIRECTORY(csv, [storage/csv])
MYSQL_PLUGIN_STATIC(csv, [libcsv.la])
MYSQL_PLUGIN_MANDATORY(csv) dnl Used for logging
diff --git a/storage/heap/plug.in b/storage/heap/plug.in
index 92ec01d3c88..f1b02b38c2b 100644
--- a/storage/heap/plug.in
+++ b/storage/heap/plug.in
@@ -1,6 +1,5 @@
MYSQL_STORAGE_ENGINE(heap,no, [Memory Storage Engine],
[Volatile memory based tables])
-MYSQL_PLUGIN_DIRECTORY(heap, [storage/heap])
MYSQL_PLUGIN_STATIC(heap, [libheap_s.la], [libheap_embedded.la])
MYSQL_PLUGIN_MANDATORY(heap) dnl Memory tables
diff --git a/storage/innobase/plug.in.disabled b/storage/innobase/plug.in.disabled
index b18950b9c7a..2d6af1d2883 100644
--- a/storage/innobase/plug.in.disabled
+++ b/storage/innobase/plug.in.disabled
@@ -1,6 +1,5 @@
MYSQL_STORAGE_ENGINE(innobase, innodb, [InnoDB Storage Engine],
[Transactional Tables using InnoDB], [max,max-no-ndb])
-MYSQL_PLUGIN_DIRECTORY(innobase, [storage/innobase])
MYSQL_PLUGIN_STATIC(innobase, [libinnobase.la])
MYSQL_PLUGIN_DYNAMIC(innobase, [ha_innodb.la])
MYSQL_PLUGIN_ACTIONS(innobase, [
diff --git a/storage/innodb_plugin/plug.in b/storage/innodb_plugin/plug.in
index ebaa3f574a0..e5e2def5435 100644
--- a/storage/innodb_plugin/plug.in
+++ b/storage/innodb_plugin/plug.in
@@ -16,7 +16,6 @@
MYSQL_STORAGE_ENGINE(innodb_plugin,, [InnoDB Storage Engine],
[Transactional Tables using InnoDB], [])
-MYSQL_PLUGIN_DIRECTORY(innodb_plugin, [storage/innodb_plugin])
# Enable if you know what you are doing (trying to link both InnoDB and
# InnoDB Plugin statically into MySQL does not work).
#MYSQL_PLUGIN_STATIC(innodb_plugin, [libinnobase.a])
diff --git a/storage/maria/CMakeLists.txt b/storage/maria/CMakeLists.txt
index 7e32d2fe3d8..77083c5839f 100644
--- a/storage/maria/CMakeLists.txt
+++ b/storage/maria/CMakeLists.txt
@@ -50,36 +50,36 @@ MYSQL_STORAGE_ENGINE(ARIA)
IF(NOT SOURCE_SUBLIBS)
- ADD_DEPENDENCIES(aria GenError)
+ ADD_DEPENDENCIES(libaria_s GenError)
MYSQL_ADD_EXECUTABLE(aria_ftdump maria_ftdump.c)
-TARGET_LINK_LIBRARIES(aria_ftdump aria myisam mysys dbug strings zlib wsock32)
+TARGET_LINK_LIBRARIES(aria_ftdump libaria_s libmyisam_s mysys dbug strings zlib wsock32)
MYSQL_ADD_EXECUTABLE(aria_chk maria_chk.c)
-TARGET_LINK_LIBRARIES(aria_chk aria myisam mysys dbug strings zlib wsock32)
+TARGET_LINK_LIBRARIES(aria_chk libaria_s libmyisam_s mysys dbug strings zlib wsock32)
MYSQL_ADD_EXECUTABLE(aria_read_log maria_read_log.c)
-TARGET_LINK_LIBRARIES(aria_read_log aria myisam mysys dbug strings zlib wsock32)
+TARGET_LINK_LIBRARIES(aria_read_log libaria_s libmyisam_s mysys dbug strings zlib wsock32)
MYSQL_ADD_EXECUTABLE(aria_pack maria_pack.c)
-TARGET_LINK_LIBRARIES(aria_pack aria myisam mysys dbug strings zlib wsock32)
+TARGET_LINK_LIBRARIES(aria_pack libaria_s libmyisam_s mysys dbug strings zlib wsock32)
MYSQL_ADD_EXECUTABLE(aria_dump_log maria_dump_log.c unittest/ma_loghandler_examples.c)
-TARGET_LINK_LIBRARIES(aria_dump_log aria myisam mysys dbug strings zlib wsock32)
+TARGET_LINK_LIBRARIES(aria_dump_log libaria_s libmyisam_s mysys dbug strings zlib wsock32)
ADD_EXECUTABLE(ma_test1 ma_test1.c)
-TARGET_LINK_LIBRARIES(ma_test1 aria myisam mysys dbug strings zlib wsock32)
+TARGET_LINK_LIBRARIES(ma_test1 libaria_s libmyisam_s mysys dbug strings zlib wsock32)
ADD_EXECUTABLE(ma_test2 ma_test2.c)
-TARGET_LINK_LIBRARIES(ma_test2 aria myisam mysys dbug strings zlib wsock32)
+TARGET_LINK_LIBRARIES(ma_test2 libaria_s libmyisam_s mysys dbug strings zlib wsock32)
ADD_EXECUTABLE(ma_test3 ma_test3.c)
-TARGET_LINK_LIBRARIES(ma_test3 aria myisam mysys dbug strings zlib wsock32)
+TARGET_LINK_LIBRARIES(ma_test3 libaria_s libmyisam_s mysys dbug strings zlib wsock32)
ADD_EXECUTABLE(ma_rt_test ma_rt_test.c)
-TARGET_LINK_LIBRARIES(ma_rt_test aria myisam mysys dbug strings zlib wsock32)
+TARGET_LINK_LIBRARIES(ma_rt_test libaria_s libmyisam_s mysys dbug strings zlib wsock32)
ADD_EXECUTABLE(ma_sp_test ma_sp_test.c)
-TARGET_LINK_LIBRARIES(ma_sp_test aria myisam mysys dbug strings zlib wsock32)
+TARGET_LINK_LIBRARIES(ma_sp_test libaria_s libmyisam_s mysys dbug strings zlib wsock32)
ENDIF(NOT SOURCE_SUBLIBS)
diff --git a/storage/maria/plug.in b/storage/maria/plug.in
index c48928be44f..609adcb2f66 100644
--- a/storage/maria/plug.in
+++ b/storage/maria/plug.in
@@ -1,6 +1,5 @@
MYSQL_STORAGE_ENGINE(aria,, [Aria Storage Engine],
[Crash-safe tables with MyISAM heritage], [default,max,max-no-ndb])
-MYSQL_PLUGIN_DIRECTORY(aria, [storage/maria])
MYSQL_PLUGIN_STATIC(aria, [libaria_s.la], [libaria_embedded.la])
MYSQL_PLUGIN_ACTIONS(aria, [
diff --git a/storage/maria/unittest/CMakeLists.txt b/storage/maria/unittest/CMakeLists.txt
index a6e8736daab..715a6199185 100644
--- a/storage/maria/unittest/CMakeLists.txt
+++ b/storage/maria/unittest/CMakeLists.txt
@@ -13,10 +13,9 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/zlib
${CMAKE_SOURCE_DIR}/unittest/mytap)
-LINK_LIBRARIES(maria myisam mytap mysys dbug strings wsock32 zlib)
+LINK_LIBRARIES(libmaria_s libmyisam_s mytap mysys dbug strings wsock32 zlib)
ADD_EXECUTABLE(ma_control_file-t ma_control_file-t.c)
ADD_EXECUTABLE(trnman-t trnman-t.c)
diff --git a/storage/myisam/CMakeLists.txt b/storage/myisam/CMakeLists.txt
index e7e3de64cf3..ce27c209418 100644
--- a/storage/myisam/CMakeLists.txt
+++ b/storage/myisam/CMakeLists.txt
@@ -32,31 +32,31 @@ MYSQL_STORAGE_ENGINE(MYISAM)
IF(NOT SOURCE_SUBLIBS)
MYSQL_ADD_EXECUTABLE(myisam_ftdump myisam_ftdump.c DESTINATION bin)
- TARGET_LINK_LIBRARIES(myisam_ftdump myisam mysys debug dbug strings zlib wsock32)
+ TARGET_LINK_LIBRARIES(myisam_ftdump libmyisam_s mysys debug dbug strings zlib wsock32)
MYSQL_ADD_EXECUTABLE(myisamchk myisamchk.c DESTINATION bin)
- TARGET_LINK_LIBRARIES(myisamchk myisam mysys debug dbug strings zlib wsock32)
+ TARGET_LINK_LIBRARIES(myisamchk libmyisam_s mysys debug dbug strings zlib wsock32)
MYSQL_ADD_EXECUTABLE(myisamlog myisamlog.c DESTINATION bin)
- TARGET_LINK_LIBRARIES(myisamlog myisam mysys debug dbug strings zlib wsock32)
+ TARGET_LINK_LIBRARIES(myisamlog libmyisam_s mysys debug dbug strings zlib wsock32)
MYSQL_ADD_EXECUTABLE(myisampack myisampack.c DESTINATION bin)
- TARGET_LINK_LIBRARIES(myisampack myisam mysys debug dbug strings zlib wsock32)
+ TARGET_LINK_LIBRARIES(myisampack libmyisam_s mysys debug dbug strings zlib wsock32)
ADD_EXECUTABLE(mi_test1 mi_test1.c)
- TARGET_LINK_LIBRARIES(mi_test1 myisam mysys debug dbug strings zlib wsock32)
+ TARGET_LINK_LIBRARIES(mi_test1 libmyisam_s mysys debug dbug strings zlib wsock32)
ADD_EXECUTABLE(mi_test2 mi_test2.c)
- TARGET_LINK_LIBRARIES(mi_test2 myisam mysys debug dbug strings zlib wsock32)
+ TARGET_LINK_LIBRARIES(mi_test2 libmyisam_s mysys debug dbug strings zlib wsock32)
ADD_EXECUTABLE(mi_test3 mi_test3.c)
- TARGET_LINK_LIBRARIES(mi_test3 myisam mysys debug dbug strings zlib wsock32)
+ TARGET_LINK_LIBRARIES(mi_test3 libmyisam_s mysys debug dbug strings zlib wsock32)
ADD_EXECUTABLE(sp_test sp_test.c)
- TARGET_LINK_LIBRARIES(sp_test myisam mysys debug dbug strings zlib wsock32)
+ TARGET_LINK_LIBRARIES(sp_test libmyisam_s mysys debug dbug strings zlib wsock32)
ADD_EXECUTABLE(rt_test rt_test.c)
- TARGET_LINK_LIBRARIES(rt_test myisam mysys debug dbug strings zlib wsock32)
+ TARGET_LINK_LIBRARIES(rt_test libmyisam_s mysys debug dbug strings zlib wsock32)
SET_TARGET_PROPERTIES(myisamchk myisampack PROPERTIES LINK_FLAGS "setargv.obj")
diff --git a/storage/myisam/plug.in b/storage/myisam/plug.in
index 95b29336493..0ec7ea1e1d2 100644
--- a/storage/myisam/plug.in
+++ b/storage/myisam/plug.in
@@ -1,6 +1,5 @@
dnl MYSQL_STORAGE_ENGINE(myisam,no, [MyISAM Storage Engine],
dnl [Traditional non-transactional MySQL tables])
-dnl MYSQL_PLUGIN_DIRECTORY(myisam, [storage/myisam])
dnl MYSQL_PLUGIN_STATIC(myisam, [libmyisam_s.la], [libmyisam_embedded.la])
dnl MYSQL_PLUGIN_MANDATORY(myisam) dnl Default
diff --git a/storage/myisammrg/plug.in b/storage/myisammrg/plug.in
index a2654373fba..22cd5b17cb4 100644
--- a/storage/myisammrg/plug.in
+++ b/storage/myisammrg/plug.in
@@ -1,5 +1,4 @@
MYSQL_STORAGE_ENGINE(myisammrg,no,[MyISAM MERGE Engine],
[Merge multiple MySQL tables into one])
-MYSQL_PLUGIN_DIRECTORY(myisammrg,[storage/myisammrg])
MYSQL_PLUGIN_STATIC(myisammrg, [libmyisammrg_s.la], [libmyisammrg_embedded.la])
MYSQL_PLUGIN_MANDATORY(myisammrg)
diff --git a/storage/mysql_storage_engine.cmake b/storage/mysql_storage_engine.cmake
index 07b4151c50c..b29ba961179 100644
--- a/storage/mysql_storage_engine.cmake
+++ b/storage/mysql_storage_engine.cmake
@@ -10,41 +10,41 @@
# ${engine}_LIBS variable containing extra libraries to link with may be set
-MACRO(MYSQL_STORAGE_ENGINE engine)
+MACRO(MYSQL_PLUGIN engine)
IF(NOT SOURCE_SUBLIBS)
# Add common include directories
- INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/zlib
- ${CMAKE_SOURCE_DIR}/sql
- ${CMAKE_SOURCE_DIR}/regex
- ${CMAKE_SOURCE_DIR}/extra/yassl/include
- ${CMAKE_BINARY_DIR}/include
- ${CMAKE_BINARY_DIR}/sql
- )
+ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_BINARY_DIR}/include)
STRING(TOUPPER ${engine} engine)
- STRING(TOLOWER ${engine} libname)
IF(${ENGINE_BUILD_TYPE} STREQUAL "STATIC")
- ADD_DEFINITIONS(-DWITH_${engine}_STORAGE_ENGINE -DMYSQL_SERVER)
- #Create static library. The name of the library is <storage_engine>.lib
- ADD_LIBRARY(${libname} ${${engine}_SOURCES})
- ADD_DEPENDENCIES(${libname} GenError)
+ ADD_LIBRARY(${${engine}_LIB} ${${engine}_SOURCES})
+ ADD_DEPENDENCIES(${${engine}_LIB} GenError)
IF(${engine}_LIBS)
- TARGET_LINK_LIBRARIES(${libname} ${${engine}_LIBS})
+ TARGET_LINK_LIBRARIES(${${engine}_LIB} ${${engine}_LIBS})
ENDIF(${engine}_LIBS)
- MESSAGE("build ${engine} as static library")
+ MESSAGE("build ${engine} as static library (${${engine}_LIB}.lib)")
ELSEIF(${ENGINE_BUILD_TYPE} STREQUAL "DYNAMIC")
ADD_DEFINITIONS(-DMYSQL_DYNAMIC_PLUGIN)
- #Create a DLL.The name of the dll is ha_<storage_engine>.dll
- #The dll is linked to the mysqld executable
- SET(dyn_libname ha_${libname})
- ADD_VERSION_INFO(${dyn_libname} SHARED ${engine}_SOURCES)
- ADD_LIBRARY(${dyn_libname} MODULE ${${engine}_SOURCES})
- TARGET_LINK_LIBRARIES (${dyn_libname} mysqlservices mysqld)
+ ADD_VERSION_INFO(${${engine}_LIB} SHARED ${engine}_SOURCES)
+ ADD_LIBRARY(${${engine}_LIB} MODULE ${${engine}_SOURCES})
+ TARGET_LINK_LIBRARIES (${${engine}_LIB} mysqlservices mysqld)
IF(${engine}_LIBS)
- TARGET_LINK_LIBRARIES(${dyn_libname} ${${engine}_LIBS})
+ TARGET_LINK_LIBRARIES(${${engine}_LIB} ${${engine}_LIBS})
ENDIF(${engine}_LIBS)
# Install the plugin
- MYSQL_INSTALL_TARGETS(${dyn_libname} DESTINATION lib/plugin COMPONENT Server)
- MESSAGE("build ${engine} as DLL")
+ MYSQL_INSTALL_TARGETS(${${engine}_LIB} DESTINATION lib/plugin COMPONENT Server)
+ MESSAGE("build ${engine} as DLL (${${engine}_LIB}.dll)")
+ ENDIF(${ENGINE_BUILD_TYPE} STREQUAL "STATIC")
+ENDIF(NOT SOURCE_SUBLIBS)
+ENDMACRO(MYSQL_PLUGIN)
+
+MACRO(MYSQL_STORAGE_ENGINE engine)
+IF(NOT SOURCE_SUBLIBS)
+ MYSQL_PLUGIN(${engine})
+ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/zlib ${CMAKE_SOURCE_DIR}/sql
+ ${CMAKE_SOURCE_DIR}/regex ${CMAKE_BINARY_DIR}/sql
+ ${CMAKE_SOURCE_DIR}/extra/yassl/include)
+ IF(${ENGINE_BUILD_TYPE} STREQUAL "STATIC")
+ ADD_DEFINITIONS(-DWITH_${engine}_STORAGE_ENGINE -DMYSQL_SERVER)
ENDIF(${ENGINE_BUILD_TYPE} STREQUAL "STATIC")
ENDIF(NOT SOURCE_SUBLIBS)
ENDMACRO(MYSQL_STORAGE_ENGINE)
diff --git a/storage/ndb/plug.in b/storage/ndb/plug.in
index 3d3349f7a8b..d5f30d1e4b2 100644
--- a/storage/ndb/plug.in
+++ b/storage/ndb/plug.in
@@ -1,6 +1,5 @@
MYSQL_STORAGE_ENGINE(ndbcluster, ndbcluster, [Cluster Storage Engine],
[High Availability Clustered tables],)
-MYSQL_PLUGIN_DIRECTORY(ndbcluster,[storage/ndb])
MYSQL_PLUGIN_STATIC(ndbcluster, [[\$(ndbcluster_libs) \$(ndbcluster_system_libs) \$(NDB_SCI_LIBS)]])
MYSQL_PLUGIN_ACTIONS(ndbcluster,[MYSQL_SETUP_NDBCLUSTER])
MYSQL_PLUGIN_DEPENDS(ndbcluster, [partition])
diff --git a/storage/pbxt/plug.in b/storage/pbxt/plug.in
index c0dc06d9702..2d79ad61b3a 100644
--- a/storage/pbxt/plug.in
+++ b/storage/pbxt/plug.in
@@ -1,6 +1,5 @@
MYSQL_STORAGE_ENGINE(pbxt,no, [PBXT Storage Engine],
[MVCC-based transactional engine], [max,max-no-ndb])
-MYSQL_PLUGIN_DIRECTORY(pbxt, [storage/pbxt])
MYSQL_PLUGIN_STATIC(pbxt, [src/libpbxt_s.la], [src/libpbxt_s_embedded.la])
MYSQL_PLUGIN_ACTIONS(pbxt, [
# AC_CONFIG_FILES(storage/pbxt/src/Makefile)
diff --git a/storage/xtradb/CMakeLists.txt b/storage/xtradb/CMakeLists.txt
index 6e16c4ced32..8426804615d 100644
--- a/storage/xtradb/CMakeLists.txt
+++ b/storage/xtradb/CMakeLists.txt
@@ -13,7 +13,9 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-# This is the CMakeLists for InnoDB Plugin
+# This is the CMakeLists for XtraDB
+
+INCLUDE("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake")
IF (CMAKE_SIZEOF_VOID_P MATCHES 8)
SET(WIN64 TRUE)
diff --git a/storage/xtradb/plug.in b/storage/xtradb/plug.in
index 2e0c873094a..1846543a81c 100644
--- a/storage/xtradb/plug.in
+++ b/storage/xtradb/plug.in
@@ -16,7 +16,6 @@
MYSQL_STORAGE_ENGINE(xtradb, xtradb, [XtraDB Storage Engine],
[XtraDB - a drop-in replacement for InnoDB], [max,max-no-ndb])
-MYSQL_PLUGIN_DIRECTORY(xtradb, [storage/xtradb])
MYSQL_PLUGIN_STATIC(xtradb, [libxtradb.la])
MYSQL_PLUGIN_DYNAMIC(xtradb, [ha_xtradb.la])
MYSQL_PLUGIN_ACTIONS(xtradb, [
diff --git a/win/README b/win/README
index 916f64913ac..8ae611ec746 100644
--- a/win/README
+++ b/win/README
@@ -51,12 +51,10 @@ win\configure <options>
The options right now are:
- WITH_INNOBASE_STORAGE_ENGINE Enable particular storage engines
- WITH_PARTITION_STORAGE_ENGINE
- WITH_ARCHIVE_STORAGE_ENGINE
- WITH_BLACKHOLE_STORAGE_ENGINE
- WITH_EXAMPLE_STORAGE_ENGINE
- WITH_FEDERATED_STORAGE_ENGINE
+ --with-plugin-XXX Enable particular plugin or plugins
+ --with-plugins=XXX,YYY,...
+ --with-plugins=GROUP GROUP can be, for example, "max" or "max-no-ndb"
+ --without-plugin-XXX Disable particular plugin
__NT__ Enable named pipe support
MYSQL_SERVER_SUFFIX=<suffix> Server suffix, default none
COMPILATION_COMMENT=<comment> Server comment, default "Source distribution"
@@ -70,7 +68,7 @@ The options right now are:
So the command line could look like:
-win\configure WITH_INNOBASE_STORAGE_ENGINE WITH_PARTITION_STORAGE_ENGINE MYSQL_SERVER_SUFFIX=-pro
+win\configure --with-plugin-innobase --with-plugin-partition MYSQL_SERVER_SUFFIX=-pro
Step 6
------
diff --git a/win/configure-mariadb.bat b/win/configure-mariadb.bat
index 6c4283359b4..dc5b59819a3 100644
--- a/win/configure-mariadb.bat
+++ b/win/configure-mariadb.bat
@@ -5,4 +5,5 @@ cscript win\configure.js ^
WITH_PARTITION_STORAGE_ENGINE ^
WITH_ARIA_STORAGE_ENGINE ^
WITH_PBXT_STORAGE_ENGINE ^
- WITH_XTRADB_STORAGE_ENGINE
+ WITH_XTRADB_STORAGE_ENGINE ^
+ WITH_FEEDBACK_STORAGE_ENGINE
diff --git a/win/configure-mariadb.sh b/win/configure-mariadb.sh
index 616d1b790d6..67bfe293639 100644
--- a/win/configure-mariadb.sh
+++ b/win/configure-mariadb.sh
@@ -18,4 +18,5 @@ cscript win/configure.js \
WITH_ARIA_STORAGE_ENGINE \
WITH_PBXT_STORAGE_ENGINE \
WITH_XTRADB_STORAGE_ENGINE \
+ WITH_FEEDBACK_STORAGE_ENGINE \
WITH_EMBEDDED_SERVER
diff --git a/win/configure.js b/win/configure.js
index da7e4c2cd43..43234b39c22 100644
--- a/win/configure.js
+++ b/win/configure.js
@@ -126,7 +126,7 @@ try
var engineOptions = ParsePlugins();
for (option in engineOptions)
{
- configfile.WriteLine("SET(" + engineOptions[option] + " TRUE)");
+ configfile.WriteLine("SET (" + engineOptions[option] + " TRUE)");
}
configfile.Close();
@@ -302,7 +302,7 @@ function ParsePlugins()
{
var content = fso.OpenTextFile(filename, ForReading).ReadAll();
var match =
- /MYSQL_STORAGE_ENGINE([ ]*)[\(]([^\)]+)[\)]/.exec(content);
+ /MYSQL_(PLUGIN|STORAGE_ENGINE)([ ]*)[\(]([^\)]+)[\)]/.exec(content);
if (match== null)
continue;
match = /\[[\w,\-_]+\][\s]?\)/.exec(match[0]);
@@ -329,9 +329,9 @@ function ParsePlugins()
for(key in config)
{
var eng = config[key];
- if(eng.isGroup != undefined && !eng.isGroup && eng.include != undefined)
+ if(eng.isGroup != undefined && !eng.isGroup && eng.include != undefined)
{
- if (fso.FolderExists("storage\\"+key) || key=="PARTITION")
+ if (fso.FolderExists("storage\\"+key) || fso.FolderExists("plugin\\"+key) || key=="PARTITION")
{
arr[arr.length] = eng.include?
"WITH_"+key+"_STORAGE_ENGINE":"WITHOUT_"+key+"_STORAGE_ENGINE";