1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-02-26 09:57:23 +03:00

B #3946: Check database and table encodings. This may break dump -> mysql upgrade (change default encoding) -> restore

This commit is contained in:
Ruben S. Montero 2019-11-19 23:20:12 +01:00
parent 43f159201b
commit 2c3f907d6c
No known key found for this signature in database
GPG Key ID: A0CEA6FA880A1D87
2 changed files with 74 additions and 41 deletions

View File

@ -288,14 +288,28 @@ class BackEndMySQL < OneDBBacKEnd
def encoding
@encoding = ''
db_enc = ''
table_enc = ''
connect_db
@db.fetch('select default_character_set_name FROM information_schema.SCHEMATA'\
" WHERE schema_name = \"#{@db_name}\"") do |row|
@encoding = row[:default_character_set_name]
db_enc = row[:default_character_set_name]
end
@encoding
@db.fetch('select CCSA.character_set_name FROM information_schema.`TABLES`'\
' T, information_schema.`COLLATION_CHARACTER_SET_APPLICABILITY` CCSA '\
'WHERE CCSA.collation_name = T.table_collation AND T.table_schema = '\
"\"#{@db_name}\" AND T.table_name = \"system_attributes\"") do |row|
table_enc = row[:character_set_name]
end
if db_enc != table_enc
raise "Table and database charset (#{db_enc}, #{table_enc}) differs"
end
@encoding = table_enc
end
def restore(bck_file, force=nil, federated=false)

View File

@ -25,6 +25,44 @@
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
static std::string get_encoding(MYSQL * c, const std::string& sql,
std::string& error)
{
std::string encoding;
if ( mysql_query(c, sql.c_str()) != 0 )
{
error = "Could not read database encoding.";
return "";
}
MYSQL_RES * result = mysql_store_result(c);
if (result == nullptr)
{
error = "Could not read database encoding: ";
error.append(mysql_error(c));
return "";
}
MYSQL_ROW row = mysql_fetch_row(result);
if ( row == nullptr )
{
error = "Could not read databse encoding";
return "";
}
encoding = ((char **) row)[0];
mysql_free_result(result);
return encoding;
}
/* -------------------------------------------------------------------------- */
int MySqlDB::db_encoding(std::string& error)
{
MYSQL * connection = mysql_init(nullptr);
@ -46,39 +84,34 @@ int MySqlDB::db_encoding(std::string& error)
return -1;
}
//Get encodings for database and tables
if (encoding.empty())
{
//Set encoding for the database clients
std::string encoding_sql = "SELECT default_character_set_name FROM "
std::string db_sql = "SELECT default_character_set_name FROM "
"information_schema.SCHEMATA WHERE schema_name = \"" + database + "\"";
if ( mysql_query(connection, encoding_sql.c_str()) != 0 )
std::string db_enc = get_encoding(connection, db_sql, error);
if ( db_enc.empty() )
{
error = "Could not read database encoding.";
return -1;
}
MYSQL_RES * result = mysql_store_result(connection);
std::string table_sql = "SELECT CCSA.character_set_name FROM "
"information_schema.`TABLES` T, information_schema.`COLLATION_CHARACTER_SET_APPLICABILITY`"
" CCSA WHERE CCSA.collation_name = T.table_collation AND T.table_schema = "
"\"" + database + "\" AND T.table_name = \"system_attributes\"";
if (result == nullptr)
std::string table_enc = get_encoding(connection, table_sql, error);
if ( !table_enc.empty() && table_enc != db_enc)
{
error = "Could not read database encoding: ";
error.append(mysql_error(connection));
error = "Database and table charsets (" + db_enc + ", " + table_enc
+ ") differs";
return -1;
}
MYSQL_ROW row = mysql_fetch_row(result);
if ( row == nullptr )
{
error = "Could not read databse encoding";
return -1;
}
encoding = ((char **) row)[0];
mysql_free_result(result);
encoding = db_enc;
}
mysql_close(connection);
@ -89,30 +122,16 @@ int MySqlDB::db_encoding(std::string& error)
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
MySqlDB::MySqlDB(
const string& _server,
int _port,
const string& _user,
const string& _password,
const string& _database,
const string& _encoding,
int _max_connections)
MySqlDB::MySqlDB(const string& s, int p, const string& u, const string& _p,
const string& d, const string& e, int m):max_connections(m), server(s),
port(p), user(u), password(_p), database(d), encoding(e)
{
vector<MYSQL *> connections(_max_connections);
vector<MYSQL *> connections(max_connections);
MYSQL * rc;
ostringstream oss;
std::string error;
server = _server;
port = _port;
user = _user;
password = _password;
database = _database;
encoding = _encoding;
max_connections = _max_connections;
// Initialize the MySQL library
mysql_library_init(0, NULL, NULL);