[glom/mysql: 3/21] More MySQL
- From: Murray Cumming <murrayc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glom/mysql: 3/21] More MySQL
- Date: Fri, 11 Jan 2013 11:31:29 +0000 (UTC)
commit eb87f15e414baf268a5cc884d5b118fac140ac26
Author: Murray Cumming <murrayc murrayc com>
Date: Thu Jan 3 14:34:59 2013 +0100
More MySQL
glom/libglom/connectionpool_backends/mysql.cc | 21 +++--
glom/libglom/connectionpool_backends/mysql_self.cc | 102 +++++++++++++++++---
glom/libglom/connectionpool_backends/mysql_self.h | 2 +-
glom/libglom/connectionpool_backends/postgres.cc | 3 +-
glom/mode_design/users/dialog_users_list.cc | 2 +
5 files changed, 106 insertions(+), 24 deletions(-)
---
diff --git a/glom/libglom/connectionpool_backends/mysql.cc b/glom/libglom/connectionpool_backends/mysql.cc
index 724b824..a92b589 100644
--- a/glom/libglom/connectionpool_backends/mysql.cc
+++ b/glom/libglom/connectionpool_backends/mysql.cc
@@ -37,7 +37,7 @@
#include <iostream>
// Uncomment to see debug messages
-//#define GLOM_CONNECTION_DEBUG
+#define GLOM_CONNECTION_DEBUG
namespace
{
@@ -47,8 +47,16 @@ static Glib::ustring create_auth_string(const Glib::ustring& username, const Gli
if(username.empty() and password.empty())
return Glib::ustring();
else
- return "USERNAME=" + Glom::DbUtils::gda_cnc_string_encode(username) +
- ";PASSWORD=" + Glom::DbUtils::gda_cnc_string_encode(password);
+ {
+ Glib::ustring result = "USERNAME=" + Glom::DbUtils::gda_cnc_string_encode(username);
+
+ if(!password.empty()) //There is no password initially, at least with MySQL 5.5:
+ {
+ result +=";PASSWORD=" + Glom::DbUtils::gda_cnc_string_encode(password);
+ }
+
+ return result;
+ }
}
} //anonymous namespace
@@ -65,15 +73,14 @@ MySQL::MySQL()
{
}
+//TODO: Avoid copy/paste with Postgres::attempt_connect()
Glib::RefPtr<Gnome::Gda::Connection> MySQL::attempt_connect(const Glib::ustring& port, const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password, bool fake_connection)
{
- //We must specify _some_ database even when we just want to create a database.
- //This _might_ be different on some systems. I hope not. murrayc
- const Glib::ustring default_database = "template1";
+ const Glib::ustring default_database = "INFORMATION_SCHEMA";
//const Glib::ustring& actual_database = (!database.empty()) ? database : default_database;;
const Glib::ustring cnc_string_main = "HOST=" + DbUtils::gda_cnc_string_encode(m_host)
+ ";PORT=" + DbUtils::gda_cnc_string_encode(port);
- const Glib::ustring cnc_string = cnc_string_main + ";DB_NAME=" + DbUtils::gda_cnc_string_encode(database);
+ const Glib::ustring cnc_string = cnc_string_main +";DB_NAME=" + DbUtils::gda_cnc_string_encode(database);
Glib::RefPtr<Gnome::Gda::Connection> connection;
Glib::RefPtr<Gnome::Gda::DataModel> data_model;
diff --git a/glom/libglom/connectionpool_backends/mysql_self.cc b/glom/libglom/connectionpool_backends/mysql_self.cc
index 3d910b1..42079fe 100644
--- a/glom/libglom/connectionpool_backends/mysql_self.cc
+++ b/glom/libglom/connectionpool_backends/mysql_self.cc
@@ -180,19 +180,41 @@ Backend::InitErrors MySQLSelfHosted::initialize(const SlotProgress& slot_progres
+ " --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);
+ const bool result = Glom::Spawn::execute_command_line_and_wait(command_initdb, slot_progress);
if(!result)
{
std::cerr << "Error while attempting to create self-hosting MySQL database." << std::endl;
}
else
{
+ std::cout << "debug: command_initdb succeeded" << ", this=" << this << std::endl;
+
//This is used during the first start:
m_initial_password_to_set = password;
+ m_initial_username_to_set = initial_username;
//TODO: With MySQL 5.6, use the new --random-passwords option (see above)
m_temporary_password = "";
m_temporary_password_active = true;
+
+ //Startup (and shutdown) so we can set the initial username and password.
+ //TODO: This is inefficient, because the caller probably wants to start the server soon anyway,
+ //but that might be in a different instance of this backend,
+ //and we cannot take the risk of leaving the database with a default password.
+ if(startup(slot_progress, false) != STARTUPERROR_NONE)
+ {
+ std::cerr << "Error while attempting to create self-hosting MySQL database, while starting for the first time, to set the initial username and password." << std::endl;
+ return INITERROR_OTHER;
+ }
+ else
+ {
+ if(cleanup(slot_progress) != STARTUPERROR_NONE)
+ {
+ std::cerr << "Error while attempting to create self-hosting MySQL database, while shutting down, after setting the initial username and password." << std::endl;
+ return INITERROR_OTHER;
+ }
+ }
+
//Get the temporary random password,
//which will be used when first starting the server.
/*
@@ -229,8 +251,15 @@ float MySQLSelfHosted::get_mysqlql_utils_version_as_number(const SlotProgress& /
return 0; //TODO
}
+static Glib::ustring build_query_change_username(const Glib::ustring& old_username, const Glib::ustring& new_username)
+{
+ return "RENAME USER " + DbUtils::escape_sql_id(old_username) + " TO " + DbUtils::escape_sql_id(new_username);
+}
+
Backend::StartupErrors MySQLSelfHosted::startup(const SlotProgress& slot_progress, bool network_shared)
{
+ std::cout << G_STRFUNC << std::cout << " DEBUG0: m_temporary_password_active=" << m_temporary_password_active << std::endl;
+
m_network_shared = network_shared;
// Don't risk random crashes, although this really shouldn't be called
@@ -299,15 +328,16 @@ Backend::StartupErrors MySQLSelfHosted::startup(const SlotProgress& slot_progres
+ " --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;
+ //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;
+ //std::cout << G_STRFUNC << ": debug: command_check_mysql_has_started=" << command_check_mysql_has_started << std::endl;
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);
+ std::cout << G_STRFUNC << std::cout << " DEBUG: started" << std::endl;
if(!result)
{
@@ -319,14 +349,17 @@ Backend::StartupErrors MySQLSelfHosted::startup(const SlotProgress& slot_progres
m_port = available_port; //Remember it for later.
- //If necessary, set the initial password:
+ //If necessary, set the initial root password and rename the root user:
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;
+ //Set the root password:
+ const std::string command_initdb_set_initial_password = get_mysqladmin_command(m_temporary_password)
+ + " password " + Glib::shell_quote(m_initial_password_to_set);
+ std::cout << "debug: command_initdb_set_initial_password=" << command_initdb_set_initial_password << std::endl;
+
+ const bool result = Glom::Spawn::execute_command_line_and_wait(command_initdb_set_initial_password, slot_progress);
- const bool result = Glom::Spawn::execute_command_line_and_wait(command_initdb_initial_password, slot_progress);
+ std::cout << G_STRFUNC << std::cout << " DEBUG4" << std::endl;
if(!result)
{
@@ -337,12 +370,44 @@ Backend::StartupErrors MySQLSelfHosted::startup(const SlotProgress& slot_progres
m_temporary_password_active = false;
m_temporary_password.clear();
- //TODO_MySQL: " -U " + initial_username
+ std::cout << G_STRFUNC << std::cout << " DEBUG5" << std::endl;
+
+
+ //Rename the root user,
+ //so we can connnect as the expected username:
+ //We connect to the INFORMATION_SCHEMA database, because libgda needs us to specify some database.
+ Glib::RefPtr<Gnome::Gda::Connection> gda_connection = connect("INFORMATION_SCHEMA", "root", m_initial_password_to_set);
+ if(!gda_connection)
+ {
+ std::cerr << G_STRFUNC << "Error while attempting to start self-hosting MySQL database, when setting the initial username: connection failed." << std::endl;
+ return STARTUPERROR_FAILED_UNKNOWN_REASON;
+ }
+
+ std::cout << G_STRFUNC << std::cout << " DEBUG6" << std::endl;
+
+ const std::string query = build_query_change_username("root", m_initial_username_to_set);
+ try
+ {
+ const bool test = gda_connection->statement_execute_non_select(query);
+ if(!test)
+ {
+ std::cerr << G_STRFUNC << "Error while attempting to start self-hosting MySQL database, when setting the initial username: UPDATE failed." << std::endl;
+ return STARTUPERROR_FAILED_UNKNOWN_REASON;
+ }
+ }
+ catch(const Glib::Error& ex)
+ {
+ std::cerr << G_STRFUNC << "Error while attempting to start self-hosting MySQL database, when setting the initial username: UPDATE failed: " << ex.what() << std::endl;
+ return STARTUPERROR_FAILED_UNKNOWN_REASON;
+ }
}
+ m_initial_username_to_set.clear();
+
return STARTUPERROR_NONE;
}
+//TODO: Avoid copy/paste with PostgresSelfHosted:
void MySQLSelfHosted::show_active_connections()
{
Glib::RefPtr<Gnome::Gda::SqlBuilder> builder =
@@ -385,11 +450,17 @@ std::string MySQLSelfHosted::get_mysqladmin_command(const Glib::ustring& passwor
{
const std::string port_as_text = Glib::Ascii::dtostr(m_port);
- return get_path_to_mysql_executable("mysqladmin")
+ std::string command = get_path_to_mysql_executable("mysqladmin")
+ " --no-defaults"
+ " --port=" + port_as_text
- + " --user=root"
- + " --password=" + Glib::shell_quote(password);
+ + " --protocol=tcp" //Otherwise we cannot connect as root. TODO: However, maybe we could use --skip-networking if network sharing is not enabled.
+ + " --user=root";
+
+ //--password='' is not always interpreted the same as specifying no --password.
+ if(!password.empty())
+ command += " --password=" + Glib::shell_quote(password);
+
+ return command;
}
bool MySQLSelfHosted::cleanup(const SlotProgress& slot_progress)
@@ -473,13 +544,14 @@ Glib::RefPtr<Gnome::Gda::Connection> MySQLSelfHosted::connect(const Glib::ustrin
Glib::RefPtr<Gnome::Gda::Connection> result;
bool keep_trying = true;
- guint count_retries = 0;
- const guint MAX_RETRIES_KNOWN_PASSWORD = 30; /* seconds */
- const guint MAX_RETRIES_EVER = 60; /* seconds */
+ guint count_retries = 1;
+ const guint MAX_RETRIES_KNOWN_PASSWORD = 20;
+ const guint MAX_RETRIES_EVER = 20;
while(keep_trying)
{
try
{
+ std::cout << "DEBUG: Calling attempt_connect(): username=" << username << ", password=" << password << std::endl;
result = attempt_connect(port_as_string(m_port), database, username, password, fake_connection);
}
catch(const ExceptionConnection& ex)
diff --git a/glom/libglom/connectionpool_backends/mysql_self.h b/glom/libglom/connectionpool_backends/mysql_self.h
index 4216154..ac46f60 100644
--- a/glom/libglom/connectionpool_backends/mysql_self.h
+++ b/glom/libglom/connectionpool_backends/mysql_self.h
@@ -90,7 +90,7 @@ private:
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_initial_password_to_set, m_initial_username_to_set;
Glib::ustring m_temporary_password;
};
diff --git a/glom/libglom/connectionpool_backends/postgres.cc b/glom/libglom/connectionpool_backends/postgres.cc
index 3fb50aa..519ecff 100644
--- a/glom/libglom/connectionpool_backends/postgres.cc
+++ b/glom/libglom/connectionpool_backends/postgres.cc
@@ -65,6 +65,7 @@ Postgres::Postgres()
{
}
+//TODO: We need to specify TCP for the connection: https://bugzilla.gnome.org/show_bug.cgi?id=691069
Glib::RefPtr<Gnome::Gda::Connection> Postgres::attempt_connect(const Glib::ustring& port, const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password, bool fake_connection)
{
//We must specify _some_ database even when we just want to create a database.
@@ -100,7 +101,7 @@ Glib::RefPtr<Gnome::Gda::Connection> Postgres::attempt_connect(const Glib::ustri
cnc_string, auth_string,
Gnome::Gda::CONNECTION_OPTIONS_SQL_IDENTIFIERS_CASE_SENSITIVE);
- connection->statement_execute_non_select("SET DATESTYLE = 'ISO'");
+ //connection->statement_execute_non_select("SET DATESTYLE = 'ISO'");
data_model = connection->statement_execute_select("SELECT version()");
}
}
diff --git a/glom/mode_design/users/dialog_users_list.cc b/glom/mode_design/users/dialog_users_list.cc
index 1eee143..8dada10 100644
--- a/glom/mode_design/users/dialog_users_list.cc
+++ b/glom/mode_design/users/dialog_users_list.cc
@@ -332,6 +332,8 @@ void Dialog_UsersList::on_button_user_edit()
if(!user.empty() && !password.empty())
{
+ //TODO: Can this change the username too?
+ //Note: If using MySQL, we need MySQL 5.6.7 for ALTER USER:
const Glib::ustring strQuery = "ALTER USER " + DbUtils::escape_sql_id(user) + " PASSWORD '" + password + "'" ; //TODO: Escape the password.
const bool test = DbUtils::query_execute_string(strQuery);
if(!test)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]