[glom/mysql] Some more MySQL support.
- From: Murray Cumming <murrayc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glom/mysql] Some more MySQL support.
- Date: Wed, 2 Jan 2013 21:37:27 +0000 (UTC)
commit 4bc56ab17f3abc180512a99f4df2d73ed6d2b762
Author: Murray Cumming <murrayc murrayc com>
Date: Wed Jan 2 22:37:19 2013 +0100
Some more MySQL support.
configure.ac | 14 +-
glom/libglom/connectionpool.cc | 20 ++
glom/libglom/connectionpool_backends/mysql.cc | 111 +-------
glom/libglom/connectionpool_backends/mysql.h | 7 -
.../connectionpool_backends/mysql_central.cc | 170 ++++++++++
.../connectionpool_backends/mysql_central.h | 66 ++++
glom/libglom/connectionpool_backends/mysql_self.cc | 325 +++++++-------------
glom/libglom/connectionpool_backends/mysql_self.h | 6 +
glom/libglom/document/document.cc | 34 ++-
glom/libglom/document/document.h | 6 +-
glom/libglom/filelist.am | 2 +
tests/test_selfhosting_new_empty.cc | 7 +
tests/test_selfhosting_utils.cc | 2 +
13 files changed, 429 insertions(+), 341 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index ca1ed24..38e19f1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -258,8 +258,8 @@ AS_IF([test "x$glom_host_win32" != xyes && test "x$glom_enable_client_only" != x
POSTGRES_UTILS_PATH=`pg_config --bindir 2>&AS_MESSAGE_LOG_FD`
AS_IF(["$POSTGRES_UTILS_PATH/pg_ctl" --version >/dev/null 2>&AS_MESSAGE_LOG_FD],,
[AC_MSG_ERROR([[
-The Postgres utilities could not be found. They are needed for
-self-hosting of Glom databases. Please make sure that Postgres
+The PostgreSQL utilities could not be found. They are needed for
+self-hosting of Glom databases. Please make sure that PostgreSQL
is installed, and if necessary specify the correct directory
explicitly with the --with-postgres-utils option.
]])])])])
@@ -275,8 +275,16 @@ AC_ARG_WITH([mysql-utils],
[AS_HELP_STRING([--with-mysql-utils=DIR],
[path to MySQL utilities.])],
[MYSQL_UTILS_PATH=$withval])
+# Path not needed on Windows
+AS_IF([test "x$glom_host_win32" != xyes && test "x$glom_enable_client_only" != xyes],
+ [AS_CASE([$MYSQL_UTILS_PATH], [""|no|yes],
+[
+ # TODO: Check properly instead of hard-coding /usr/bin
+ MYSQL_UTILS_PATH="/usr/bin"
+])])
+
AC_DEFINE_UNQUOTED([MYSQL_UTILS_PATH], ["$MYSQL_UTILS_PATH"],
- [Define to the location of the PostgreSQL utilities.])
+ [Define to the location of the MySQL utilities.])
GNOME_DOC_INIT([0.9.0],,
diff --git a/glom/libglom/connectionpool.cc b/glom/libglom/connectionpool.cc
index f06c3cf..9224433 100644
--- a/glom/libglom/connectionpool.cc
+++ b/glom/libglom/connectionpool.cc
@@ -29,6 +29,8 @@
#include <libglom/connectionpool_backends/postgres_central.h>
#include <libglom/connectionpool_backends/postgres_self.h>
#include <libglom/connectionpool_backends/sqlite.h>
+#include <libglom/connectionpool_backends/mysql_central.h>
+#include <libglom/connectionpool_backends/mysql_self.h>
#include <glibmm/main.h>
@@ -164,6 +166,22 @@ void ConnectionPool::setup_from_document(const Document* document)
set_backend(std::auto_ptr<ConnectionPool::Backend>(backend));
}
break;
+ case Document::HOSTING_MODE_MYSQL_SELF:
+ {
+ ConnectionPoolBackends::MySQLSelfHosted* backend = new ConnectionPoolBackends::MySQLSelfHosted;
+ backend->set_database_directory_uri(document->get_connection_self_hosted_directory_uri());
+ set_backend(std::auto_ptr<ConnectionPool::Backend>(backend));
+ }
+ break;
+ case Document::HOSTING_MODE_MYSQL_CENTRAL:
+ {
+ ConnectionPoolBackends::MySQLCentralHosted* backend = new ConnectionPoolBackends::MySQLCentralHosted;
+ backend->set_host(document->get_connection_server());
+ backend->set_port(document->get_connection_port());
+ backend->set_try_other_ports(document->get_connection_try_other_ports());
+ set_backend(std::auto_ptr<ConnectionPool::Backend>(backend));
+ }
+ break;
default:
//on_document_load() should have checked for this already, informing the user.
@@ -420,6 +438,7 @@ bool ConnectionPool::save_backup(const SlotProgress& slot_progress, const std::s
std::string uri;
try
{
+ //TODO_MySQL:
//TODO: Avoid the copy/paste of glom_postgres_data and make it work for sqlite too.
const std::string subdir = Glib::build_filename(path_dir, "glom_postgres_data");
uri = Glib::filename_to_uri(subdir);
@@ -440,6 +459,7 @@ bool ConnectionPool::convert_backup(const SlotProgress& slot_progress, const std
{
g_assert(m_backend.get());
+ //TODO_MySQL:
//TODO: Avoid this copy/paste of the directory name:
std::string path_dir_to_use = path_dir;
if(!path_dir_to_use.empty())
diff --git a/glom/libglom/connectionpool_backends/mysql.cc b/glom/libglom/connectionpool_backends/mysql.cc
index f738711..724b824 100644
--- a/glom/libglom/connectionpool_backends/mysql.cc
+++ b/glom/libglom/connectionpool_backends/mysql.cc
@@ -523,63 +523,7 @@ Glib::ustring MySQL::port_as_string(unsigned int port_num)
return result;
}
-//Because ~/.pgpass is not an absolute path.
-static std::string get_absolute_pgpass_filepath()
-{
- return Glib::build_filename(
- Glib::get_home_dir(), ".pgpass");
-}
-
-bool MySQL::save_password_to_pgpass(const Glib::ustring username, const Glib::ustring& password, std::string& filepath_previous, std::string& filepath_original)
-{
- //Initialize output variables:
- filepath_previous.clear();
- filepath_original.clear();
-
- const std::string filepath_pgpass = get_absolute_pgpass_filepath();
- filepath_original = filepath_pgpass;
-
- //Move any existing file out of the way:
- if(file_exists_filepath(filepath_pgpass))
- {
- //std::cout << "DEBUG: File exists: " << filepath_pgpass << std::endl;
- filepath_previous = filepath_pgpass + ".glombackup";
- if(g_rename(filepath_pgpass.c_str(), filepath_previous.c_str()) != 0)
- {
- std::cerr << G_STRFUNC << "Could not rename file: from=" << filepath_pgpass << ", to=" << filepath_previous << std::endl;
- return false;
- }
- }
-
- //See http://www.mysqlql.org/docs/8.4/static/libpq-pgpass.html
- //TODO: Escape \ and : characters.
- const Glib::ustring contents =
- m_host + ":" + port_as_string(m_port) + ":*:" + username + ":" + password;
-
- std::string uri;
- try
- {
- uri = Glib::filename_to_uri(filepath_pgpass);
- }
- catch(const Glib::Error& ex)
- {
- std::cerr << G_STRFUNC << ": exception from Glib::filename_from_uri(): " << ex.what() << std::endl;
- g_rename(filepath_previous.c_str(), filepath_pgpass.c_str());
- return false;
- }
-
- const bool result = create_text_file(uri, contents, true /* current user only */);
- if(!result)
- {
- std::cerr << G_STRFUNC << ": create_text_file() failed." << std::endl;
- g_rename(filepath_previous.c_str(), filepath_pgpass.c_str());
- return false;
- }
-
- return result;
-}
-
-bool MySQL::save_backup(const SlotProgress& slot_progress, const Glib::ustring& username, const Glib::ustring& password, const Glib::ustring& database_name)
+bool MySQL::save_backup(const SlotProgress& slot_progress, const Glib::ustring& username, const Glib::ustring& password, const Glib::ustring& /* database_name */)
{
/* TODO:
if(m_network_shared && !running)
@@ -614,43 +558,19 @@ bool MySQL::save_backup(const SlotProgress& slot_progress, const Glib::ustring&
return false;
}
- // Save the password to ~/.pgpass, because this is the only way to use
- // pg_dump without it asking for the password:
- std::string pgpass_backup, pgpass_original;
- const bool pgpass_created = save_password_to_pgpass(username, password, pgpass_backup, pgpass_original);
- if(!pgpass_created)
- {
- std::cerr << G_STRFUNC << ": save_password_to_pgpass() failed." << std::endl;
- return false;
- }
-
const std::string path_backup = get_self_hosting_backup_path(std::string(), true /* create parent directory if necessary */);
if(path_backup.empty())
return false;
// Make sure to use double quotes for the executable path, because the
// CreateProcess() API used on Windows does not support single quotes.
- const std::string command_dump = get_path_to_mysql_executable("pg_dump") +
- " --format=c " + // The default (plain) format cannot be used with pg_restore.
- " --create --file=" + Glib::shell_quote(path_backup) +
- " --host=" + Glib::shell_quote(m_host) +
- " --port=" + port_as_string(m_port) +
- " --username=" + Glib::shell_quote(username) +
- " " + database_name; //TODO: Quote database_name?
+ const std::string command_dump; //TODO_MySQL
//std::cout << "DEBUG: command_dump=" << command_dump << std::endl;
const bool result = Glom::Spawn::execute_command_line_and_wait(command_dump, slot_progress);
- //Move the previously-existing .pgpass file back:
- //TODO: Really, we should just edit the file instead of completely replacing it,
- // because another application might try to edit it in the meantime.
- if(!pgpass_backup.empty())
- {
- g_rename(pgpass_backup.c_str(), pgpass_original.c_str());
- }
-
if(!result)
{
std::cerr << "Error while attempting to call pg_dump." << std::endl;
@@ -659,7 +579,7 @@ bool MySQL::save_backup(const SlotProgress& slot_progress, const Glib::ustring&
return result;
}
-bool MySQL::convert_backup(const SlotProgress& slot_progress, const std::string& base_directory, const Glib::ustring& username, const Glib::ustring& password, const Glib::ustring& database_name)
+bool MySQL::convert_backup(const SlotProgress& slot_progress, const std::string& base_directory, const Glib::ustring& username, const Glib::ustring& password, const Glib::ustring& /* database_name */)
{
/* TODO:
if(m_network_shared && !running)
@@ -702,24 +622,9 @@ bool MySQL::convert_backup(const SlotProgress& slot_progress, const std::string&
return false;
}
- // Save the password to ~/.pgpass, because this is the only way to use
- // pg_dump without it asking for the password:
- std::string pgpass_backup, pgpass_original;
- const bool pgpass_created = save_password_to_pgpass(username, password, pgpass_backup, pgpass_original);
- if(!pgpass_created)
- {
- std::cerr << G_STRFUNC << ": save_password_to_pgpass() failed." << std::endl;
- return false;
- }
-
// Make sure to use double quotes for the executable path, because the
// CreateProcess() API used on Windows does not support single quotes.
- const std::string command_restore = get_path_to_mysql_executable("pg_restore") +
- " -d " + database_name + //TODO: Quote database name?
- " --host=" + Glib::shell_quote(m_host) +
- " --port=" + port_as_string(m_port) +
- " --username=" + Glib::shell_quote(username) +
- " " + path_backup;
+ const std::string command_restore; //TODO_MySQL
std::cout << "DEBUG: command_restore=" << command_restore << std::endl;
@@ -727,14 +632,6 @@ bool MySQL::convert_backup(const SlotProgress& slot_progress, const std::string&
const bool result = Glom::Spawn::execute_command_line_and_wait(command_restore, slot_progress);
- //Move the previously-existing .pgpass file back:
- //TODO: Really, we should just edit the file instead of completely replacing it,
- // because another application might try to edit it in the meantime.
- if(!pgpass_backup.empty())
- {
- g_rename(pgpass_backup.c_str(), pgpass_original.c_str());
- }
-
if(!result)
{
std::cerr << "Error while attempting to call pg_restore." << std::endl;
diff --git a/glom/libglom/connectionpool_backends/mysql.h b/glom/libglom/connectionpool_backends/mysql.h
index d711a38..218cccc 100644
--- a/glom/libglom/connectionpool_backends/mysql.h
+++ b/glom/libglom/connectionpool_backends/mysql.h
@@ -97,13 +97,6 @@ protected:
*/
static bool create_text_file(const std::string& file_uri, const std::string& contents, bool current_user_only = false);
- /**
- * @param filepath_previous The path to which the previous .pgpass, if any was moved.
- * @param filepath_original The path to which filepath_previous should be moved back after the caller has finished.
- * @param result whether it succeeded.
- */
- bool save_password_to_pgpass(const Glib::ustring username, const Glib::ustring& password, std::string& filepath_previous, std::string& filepath_original);
-
protected:
static Glib::ustring port_as_string(unsigned int port_num);
diff --git a/glom/libglom/connectionpool_backends/mysql_central.cc b/glom/libglom/connectionpool_backends/mysql_central.cc
new file mode 100644
index 0000000..5bbbda6
--- /dev/null
+++ b/glom/libglom/connectionpool_backends/mysql_central.cc
@@ -0,0 +1,170 @@
+/* Glom
+ *
+ * Copyright (C) 2001-2004 Murray Cumming
+ *
+ * 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; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ */
+
+#include <libglom/libglom_config.h>
+
+#include <libglom/connectionpool_backends/mysql_central.h>
+#include <glibmm/i18n.h>
+
+// Uncomment to see debug messages
+//#define GLOM_CONNECTION_DEBUG
+
+namespace Glom
+{
+
+namespace ConnectionPoolBackends
+{
+
+MySQLCentralHosted::MySQLCentralHosted()
+: m_try_other_ports(true)
+{
+ //TODO_MySQL:
+ m_list_ports.push_back("5432"); //Ubuntu Breezy seems to default to this for MySQL 7.4, and this is probably the default for most mysql installations, including Fedora.
+
+ m_list_ports.push_back("5433"); //Ubuntu Dapper seems to default to this for MySQL 8.1, probably to avoid a clash with MySQL 7.4
+
+ m_list_ports.push_back("5434"); //Earlier versions of Ubuntu Feisty defaulted to this for MySQL 8.2.
+ m_list_ports.push_back("5435"); //In case Ubuntu increases the port number again in future.
+ m_list_ports.push_back("5436"); //In case Ubuntu increases the port number again in future.
+}
+
+void MySQLCentralHosted::set_host(const Glib::ustring& value)
+{
+ if(value != m_host)
+ {
+ m_host = value;
+
+ // Force us to try all ports again when connecting for the first time, then remember the working port again. Except when a specific port was set to be used.
+ if(m_try_other_ports)
+ m_port = 0;
+ }
+}
+
+void MySQLCentralHosted::set_port(unsigned int port)
+{
+ m_port = port;
+}
+
+void MySQLCentralHosted::set_try_other_ports(bool val)
+{
+ m_try_other_ports = val;
+}
+
+Glib::ustring MySQLCentralHosted::get_host() const
+{
+ return m_host;
+}
+
+unsigned int MySQLCentralHosted::get_port() const
+{
+ return m_port;
+}
+
+bool MySQLCentralHosted::get_try_other_ports() const
+{
+ return m_try_other_ports;
+}
+
+Glib::RefPtr<Gnome::Gda::Connection> MySQLCentralHosted::connect(const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password, bool fake_connection)
+{
+ Glib::RefPtr<Gnome::Gda::Connection> connection;
+
+ //Try each possible network port:
+ type_list_ports::const_iterator iter_port = m_list_ports.begin();
+
+ //Start with the remembered-as-working port:
+ Glib::ustring port = port_as_string(m_port);
+ if(m_port == 0)
+ port = *iter_port ++;
+
+ bool connection_possible = false;
+ try
+ {
+ connection = attempt_connect(port, database, username, password, fake_connection);
+ connection_possible = true;
+ m_port = atoi(port.c_str());
+ }
+ catch(const ExceptionConnection& ex)
+ {
+ // Remember port if only the database was missing
+ connection_possible = false;
+ if(ex.get_failure_type() == ExceptionConnection::FAILURE_NO_DATABASE)
+ {
+ connection_possible = true;
+ m_port = atoi(port.c_str());
+ }
+ }
+
+ // Try more ports if so desired, and we don't have a connection yet
+ if(m_try_other_ports && !connection)
+ {
+ while(!connection && iter_port != m_list_ports.end())
+ {
+ port = *iter_port;
+
+ try
+ {
+ connection = attempt_connect(port, database, username, password, fake_connection);
+ connection_possible = true;
+ m_port = atoi(port.c_str());
+ }
+ catch(const ExceptionConnection& ex)
+ {
+ //Don't set this, because we might have previously set it to true to
+ //show that a connection was possible with a previously-tried port: connection_possible = false;
+
+ // Remember port if only the database was missing
+ if(ex.get_failure_type() == ExceptionConnection::FAILURE_NO_DATABASE)
+ {
+ connection_possible = true;
+ m_port = atoi(port.c_str());
+ }
+ }
+
+ // Skip if we already tried this port
+ if(iter_port != m_list_ports.end() && *iter_port == port)
+ ++ iter_port;
+ }
+ }
+
+ if(connection)
+ {
+ //Remember working port:
+ m_port = atoi(port.c_str());
+ }
+ else
+ {
+ if(connection_possible)
+ throw ExceptionConnection(ExceptionConnection::FAILURE_NO_DATABASE);
+ else
+ throw ExceptionConnection(ExceptionConnection::FAILURE_NO_SERVER);
+ }
+
+ return connection;
+}
+
+bool MySQLCentralHosted::create_database(const SlotProgress& slot_progress, const Glib::ustring& database_name, const Glib::ustring& username, const Glib::ustring& password)
+{
+ return attempt_create_database(slot_progress, database_name, get_host(), port_as_string(m_port), username, password);
+}
+
+}
+
+}
diff --git a/glom/libglom/connectionpool_backends/mysql_central.h b/glom/libglom/connectionpool_backends/mysql_central.h
new file mode 100644
index 0000000..8bdbbfb
--- /dev/null
+++ b/glom/libglom/connectionpool_backends/mysql_central.h
@@ -0,0 +1,66 @@
+/* Glom
+ *
+ * Copyright (C) 2001-2004 Murray Cumming
+ *
+ * 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; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ */
+
+#ifndef GLOM_BACKEND_MYSQL_CENTRAL_H
+#define GLOM_BACKEND_MYSQL_CENTRAL_H
+
+#include <libglom/connectionpool_backends/mysql.h>
+
+#include <libglom/libglom_config.h>
+
+namespace Glom
+{
+
+namespace ConnectionPoolBackends
+{
+
+class MySQLCentralHosted : public MySQL
+{
+public:
+ MySQLCentralHosted();
+
+ /** 0 means any port
+ * Other ports will be tried if the specified port fails.
+ */
+ void set_host(const Glib::ustring& value);
+ void set_port(unsigned int port);
+ void set_try_other_ports(bool val);
+
+ Glib::ustring get_host() const;
+ unsigned int get_port() const;
+ bool get_try_other_ports() const;
+
+private:
+ virtual Glib::RefPtr<Gnome::Gda::Connection> connect(const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password, bool fake_connection = false);
+
+ virtual bool create_database(const SlotProgress& slot_progress, const Glib::ustring& database_name, const Glib::ustring& username, const Glib::ustring& password);
+
+private:
+ typedef std::vector<Glib::ustring> type_list_ports;
+ type_list_ports m_list_ports;
+
+ bool m_try_other_ports;
+};
+
+} //namespace ConnectionPoolBackends
+
+} //namespace Glom
+
+#endif //GLOM_BACKEND_MYSQL_CENTRAL_H
diff --git a/glom/libglom/connectionpool_backends/mysql_self.cc b/glom/libglom/connectionpool_backends/mysql_self.cc
index aa64130..3d910b1 100644
--- a/glom/libglom/connectionpool_backends/mysql_self.cc
+++ b/glom/libglom/connectionpool_backends/mysql_self.cc
@@ -27,6 +27,7 @@
#include <glib/gstdio.h> // For g_remove
#include <glibmm/convert.h>
+#include <glibmm/fileutils.h>
#include <glibmm/miscutils.h>
#include <glibmm/stringutils.h>
#include <glibmm/regex.h>
@@ -59,39 +60,15 @@ namespace Glom
namespace ConnectionPoolBackends
{
-
-#define DEFAULT_CONFIG_PG_HBA_LOCAL \
-"# TYPE DATABASE USER CIDR-ADDRESS METHOD\n" \
-"\n" \
-"# local is for Unix domain socket connections only\n" \
-"# trust allows connection from the current PC without a password:\n" \
-"local all all trust\n" \
-"local all all md5\n" \
-"\n" \
-"# TCP connections from the same computer, with a password:\n" \
-"host all all 127.0.0.1 255.255.255.255 md5\n" \
-"# IPv6 local connections:\n" \
-"host all all ::1/128 md5\n"
-
-#define DEFAULT_CONFIG_PG_HBA_REMOTE_EXTRA \
-"\n" \
-"# IPv4 local connections:\n" \
-"host all all 0.0.0.0/0 md5\n" \
-"# IPv6 local connections:\n" \
-"host all all ::1/128 md5\n"
-
-#define DEFAULT_CONFIG_PG_HBA_REMOTE \
-DEFAULT_CONFIG_PG_HBA_LOCAL \
-DEFAULT_CONFIG_PG_HBA_REMOTE_EXTRA
-
-static const int PORT_MYSQL_SELF_HOSTED_START = 5433;
-static const int PORT_MYSQL_SELF_HOSTED_END = 5500;
+static const int PORT_MYSQL_SELF_HOSTED_START = 3306;
+static const int PORT_MYSQL_SELF_HOSTED_END = 3350;
static const char FILENAME_DATA[] = "data";
static const char FILENAME_BACKUP[] = "backup";
MySQLSelfHosted::MySQLSelfHosted()
-: m_network_shared(false)
+: m_network_shared(false),
+ m_temporary_password_active(false)
{
m_host = "localhost";
}
@@ -179,17 +156,8 @@ Backend::InitErrors MySQLSelfHosted::initialize(const SlotProgress& slot_progres
return INITERROR_COULD_NOT_CREATE_DIRECTORY;
}
- //Create the config directory:
- const std::string dbdir_config = get_self_hosting_config_path(true /* create */);
- if(dbdir_config.empty())
- {
- std::cerr << "Couldn't create the config directory: " << dbdir << std::endl;
-
- return INITERROR_COULD_NOT_CREATE_DIRECTORY;
- }
-
- //Create these files: environment, pg_hba.conf, start.conf
- set_network_shared(slot_progress, m_network_shared); //Creates pg_hba.conf
+ //Create these files: environment
+ set_network_shared(slot_progress, m_network_shared);
//Check that there is not an existing data directory:
const std::string dbdir_data = get_self_hosting_data_path(true /* create */);
@@ -202,139 +170,65 @@ Backend::InitErrors MySQLSelfHosted::initialize(const SlotProgress& slot_progres
// initdb creates a new mysql database cluster:
- //Get file:// URI for the tmp/ directory:
- const std::string temp_pwfile = Utils::get_temp_file_path("glom_initdb_pwfile");
- const Glib::ustring temp_pwfile_uri = Glib::filename_to_uri(temp_pwfile);
- const bool pwfile_creation_succeeded = create_text_file(temp_pwfile_uri, password);
- g_assert(pwfile_creation_succeeded);
-
// Make sure to use double quotes for the executable path, because the
// CreateProcess() API used on Windows does not support single quotes.
- const std::string command_initdb = get_path_to_mysql_executable("initdb") + " -D " + Glib::shell_quote(dbdir_data) +
- " -U " + initial_username + " --pwfile=" + Glib::shell_quote(temp_pwfile);
-
- //Note that --pwfile takes the password from the first line of a file. It's an alternative to supplying it when prompted on stdin.
- const bool result = Glom::Spawn::execute_command_line_and_wait(command_initdb, slot_progress);
+ // We don't use mysql_secure_installation because it only takes the details via prompts.
+ // TODO: With MySQL 5.6, use the new --random-passwords option, because otherwise the root password will be blank,
+ // and, at least on Ubuntu, we will then not be able to connect with mysqladmin.
+ const std::string command_initdb = get_path_to_mysql_executable("mysql_install_db")
+ + " --no-defaults" //Otherwise Ubuntu specifies --user=mysql
+ + " --datadir=" + Glib::shell_quote(dbdir_data);
+ //TODO: + " --random-passwords";
+ std::cout << "debug: command_initdb=" << command_initdb << std::endl;
+ bool result = Glom::Spawn::execute_command_line_and_wait(command_initdb, slot_progress);
if(!result)
{
- std::cerr << "Error while attempting to create self-hosting database." << std::endl;
+ std::cerr << "Error while attempting to create self-hosting MySQL database." << std::endl;
}
+ else
+ {
+ //This is used during the first start:
+ m_initial_password_to_set = password;
+
+ //TODO: With MySQL 5.6, use the new --random-passwords option (see above)
+ m_temporary_password = "";
+ m_temporary_password_active = true;
+ //Get the temporary random password,
+ //which will be used when first starting the server.
+ /*
+ const std::string temporary_password_file = Glib::build_filename(
+ Glib::get_home_dir(), ".mysql.secret");
+ try
+ {
+ m_temporary_password = Glib::file_get_contents(temporary_password_file);
+ m_temporary_password_active = true;
+ }
+ catch(const Glib::Error& ex)
+ {
+ std::cerr << G_STRFUNC << "file_get_contents() failed: " << ex.what() << std::endl;
+ }
- const int temp_pwfile_removed = g_remove(temp_pwfile.c_str()); //Of course, we don't want this to stay around. It would be a security risk.
- g_assert(temp_pwfile_removed == 0);
+ if(m_temporary_password.empty())
+ {
+ std::cerr << G_STRFUNC << " Unable to discover the initial MySQL password." << std::endl;
+ result = false;
+ }
+ */
+ }
return result ? INITERROR_NONE : INITERROR_COULD_NOT_START_SERVER;
}
-Glib::ustring MySQLSelfHosted::get_mysqlql_utils_version(const SlotProgress& slot_progress)
+Glib::ustring MySQLSelfHosted::get_mysqlql_utils_version(const SlotProgress& /* slot_progress */)
{
- Glib::ustring result;
-
- const std::string command = get_path_to_mysql_executable("pg_ctl") + " --version";
-
- //The first command does not return, but the second command can check whether it succeeded:
- std::string output;
- const bool spawn_result = Glom::Spawn::execute_command_line_and_wait(command, slot_progress, output);
- if(!spawn_result)
- {
- std::cerr << "Error while attempting to discover the pg_ctl version." << std::endl;
- return result;
- }
-
- //Use a regex to get the version number:
- Glib::RefPtr<Glib::Regex> regex;
-
- //We want the characters at the end:
- const gchar VERSION_REGEX[] = "pg_ctl \\(MySQL\\) (.*)";
-
- try
- {
- regex = Glib::Regex::create(VERSION_REGEX);
- }
- catch(const Glib::Error& ex)
- {
- std::cerr << "Glom: Glib::Regex::create() failed: " << ex.what() << std::endl;
- return result;
- }
-
- if(!regex)
- return result;
-
- typedef std::vector<Glib::ustring> type_vec_strings;
- const type_vec_strings vec = regex->split(output, Glib::REGEX_MATCH_NOTEMPTY);
- //std::cout << "DEBUG: output == " << output << std::endl;
- //std::cout << "DEBUG: vec.size() == " << vec.size() << std::endl;
-
- // We get, for instance, "\n" and 8.4.1" and "\n".
- for(type_vec_strings::const_iterator iter = vec.begin();
- iter != vec.end();
- ++iter)
- {
- const Glib::ustring str = *iter;
- if(!str.empty())
- return str; //Found.
- }
-
- return result;
+ return Glib::ustring(); //TODO
}
-float MySQLSelfHosted::get_mysqlql_utils_version_as_number(const SlotProgress& slot_progress)
+float MySQLSelfHosted::get_mysqlql_utils_version_as_number(const SlotProgress& /* slot_progress */)
{
- float result = 0;
-
- const Glib::ustring version_str = get_mysqlql_utils_version(slot_progress);
-
- Glib::RefPtr<Glib::Regex> regex;
-
- //We want the characters at the end:
- const gchar VERSION_REGEX[] = "^(\\d*)\\.(\\d*)";
-
- try
- {
- regex = Glib::Regex::create(VERSION_REGEX);
- }
- catch(const Glib::Error& ex)
- {
- std::cerr << "Glom: Glib::Regex::create() failed: " << ex.what() << std::endl;
- return result;
- }
-
- if(!regex)
- return result;
-
- typedef std::vector<Glib::ustring> type_vec_strings;
- const type_vec_strings vec = regex->split(version_str, Glib::REGEX_MATCH_NOTEMPTY);
- //std::cout << "DEBUG: str == " << version_str << std::endl;
- //std::cout << "DEBUG: vec.size() == " << vec.size() << std::endl;
-
- //We need to loop over the numbers because we get some "" items that we want to ignore:
- guint count = 0; //We want 2 numbers.
- for(type_vec_strings::const_iterator iter = vec.begin();
- iter != vec.end();
- ++iter)
- {
- //std::cout << "regex item: START" << *iter << "END" << std::endl;
-
- const Glib::ustring str = *iter;
- if(str.empty())
- continue;
-
- const float num = atoi(str.c_str());
- if(count == 0)
- result = num;
- else if(count == 1)
- {
- result += (0.1 * num);
- break;
- }
-
- ++count;
- }
-
- return result;
+ return 0; //TODO
}
-
Backend::StartupErrors MySQLSelfHosted::startup(const SlotProgress& slot_progress, bool network_shared)
{
m_network_shared = network_shared;
@@ -381,7 +275,7 @@ Backend::StartupErrors MySQLSelfHosted::startup(const SlotProgress& slot_progres
}
//Attempt to ensure that the config files are correct:
- set_network_shared(slot_progress, m_network_shared); //Creates pg_hba.conf
+ set_network_shared(slot_progress, m_network_shared);
const unsigned int available_port = discover_first_free_port(PORT_MYSQL_SELF_HOSTED_START, PORT_MYSQL_SELF_HOSTED_END);
//std::cout << "debug: " << G_STRFUNC << ":() : debug: Available port for self-hosting: " << available_port << std::endl;
@@ -395,46 +289,57 @@ Backend::StartupErrors MySQLSelfHosted::startup(const SlotProgress& slot_progres
//TODO: Performance:
const std::string port_as_text = Glib::Ascii::dtostr(available_port);
- // -D specifies the data directory.
- // -c config_file= specifies the configuration file
- // -k specifies a directory to use for the socket. This must be writable by us.
// Make sure to use double quotes for the executable path, because the
// CreateProcess() API used on Windows does not support single quotes.
- const std::string dbdir_config = Glib::build_filename(dbdir, "config");
- const std::string dbdir_hba = Glib::build_filename(dbdir_config, "pg_hba.conf");
const std::string dbdir_pid = Glib::build_filename(dbdir, "pid");
- const std::string listen_address = (m_network_shared ? "*" : "localhost");
- const std::string command_mysql_start = get_path_to_mysql_executable("mysql") + " -D " + Glib::shell_quote(dbdir_data)
- + " -p " + port_as_text
- + " -h " + listen_address
- + " -c hba_file=" + Glib::shell_quote(dbdir_hba)
- + " -k " + Glib::shell_quote(dbdir)
- + " --external_pid_file=" + Glib::shell_quote(dbdir_pid);
- //std::cout << G_STRFUNC << ": debug: " << command_mysql_start << std::endl;
+ const std::string dbdir_socket = Glib::build_filename(dbdir, "mysqld.sock");
+ const std::string command_mysql_start = get_path_to_mysql_executable("mysqld_safe")
+ + " --no-defaults"
+ + " --port=" + port_as_text
+ + " --datadir=" + Glib::shell_quote(dbdir_data)
+ + " --socket=" + Glib::shell_quote(dbdir_socket)
+ + " --pid-file=" + Glib::shell_quote(dbdir_pid);
+ std::cout << G_STRFUNC << ": debug: command_mysql_start=" << command_mysql_start << std::endl;
+
+ m_port = available_port; //Needed by get_mysqladmin_command().
+ const std::string command_check_mysql_has_started = get_mysqladmin_command(m_temporary_password) //TODO: Get the temporary password in a callback.
+ + " ping";
+ const std::string second_command_success_text = "mysqld is alive"; //TODO: This is not a stable API. Also, watch out for localisation.
+ std::cout << G_STRFUNC << ": debug: command_check_mysql_has_started=" << command_check_mysql_has_started << std::endl;
- // Make sure to use double quotes for the executable path, because the
- // CreateProcess() API used on Windows does not support single quotes.
- const std::string command_check_mysql_has_started = get_path_to_mysql_executable("pg_ctl") + " status -D " + Glib::shell_quote(dbdir_data);
-
- //For mysql 8.1, this is "postmaster is running".
- //For mysql 8.2, this is "server is running".
- //This is a big hack that we should avoid. murrayc.
- //
- //pg_ctl actually seems to return a 0 result code for "is running" and a 1 for not running, at least with MySQL 8.2,
- //so maybe we can avoid this in future.
- //Please do test it with your mysql version, using "echo $?" to see the result code of the last command.
- const std::string second_command_success_text = "is running"; //TODO: This is not a stable API. Also, watch out for localisation.
-
- //The first command does not return, but the second command can check whether it succeeded:
const bool result = Glom::Spawn::execute_command_line_and_wait_until_second_command_returns_success(command_mysql_start, command_check_mysql_has_started, slot_progress, second_command_success_text);
+
if(!result)
{
- std::cerr << "Error while attempting to self-host a database." << std::endl;
+ m_port = 0;
+
+ std::cerr << "Error while attempting to self-host a MySQL database." << std::endl;
return STARTUPERROR_FAILED_UNKNOWN_REASON;
}
m_port = available_port; //Remember it for later.
+ //If necessary, set the initial password:
+ if(m_temporary_password_active)
+ {
+ const std::string command_initdb_initial_password = get_mysqladmin_command(m_temporary_password)
+ + " password" + Glib::shell_quote(m_initial_password_to_set);
+ std::cout << "debug: command_initdb_initial_password=" << command_initdb_initial_password << std::endl;
+
+ const bool result = Glom::Spawn::execute_command_line_and_wait(command_initdb_initial_password, slot_progress);
+
+ if(!result)
+ {
+ std::cerr << "Error while attempting to start self-hosting MySQL database, when setting the initial password." << std::endl;
+ return STARTUPERROR_FAILED_UNKNOWN_REASON;
+ }
+
+ m_temporary_password_active = false;
+ m_temporary_password.clear();
+
+ //TODO_MySQL: " -U " + initial_username
+ }
+
return STARTUPERROR_NONE;
}
@@ -476,6 +381,17 @@ void MySQLSelfHosted::show_active_connections()
gda_connection->close();
}
+std::string MySQLSelfHosted::get_mysqladmin_command(const Glib::ustring& password)
+{
+ const std::string port_as_text = Glib::Ascii::dtostr(m_port);
+
+ return get_path_to_mysql_executable("mysqladmin")
+ + " --no-defaults"
+ + " --port=" + port_as_text
+ + " --user=root"
+ + " --password=" + Glib::shell_quote(password);
+}
+
bool MySQLSelfHosted::cleanup(const SlotProgress& slot_progress)
{
// This seems to be called twice sometimes, so we don't assert here until
@@ -485,15 +401,7 @@ bool MySQLSelfHosted::cleanup(const SlotProgress& slot_progress)
if(!get_self_hosting_active())
return true; //Don't try to stop it if we have not started it.
- const std::string dbdir_uri = m_database_directory_uri;
- const std::string dbdir = Glib::filename_from_uri(dbdir_uri);
- g_assert(!dbdir.empty());
-
- const std::string dbdir_data = Glib::build_filename(dbdir, FILENAME_DATA);
-
-
- // TODO: Detect other instances on the same computer, and use a different port number,
- // or refuse to continue, showing an error dialog.
+ const std::string port_as_text = Glib::Ascii::dtostr(m_port);
// -D specifies the data directory.
// -c config_file= specifies the configuration file
@@ -502,11 +410,12 @@ bool MySQLSelfHosted::cleanup(const SlotProgress& slot_progress)
// TODO: Warn about connected clients on other computers? Warn those other users?
// Make sure to use double quotes for the executable path, because the
// CreateProcess() API used on Windows does not support single quotes.
- const std::string command_mysql_stop = get_path_to_mysql_executable("pg_ctl") + " -D " + Glib::shell_quote(dbdir_data) + " stop -m fast";
+ const std::string command_mysql_stop = get_mysqladmin_command("" /* m_password */)
+ + " shutdown";
const bool result = Glom::Spawn::execute_command_line_and_wait(command_mysql_stop, slot_progress);
if(!result)
{
- std::cerr << "Error while attempting to stop self-hosting of the database. Trying again." << std::endl;
+ std::cerr << "Error while attempting to stop self-hosting of the MySQL database. Trying again." << std::endl;
//Show open connections for debugging:
try
@@ -515,7 +424,7 @@ bool MySQLSelfHosted::cleanup(const SlotProgress& slot_progress)
}
catch(const Glib::Error& ex)
{
- std::cerr << G_STRFUNC << ": exception while trying to show active connections: " << ex.what() << std::endl;
+ std::cerr << G_STRFUNC << ": exception while trying to show active MySQL connections: " << ex.what() << std::endl;
}
//I've seen it fail when running under valgrind, and there are reports of failures in bug #420962.
@@ -541,27 +450,7 @@ bool MySQLSelfHosted::set_network_shared(const SlotProgress& /* slot_progress */
m_network_shared = network_shared;
- const std::string dbdir_uri = m_database_directory_uri;
- const std::string dbdir = Glib::filename_from_uri(dbdir_uri);
-
- const std::string dbdir_uri_config = dbdir_uri + "/config";
- const char* default_conf_contents = 0;
-
- // Choose the configuration contents based on
- // whether we want to be network-shared:
- //const float mysqlql_version = get_mysqlql_utils_version_as_number(slot_progress);
- //std::cout << "DEBUG: mysqlql_version=" << mysqlql_version << std::endl;
-
- default_conf_contents = m_network_shared ? DEFAULT_CONFIG_PG_HBA_REMOTE : DEFAULT_CONFIG_PG_HBA_LOCAL;
-
- //std::cout << "DEBUG: default_conf_contents=" << default_conf_contents << std::endl;
-
- const bool hba_conf_creation_succeeded = create_text_file(dbdir_uri_config + "/pg_hba.conf", default_conf_contents);
- g_assert(hba_conf_creation_succeeded);
- if(!hba_conf_creation_succeeded)
- return false;
-
- return hba_conf_creation_succeeded;
+ return true;
}
static bool on_timeout_delay(const Glib::RefPtr<Glib::MainLoop>& mainloop)
diff --git a/glom/libglom/connectionpool_backends/mysql_self.h b/glom/libglom/connectionpool_backends/mysql_self.h
index 538a9b2..4216154 100644
--- a/glom/libglom/connectionpool_backends/mysql_self.h
+++ b/glom/libglom/connectionpool_backends/mysql_self.h
@@ -55,6 +55,8 @@ public:
static bool install_mysql(const SlotProgress& slot_progress);
private:
+ std::string get_mysqladmin_command(const Glib::ustring& password);
+
virtual InitErrors initialize(const SlotProgress& slot_progress, const Glib::ustring& initial_username, const Glib::ustring& password, bool network_shared = false);
virtual StartupErrors startup(const SlotProgress& slot_progress, bool network_shared = false);
@@ -86,6 +88,10 @@ private:
//These are only remembered in order to use them to provide debug
//information when the MySQL shutdown fails:
Glib::ustring m_saved_database_name, m_saved_username, m_saved_password;
+
+ bool m_temporary_password_active; //Whether the password is an initial temporary one.
+ Glib::ustring m_initial_password_to_set;
+ Glib::ustring m_temporary_password;
};
} // namespace ConnectionPoolBackends
diff --git a/glom/libglom/document/document.cc b/glom/libglom/document/document.cc
index 2718d26..9b394b4 100644
--- a/glom/libglom/document/document.cc
+++ b/glom/libglom/document/document.cc
@@ -58,6 +58,8 @@ static const char GLOM_ATTRIBUTE_CONNECTION_HOSTING_MODE[] = "hosting_mode";
static const char GLOM_ATTRIBUTE_CONNECTION_HOSTING_POSTGRES_CENTRAL[] = "postgres_central";
static const char GLOM_ATTRIBUTE_CONNECTION_HOSTING_POSTGRES_SELF[] = "postgres_self";
static const char GLOM_ATTRIBUTE_CONNECTION_HOSTING_SQLITE[] = "sqlite";
+static const char GLOM_ATTRIBUTE_CONNECTION_HOSTING_MYSQL_CENTRAL[] = "mysql_central";
+static const char GLOM_ATTRIBUTE_CONNECTION_HOSTING_MYSQL_SELF[] = "mysql_self";
static const char GLOM_ATTRIBUTE_CONNECTION_NETWORK_SHARED[] = "network_shared";
static const char GLOM_ATTRIBUTE_CONNECTION_SERVER[] = "server";
static const char GLOM_ATTRIBUTE_CONNECTION_PORT[] = "port";
@@ -341,8 +343,11 @@ bool Document::get_network_shared() const
//Enforce constraints:
const HostingMode hosting_mode = get_hosting_mode();
- if(hosting_mode == HOSTING_MODE_POSTGRES_CENTRAL)
+ if( (hosting_mode == HOSTING_MODE_POSTGRES_CENTRAL) ||
+ (hosting_mode == HOSTING_MODE_MYSQL_CENTRAL) )
+ {
shared = true; //Central hosting means that it must be shared on the network.
+ }
else if(hosting_mode == HOSTING_MODE_SQLITE)
shared = false; //sqlite does not allow network sharing.
@@ -378,6 +383,12 @@ std::string Document::get_connection_self_hosted_directory_uri() const
case HOSTING_MODE_SQLITE:
datadir = parent;
break;
+ case HOSTING_MODE_MYSQL_SELF:
+ datadir = parent->get_child("glom_mysql_data");
+ break;
+ case HOSTING_MODE_MYSQL_CENTRAL:
+ datadir = parent;
+ break;
default:
g_assert_not_reached();
break;
@@ -2547,6 +2558,10 @@ bool Document::load_after(int& failure_code)
mode = HOSTING_MODE_POSTGRES_SELF;
else if(attr_mode == GLOM_ATTRIBUTE_CONNECTION_HOSTING_SQLITE)
mode = HOSTING_MODE_SQLITE;
+ else if(attr_mode == GLOM_ATTRIBUTE_CONNECTION_HOSTING_MYSQL_CENTRAL)
+ mode = HOSTING_MODE_MYSQL_CENTRAL;
+ else if(attr_mode == GLOM_ATTRIBUTE_CONNECTION_HOSTING_MYSQL_SELF)
+ mode = HOSTING_MODE_MYSQL_SELF;
else
{
std::cerr << G_STRFUNC << ": Hosting mode " << attr_mode << " is not supported" << std::endl;
@@ -3570,13 +3585,24 @@ bool Document::save_before()
switch(m_hosting_mode)
{
case HOSTING_MODE_POSTGRES_CENTRAL:
- XmlUtils::set_node_attribute_value(nodeConnection, GLOM_ATTRIBUTE_CONNECTION_HOSTING_MODE, GLOM_ATTRIBUTE_CONNECTION_HOSTING_POSTGRES_CENTRAL);
+ XmlUtils::set_node_attribute_value(nodeConnection,
+ GLOM_ATTRIBUTE_CONNECTION_HOSTING_MODE, GLOM_ATTRIBUTE_CONNECTION_HOSTING_POSTGRES_CENTRAL);
break;
case HOSTING_MODE_POSTGRES_SELF:
- XmlUtils::set_node_attribute_value(nodeConnection, GLOM_ATTRIBUTE_CONNECTION_HOSTING_MODE, GLOM_ATTRIBUTE_CONNECTION_HOSTING_POSTGRES_SELF);
+ XmlUtils::set_node_attribute_value(nodeConnection,
+ GLOM_ATTRIBUTE_CONNECTION_HOSTING_MODE, GLOM_ATTRIBUTE_CONNECTION_HOSTING_POSTGRES_SELF);
break;
case HOSTING_MODE_SQLITE:
- XmlUtils::set_node_attribute_value(nodeConnection, GLOM_ATTRIBUTE_CONNECTION_HOSTING_MODE, GLOM_ATTRIBUTE_CONNECTION_HOSTING_SQLITE);
+ XmlUtils::set_node_attribute_value(nodeConnection,
+ GLOM_ATTRIBUTE_CONNECTION_HOSTING_MODE, GLOM_ATTRIBUTE_CONNECTION_HOSTING_SQLITE);
+ break;
+ case HOSTING_MODE_MYSQL_CENTRAL:
+ XmlUtils::set_node_attribute_value(nodeConnection,
+ GLOM_ATTRIBUTE_CONNECTION_HOSTING_MODE, GLOM_ATTRIBUTE_CONNECTION_HOSTING_MYSQL_CENTRAL);
+ break;
+ case HOSTING_MODE_MYSQL_SELF:
+ XmlUtils::set_node_attribute_value(nodeConnection,
+ GLOM_ATTRIBUTE_CONNECTION_HOSTING_MODE, GLOM_ATTRIBUTE_CONNECTION_HOSTING_MYSQL_SELF);
break;
default:
g_assert_not_reached();
diff --git a/glom/libglom/document/document.h b/glom/libglom/document/document.h
index 58d5dfd..fd12fd6 100644
--- a/glom/libglom/document/document.h
+++ b/glom/libglom/document/document.h
@@ -106,9 +106,11 @@ public:
/// How the database is hosted.
enum HostingMode
{
- HOSTING_MODE_POSTGRES_CENTRAL, /*!< The database is hosted on an external postgresql server. */
- HOSTING_MODE_POSTGRES_SELF, /*!< A new postgres database process is spawned that hosts the data. */
+ HOSTING_MODE_POSTGRES_CENTRAL, /*!< The database is hosted on an external PostgreSQL server. */
+ HOSTING_MODE_POSTGRES_SELF, /*!< A new PostgreSQL database process is spawned that hosts the data. */
HOSTING_MODE_SQLITE, /*!< A sqlite database file is used. */
+ HOSTING_MODE_MYSQL_CENTRAL, /*!< The database is hosted on an external MySQL server. */
+ HOSTING_MODE_MYSQL_SELF, /*!< A new MySQL database process is spawned that hosts the data. */
HOSTING_MODE_DEFAULT = HOSTING_MODE_POSTGRES_SELF /*!- Arbitrary default. */
};
diff --git a/glom/libglom/filelist.am b/glom/libglom/filelist.am
index 7488026..d4feee5 100644
--- a/glom/libglom/filelist.am
+++ b/glom/libglom/filelist.am
@@ -182,6 +182,8 @@ libglom_sources = \
glom/libglom/python_embed/pygdavalue_conversions.h \
glom/libglom/connectionpool_backends/mysql.cc \
glom/libglom/connectionpool_backends/mysql.h \
+ glom/libglom/connectionpool_backends/mysql_central.cc \
+ glom/libglom/connectionpool_backends/mysql_central.h \
glom/libglom/connectionpool_backends/sqlite.cc \
glom/libglom/connectionpool_backends/sqlite.h \
glom/libglom/connectionpool_backends/postgres.cc \
diff --git a/tests/test_selfhosting_new_empty.cc b/tests/test_selfhosting_new_empty.cc
index 7c8c656..4f47086 100644
--- a/tests/test_selfhosting_new_empty.cc
+++ b/tests/test_selfhosting_new_empty.cc
@@ -71,6 +71,13 @@ int main()
return EXIT_FAILURE;
}
+ if(!test(Glom::Document::HOSTING_MODE_MYSQL_SELF))
+ {
+ std::cerr << "Failed with MySQL" << std::endl;
+ test_selfhosting_cleanup();
+ return EXIT_FAILURE;
+ }
+
Glom::libglom_deinit();
return EXIT_SUCCESS;
diff --git a/tests/test_selfhosting_utils.cc b/tests/test_selfhosting_utils.cc
index f40d338..b7fa45f 100644
--- a/tests/test_selfhosting_utils.cc
+++ b/tests/test_selfhosting_utils.cc
@@ -173,6 +173,7 @@ bool test_selfhost(Glom::Document& document, const Glib::ustring& user, const Gl
bool test_create_and_selfhost_new_empty(Glom::Document& document, Glom::Document::HostingMode hosting_mode, const std::string& subdirectory_path)
{
if( (hosting_mode != Glom::Document::HOSTING_MODE_POSTGRES_SELF) &&
+ (hosting_mode != Glom::Document::HOSTING_MODE_MYSQL_SELF) &&
(hosting_mode != Glom::Document::HOSTING_MODE_SQLITE) )
{
std::cerr << G_STRFUNC << ": This test function does not support the specified hosting_mode: " << hosting_mode << std::endl;
@@ -323,6 +324,7 @@ bool test_create_and_selfhost_from_test_example(const std::string& example_filen
bool test_create_and_selfhost_from_uri(const Glib::ustring& example_file_uri, Glom::Document& document, Glom::Document::HostingMode hosting_mode, const std::string& subdirectory_path)
{
if( (hosting_mode != Glom::Document::HOSTING_MODE_POSTGRES_SELF) &&
+ (hosting_mode != Glom::Document::HOSTING_MODE_MYSQL_SELF) &&
(hosting_mode != Glom::Document::HOSTING_MODE_SQLITE) )
{
std::cerr << G_STRFUNC << ": This test function does not support the specified hosting_mode: " << hosting_mode << std::endl;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]