diff --git a/CMakeLists.txt b/CMakeLists.txt index 5c561338..3ee9750d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -196,15 +196,18 @@ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}/include) IF(WIN32) SET(SYSTEM_LIBS ws2_32 advapi32 kernel32) ELSE() - SET(SYSTEM_LIBS ${LIBPTHREAD} ${LIBDL} ${LIBM} ${LIBICONV}) + SET(SYSTEM_LIBS ${LIBPTHREAD} ${LIBDL} ${LIBM}) + IF(ICONV_EXTERNAL) + SET(SYSTEM_LIBS ${SYSTEM_LIBS} ${ICONV_LIBRARIES}) + ENDIF() ENDIF() IF(OPENSSL_FOUND) SET(SYSTEM_LIBS ${SYSTEM_LIBS} ${SSL_LIBRARIES}) ENDIF() ADD_SUBDIRECTORY(include) -ADD_SUBDIRECTORY(plugins) ADD_SUBDIRECTORY(libmariadb) +ADD_SUBDIRECTORY(plugins) IF(NOT WIN32) ADD_SUBDIRECTORY(mariadb_config) ENDIF() diff --git a/cmake/FindIconv.cmake b/cmake/FindIconv.cmake index 8f344d3d..f0768f71 100644 --- a/cmake/FindIconv.cmake +++ b/cmake/FindIconv.cmake @@ -19,6 +19,7 @@ IF(APPLE) /opt/local/lib/ /usr/lib/ NO_CMAKE_SYSTEM_PATH) + SET(ICONV_EXTERNAL TRUE) ELSE() find_library(ICONV_LIBRARIES NAMES iconv libiconv libiconv-2) IF(ICONV_LIBRARIES) diff --git a/cmake/symlink.cmake b/cmake/symlink.cmake new file mode 100644 index 00000000..559f3e81 --- /dev/null +++ b/cmake/symlink.cmake @@ -0,0 +1,30 @@ +MACRO(create_symlink symlink_name target install_path) +# According to cmake documentation symlinks work on unix systems only +IF(UNIX) + # Get target components + GET_TARGET_PROPERTY(target_location ${target} LOCATION) + GET_FILENAME_COMPONENT(target_path ${target_location} PATH) + GET_FILENAME_COMPONENT(target_name ${target_location} NAME) + + ADD_CUSTOM_COMMAND( + OUTPUT ${target_path}/${symlink_name} + COMMAND ${CMAKE_COMMAND} ARGS -E remove -f ${target_path}/${symlink_name} + COMMAND ${CMAKE_COMMAND} ARGS -E create_symlink ${target_name} ${symlink_name} + WORKING_DIRECTORY ${target_path} + DEPENDS ${target} + ) + + ADD_CUSTOM_TARGET(SYM_${symlink_name} + ALL + DEPENDS ${target_path}/${symlink_name}) + SET_TARGET_PROPERTIES(SYM_${symlink_name} PROPERTIES CLEAN_DIRECT_OUTPUT 1) + + IF(CMAKE_GENERATOR MATCHES "Xcode") + # For Xcode, replace project config with install config + STRING(REPLACE "${CMAKE_CFG_INTDIR}" + "\${CMAKE_INSTALL_CONFIG_NAME}" output ${target_path}/${symlink_name}) + ENDIF() + + INSTALL(FILES ${target_path}/${symlink_name} DESTINATION ${install_path}) +ENDIF() +ENDMACRO() diff --git a/include/my_global.h b/include/my_global.h index 1925e4b3..138627d2 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -454,7 +454,7 @@ typedef SOCKET_SIZE_TYPE size_socket; #ifdef _WIN32 #define NO_DIR_LIBRARY /* Not standar dir-library */ #define USE_MY_STAT_STRUCT /* For my_lib */ -#ifdef _SIZE_T_DEFINED +#ifdef _MSVC typedef SSIZE_T ssize_t; #endif #endif diff --git a/libmariadb/CMakeLists.txt b/libmariadb/CMakeLists.txt index 3ea50db2..55689fb7 100644 --- a/libmariadb/CMakeLists.txt +++ b/libmariadb/CMakeLists.txt @@ -362,10 +362,17 @@ IF(UNIX) SET_TARGET_PROPERTIES(mariadb_obj PROPERTIES COMPILE_FLAGS "${CMAKE_SHARED_LIBRARY_C_FLAGS}") ENDIF() -ADD_LIBRARY(mariadbclient STATIC $ ${EXPORT_LINK}) +# Xcode doesn't support targets that have only object files, +# so let's add an empty file to keep Xcode happy +IF(CMAKE_GENERATOR MATCHES Xcode) + FILE(WRITE ${CMAKE_SOURCE_DIR}/libmariadb/empty.c "") + SET(EMPTY_FILE ${CMAKE_SOURCE_DIR}/libmariadb/empty.c) +ENDIF() + +ADD_LIBRARY(mariadbclient STATIC $ ${EMPTY_FILE} ${EXPORT_LINK}) TARGET_LINK_LIBRARIES(mariadbclient ${SYSTEM_LIBS}) -ADD_LIBRARY(libmariadb SHARED $ ${EXPORT_LINK}) +ADD_LIBRARY(libmariadb SHARED $ ${EMPTY_FILE} ${EXPORT_LINK}) TARGET_LINK_LIBRARIES(libmariadb ${SYSTEM_LIBS}) IF(UNIX) SET_TARGET_PROPERTIES(libmariadb PROPERTIES COMPILE_FLAGS "${CMAKE_SHARED_LIBRARY_C_FLAGS}") @@ -387,33 +394,18 @@ SET_TARGET_PROPERTIES(libmariadb PROPERTIES VERSION # # Installation # +INCLUDE(${CMAKE_SOURCE_DIR}/cmake/symlink.cmake) + # There are still several projects which don't make use # of the config program. To make sure these programs can # use mariadb client library we provide libmysql symlinks IF(NOT WIN32 AND WITH_MYSQLCOMPAT) - ADD_CUSTOM_COMMAND(OUTPUT "libmysql${CMAKE_SHARED_LIBRARY_SUFFIX}" - "libmysqlclient${CMAKE_SHARED_LIBRARY_SUFFIX}" - "libmysqlclient_r${CMAKE_SHARED_LIBRARY_SUFFIX}" - "libmysqlclient${CMAKE_STATIC_LIBRARY_SUFFIX}" - COMMAND ${CMAKE_COMMAND} ARGS -E remove -f libmysql${CMAKE_SHARED_LIBRARY_SUFFIX} - COMMAND ${CMAKE_COMMAND} ARGS -E create_symlink libmariadb${CMAKE_SHARED_LIBRARY_SUFFIX} libmysql${CMAKE_SHARED_LIBRARY_SUFFIX} - COMMAND ${CMAKE_COMMAND} ARGS -E remove -f libmysqlclient_r${CMAKE_SHARED_LIBRARY_SUFFIX} - COMMAND ${CMAKE_COMMAND} ARGS -E create_symlink libmariadb${CMAKE_SHARED_LIBRARY_SUFFIX} libmysqlclient_r${CMAKE_SHARED_LIBRARY_SUFFIX} - COMMAND ${CMAKE_COMMAND} ARGS -E remove -f libmysqlclient${CMAKE_SHARED_LIBRARY_SUFFIX} - COMMAND ${CMAKE_COMMAND} ARGS -E create_symlink libmariadb${CMAKE_SHARED_LIBRARY_SUFFIX} libmysqlclient${CMAKE_SHARED_LIBRARY_SUFFIX} - COMMAND ${CMAKE_COMMAND} ARGS -E remove -f libmysqlclient${CMAKE_STATIC_LIBRARY_SUFFIX} - COMMAND ${CMAKE_COMMAND} ARGS -E create_symlink libmariadbclient${CMAKE_STATIC_LIBRARY_SUFFIX} libmysqlclient${CMAKE_STATIC_LIBRARY_SUFFIX} - WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/libmariadb - DEPENDS libmariadb mariadbclient) - -ADD_CUSTOM_TARGET(LIBMYSQL_SYMLINKS - ALL - DEPENDS "libmysql${CMAKE_SHARED_LIBRARY_SUFFIX}" - "libmysqlclient_r${CMAKE_SHARED_LIBRARY_SUFFIX}" - "libmysqlclient${CMAKE_SHARED_LIBRARY_SUFFIX}" - "libmysqlclient${CMAKE_STATIC_LIBRARY_SUFFIX}" - VERBATIM) + SET(INSTALL_PATH ${LIB_INSTALL_DIR}/${SUFFIX_INSTALL_DIR}) + create_symlink(libmysqlclient${CMAKE_SHARED_LIBRARY_SUFFIX} libmariadb ${INSTALL_PATH}) + create_symlink(libmysqlclient_r${CMAKE_SHARED_LIBRARY_SUFFIX} libmariadb ${INSTALL_PATH}) + create_symlink(libmysqlclient${CMAKE_STATIC_LIBRARY_SUFFIX} mariadbclient ${INSTALL_PATH}) + create_symlink(libmysqlclient_r${CMAKE_STATIC_LIBRARY_SUFFIX} mariadbclient ${INSTALL_PATH}) ENDIF() @@ -423,14 +415,6 @@ INSTALL(TARGETS LIBRARY DESTINATION "${LIB_INSTALL_DIR}/${SUFFIX_INSTALL_DIR}" ARCHIVE DESTINATION "${LIB_INSTALL_DIR}/${SUFFIX_INSTALL_DIR}") -IF(NOT WIN32 AND WITH_MYSQLCOMPAT) - INSTALL(FILES "${CMAKE_BINARY_DIR}/libmariadb/libmysql${CMAKE_SHARED_LIBRARY_SUFFIX}" - "${CMAKE_BINARY_DIR}/libmariadb/libmysqlclient${CMAKE_SHARED_LIBRARY_SUFFIX}" - "${CMAKE_BINARY_DIR}/libmariadb/libmysqlclient_r${CMAKE_SHARED_LIBRARY_SUFFIX}" - "${CMAKE_BINARY_DIR}/libmariadb/libmysqlclient${CMAKE_STATIC_LIBRARY_SUFFIX}" - DESTINATION ${LIB_INSTALL_DIR}/mariadb) -ENDIF() - INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/include/ DESTINATION ${INCLUDE_INSTALL_DIR}/${SUFFIX_INSTALL_DIR}) INSTALL(FILES diff --git a/libmariadb/libmariadb.c b/libmariadb/libmariadb.c index 8fd87ba7..d5f17eff 100644 --- a/libmariadb/libmariadb.c +++ b/libmariadb/libmariadb.c @@ -1376,13 +1376,16 @@ int STDCALL mysql_ssl_set(MYSQL *mysql, const char *key, const char *cert, const char *ca, const char *capath, const char *cipher) { - mysql->options.ssl_key = key==0 ? 0 : my_strdup(key,MYF(0)); - mysql->options.ssl_cert = cert==0 ? 0 : my_strdup(cert,MYF(0)); - mysql->options.ssl_ca = ca==0 ? 0 : my_strdup(ca,MYF(0)); - mysql->options.ssl_capath = capath==0 ? 0 : my_strdup(capath,MYF(0)); - mysql->options.ssl_cipher = cipher==0 ? 0 : my_strdup(cipher,MYF(0)); -/* todo: add crl stuff */ + #ifdef HAVE_SSL + return (mysql_optionsv(mysql, MYSQL_OPT_SSL_KEY, key) | + mysql_optionsv(mysql, MYSQL_OPT_SSL_CERT, cert) | + mysql_optionsv(mysql, MYSQL_OPT_SSL_CA, ca) | + mysql_optionsv(mysql, MYSQL_OPT_SSL_CAPATH, capath) | + mysql_optionsv(mysql, MYSQL_OPT_SSL_CIPHER, cipher)) ? 1 : 0; +#else return 0; +#endif + } /************************************************************************** @@ -1711,10 +1714,10 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user, if (mysql->options.extension && mysql->options.extension->async_context && mysql->options.extension->async_context->active) break; - else if (socket_block(sock, 1) == SOCKET_ERROR) + else if (socket_block(sock, 0) == SOCKET_ERROR) { - closesocket(sock); - continue; + closesocket(sock); + continue; } break; /* success! */ } @@ -1739,7 +1742,6 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user, goto error; } } - /* set timeouts */ net->vio->read_timeout= mysql->options.read_timeout; net->vio->write_timeout= mysql->options.write_timeout; @@ -1767,8 +1769,8 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user, vio_write_timeout(net->vio, mysql->options.read_timeout); /* Get version info */ mysql->protocol_version= PROTOCOL_VERSION; /* Assume this */ - if (mysql->options.connect_timeout >= 0 && - vio_wait_or_timeout(net->vio, FALSE, mysql->options.connect_timeout * 1000) < 1) + if (mysql->options.connect_timeout && + vio_wait_or_timeout(net->vio, TRUE, mysql->options.connect_timeout * 1000) < 1) { my_set_error(mysql, CR_SERVER_LOST, SQLSTATE_UNKNOWN, ER(CR_SERVER_LOST_EXTENDED), @@ -3031,23 +3033,23 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...) break; case MYSQL_OPT_SSL_KEY: my_free(mysql->options.ssl_key); - mysql->options.ssl_key=my_strdup((char *)arg1,MYF(MY_WME)); + mysql->options.ssl_key=my_strdup((char *)arg1,MYF(MY_WME | MY_ALLOW_ZERO_PTR)); break; case MYSQL_OPT_SSL_CERT: my_free(mysql->options.ssl_cert); - mysql->options.ssl_cert=my_strdup((char *)arg1,MYF(MY_WME)); + mysql->options.ssl_cert=my_strdup((char *)arg1,MYF(MY_WME | MY_ALLOW_ZERO_PTR)); break; case MYSQL_OPT_SSL_CA: my_free(mysql->options.ssl_ca); - mysql->options.ssl_ca=my_strdup((char *)arg1,MYF(MY_WME)); + mysql->options.ssl_ca=my_strdup((char *)arg1,MYF(MY_WME | MY_ALLOW_ZERO_PTR)); break; case MYSQL_OPT_SSL_CAPATH: my_free(mysql->options.ssl_capath); - mysql->options.ssl_capath=my_strdup((char *)arg1,MYF(MY_WME)); + mysql->options.ssl_capath=my_strdup((char *)arg1,MYF(MY_WME | MY_ALLOW_ZERO_PTR)); break; case MYSQL_OPT_SSL_CIPHER: my_free(mysql->options.ssl_cipher); - mysql->options.ssl_cipher=my_strdup((char *)arg1,MYF(MY_WME)); + mysql->options.ssl_cipher=my_strdup((char *)arg1,MYF(MY_WME | MY_ALLOW_ZERO_PTR)); break; case MYSQL_OPT_SSL_CRL: OPT_SET_EXTENDED_VALUE(&mysql->options, ssl_crl, (char *)arg1, 1); diff --git a/libmariadb/ma_secure.c b/libmariadb/ma_secure.c index cda76f38..a1d11aa3 100644 --- a/libmariadb/ma_secure.c +++ b/libmariadb/ma_secure.c @@ -283,10 +283,9 @@ static int my_ssl_set_certs(MYSQL *mysql) if ((certstore= SSL_CTX_get_cert_store(SSL_context))) { - if (X509_STORE_load_locations(certstore, mysql->options.ssl_ca, - mysql->options.ssl_capath) == 0 || - X509_STORE_set_flags(certstore, X509_V_FLAG_CRL_CHECK | - X509_V_FLAG_CRL_CHECK_ALL) == 0) + if (X509_STORE_load_locations(certstore, mysql->options.extension->ssl_crl, + mysql->options.extension->ssl_crlpath) == 0 || + X509_STORE_set_flags(certstore, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL) == 0) goto error; } } diff --git a/libmariadb/my_auth.c b/libmariadb/my_auth.c index 98c79678..2c8328f3 100644 --- a/libmariadb/my_auth.c +++ b/libmariadb/my_auth.c @@ -263,7 +263,7 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio, mysql->client_flag|= CLIENT_SSL; /* if server doesn't support SSL and verification of server certificate - was set to mandator, we need to return an error */ + was set to mandatory, we need to return an error */ if (mysql->options.use_ssl && !(mysql->server_capabilities & CLIENT_SSL)) { if ((mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT) || diff --git a/libmariadb/my_malloc.c b/libmariadb/my_malloc.c index 0e681cae..665d767c 100644 --- a/libmariadb/my_malloc.c +++ b/libmariadb/my_malloc.c @@ -77,7 +77,12 @@ gptr my_memdup(const unsigned char *from, size_t length, myf MyFlags) my_string my_strdup(const char *from, myf MyFlags) { gptr ptr; - uint length=(uint) strlen(from)+1; + uint length; + + if ((MyFlags & MY_ALLOW_ZERO_PTR) && !from) + return NULL; + + length=(uint) strlen(from)+1; if ((ptr=my_malloc(length,MyFlags)) != 0) memcpy((unsigned char*) ptr, (unsigned char*) from,(size_t) length); return((my_string) ptr); diff --git a/libmariadb/my_stmt.c b/libmariadb/my_stmt.c index 1f1c5b11..47a066f7 100644 --- a/libmariadb/my_stmt.c +++ b/libmariadb/my_stmt.c @@ -1887,6 +1887,7 @@ int STDCALL mysql_stmt_next_result(MYSQL_STMT *stmt) if (mysql_next_result(stmt->mysql)) { + stmt->state= MYSQL_STMT_FETCH_DONE; SET_CLIENT_STMT_ERROR(stmt, stmt->mysql->net.last_errno, stmt->mysql->net.sqlstate, stmt->mysql->net.last_error); DBUG_RETURN(1); diff --git a/libmariadb/mysql_async.c b/libmariadb/mysql_async.c index e1424509..7d5ae3b7 100644 --- a/libmariadb/mysql_async.c +++ b/libmariadb/mysql_async.c @@ -805,7 +805,7 @@ mysql_close_start(MYSQL *sock) int res; /* It is legitimate to have NULL sock argument, which will do nothing. */ - if (sock) + if (sock && sock->net.vio) { res= mysql_close_slow_part_start(sock); /* If we need to block, return now and do the rest in mysql_close_cont(). */ diff --git a/libmariadb/net.c b/libmariadb/net.c index ddf97321..0bba0b52 100644 --- a/libmariadb/net.c +++ b/libmariadb/net.c @@ -164,7 +164,11 @@ static my_bool net_realloc(NET *net, size_t length) DBUG_RETURN(1); } pkt_length = (length+IO_SIZE-1) & ~(IO_SIZE-1); - if (!(buff=(uchar*) my_realloc((char*) net->buff, pkt_length + 1, MYF(MY_WME)))) + /* reallocate buffer: + size= pkt_length + NET_HEADER_SIZE + COMP_HEADER_SIZE */ + if (!(buff=(uchar*) my_realloc((char*) net->buff, + pkt_length + NET_HEADER_SIZE + COMP_HEADER_SIZE, + MYF(MY_WME)))) { DBUG_PRINT("info", ("Out of memory")); net->error=1; diff --git a/unittest/libmariadb/async.c b/unittest/libmariadb/async.c index 4a947ab9..e54fb74d 100644 --- a/unittest/libmariadb/async.c +++ b/unittest/libmariadb/async.c @@ -200,10 +200,17 @@ static int test_conc131(MYSQL *my) return OK; } +static int test_conc129(MYSQL *my) +{ + MYSQL *mysql= mysql_init(NULL); + FAIL_IF(mysql_close_start(mysql), "No error expected"); +} + struct my_tests_st my_tests[] = { {"async1", async1, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"test_conc131", test_conc131, TEST_CONNECTION_NONE, 0, NULL, NULL}, + {"test_conc129", test_conc129, TEST_CONNECTION_NONE, 0, NULL, NULL}, {NULL, NULL, 0, 0, NULL, NULL} }; diff --git a/unittest/libmariadb/ps_bugs.c b/unittest/libmariadb/ps_bugs.c index a55dc00c..a03c8174 100644 --- a/unittest/libmariadb/ps_bugs.c +++ b/unittest/libmariadb/ps_bugs.c @@ -3868,7 +3868,46 @@ static int test_conc_5(MYSQL *mysql) return OK; } +static int test_conc141(MYSQL *mysql) +{ + int rc; + MYSQL_RES *res; + char *query= "CALL p_conc141"; + MYSQL_STMT *stmt= mysql_stmt_init(mysql); + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS conc141"); + check_mysql_rc(rc, mysql); + rc= mysql_query(mysql, "CREATE TABLE conc141 (KeyVal int not null primary key)"); + check_mysql_rc(rc, mysql); + rc= mysql_query(mysql, "INSERT INTO conc141 VALUES(1)"); + check_mysql_rc(rc, mysql); + rc= mysql_query(mysql, "DROP PROCEDURE IF EXISTS p_conc141"); + check_mysql_rc(rc, mysql); + rc= mysql_query(mysql, "CREATE PROCEDURE p_conc141()\n" + "BEGIN\n" + "select * from conc141;\n" + "insert into conc141(KeyVal) VALUES(1);\n" + "END"); + check_mysql_rc(rc, mysql); + + rc= mysql_stmt_prepare(stmt, query, strlen(query)); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + /* skip first result */ + rc= mysql_stmt_next_result(stmt); + FAIL_IF(rc==-1, "No more results and error expected"); + mysql_stmt_free_result(stmt); + FAIL_IF(mysql_stmt_errno(stmt), "No Error expected"); + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + mysql_stmt_close(stmt); + return OK; +} + struct my_tests_st my_tests[] = { + {"test_conc141", test_conc141, TEST_CONNECTION_NEW, 0, NULL , NULL}, {"test_conc67", test_conc67, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, {"test_conc_5", test_conc_5, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, {"test_bug1115", test_bug1115, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},