diff --git a/ChangeLog b/ChangeLog index 4ccdcdb4..49bae4ef 100644 --- a/ChangeLog +++ b/ChangeLog @@ -21622,3 +21622,6 @@ 2021-04-26 Fred Gleason * Fixed regressions that caused SQL errors when performing database creation in rddbmgr(8). +2021-04-26 Fred Gleason + * Added a 'Collations=' directive to the [mySQL] section of + rd.conf(5). diff --git a/conf/rd.conf-sample b/conf/rd.conf-sample index 5049a551..a030bb4d 100644 --- a/conf/rd.conf-sample +++ b/conf/rd.conf-sample @@ -61,6 +61,18 @@ HeartbeatInterval=360 ; created by Rivendell. ;Engine=MyISAM +; The following setting controls the collation used for new DB tables +; created by Rivendell. Collations control how text is sorted and matched +; by the database engine. Versions of MySQL earlier than v8.0 should use +; 'utf8mb4_general_ci', while those using v8.0 or later may find it +; beneficial to switch to 'utf8mb4_0900_ai_ci', which provides support +; for more up-to-date Unicode standards. For more information, see: +; +; https://www.monolune.com/what-is-the-utf8mb4_0900_ai_ci-collation/ +; +Collation=utf8mb4_general_ci +;Collation=utf8mb4_0900_ai_ci + [AudioStore] MountSource= MountType= diff --git a/docs/manpages/rd.conf.xml b/docs/manpages/rd.conf.xml index fc31b557..eb654993 100644 --- a/docs/manpages/rd.conf.xml +++ b/docs/manpages/rd.conf.xml @@ -1,5 +1,5 @@ - + @@ -299,6 +299,33 @@ + + + Collation = type + + + + The collation type that will be used when creating new + tables in the database. Consult the database server + documentation for the list of supported types. + + + + Collations control how text is sorted and matched + by the database engine. Versions of MySQL earlier than v8.0 + should use utf8mb4_general_ci, while + those using v8.0 or later may find it beneficial to switch to + utf8mb4_0900_ai_ci, which provides + support for more up-to-date Unicode standards. For more + information, see: + https://www.monolune.com/what-is-the-utf8mb4_0900_ai_ci-collation/ + + + Default + value is utf8mb4_general_ci. + + + diff --git a/lib/rdconfig.cpp b/lib/rdconfig.cpp index 10578958..14e8a688 100644 --- a/lib/rdconfig.cpp +++ b/lib/rdconfig.cpp @@ -217,6 +217,12 @@ QString RDConfig::mysqlEngine() const } +QString RDConfig::mysqlCollation() const +{ + return conf_mysql_collation; +} + + QString RDConfig::createTablePostfix() const { return conf_create_table_postfix; @@ -585,6 +591,8 @@ bool RDConfig::load() DEFAULT_MYSQL_HEARTBEAT_INTERVAL); conf_mysql_engine= profile->stringValue("mySQL","Engine",DEFAULT_MYSQL_ENGINE); + conf_mysql_collation= + profile->stringValue("mySQL","Collation",DEFAULT_MYSQL_COLLATION); conf_create_table_postfix= RDConfig::createTablePostfix(conf_mysql_engine); @@ -690,6 +698,7 @@ void RDConfig::clear() conf_mysql_driver=""; conf_mysql_heartbeat_interval=DEFAULT_MYSQL_HEARTBEAT_INTERVAL; conf_mysql_engine=DEFAULT_MYSQL_ENGINE; + conf_mysql_collation=DEFAULT_MYSQL_COLLATION; conf_create_table_postfix=""; conf_log_xload_debug_data=false; conf_provisioning_create_host=false; diff --git a/lib/rdconfig.h b/lib/rdconfig.h index d5a2361b..5de36d8b 100644 --- a/lib/rdconfig.h +++ b/lib/rdconfig.h @@ -62,6 +62,7 @@ class RDConfig QString mysqlDriver() const; int mysqlHeartbeatInterval() const; QString mysqlEngine() const; + QString mysqlCollation() const; QString createTablePostfix() const; bool logXloadDebugData() const; bool provisioningCreateHost() const; @@ -133,6 +134,7 @@ class RDConfig QString conf_mysql_password; QString conf_mysql_driver; QString conf_mysql_engine; + QString conf_mysql_collation; QString conf_create_table_postfix; int conf_mysql_heartbeat_interval; bool conf_provisioning_create_host; diff --git a/utils/rddbmgr/check.cpp b/utils/rddbmgr/check.cpp index 5593707b..b935b283 100644 --- a/utils/rddbmgr/check.cpp +++ b/utils/rddbmgr/check.cpp @@ -179,16 +179,17 @@ void MainObject::CheckTableAttributes() RDSqlQuery::apply(sql); } } - if(q->value(2).toString().toLower()!="utf8mb4_general_ci") { - printf(" Table \"%s\" uses charset/collation %s/%s, should be utf8mb4/utf8mb4_general_ci. Fix? (y/N) ", + if(q->value(2).toString().toLower()!=db_config->mysqlCollation()) { + printf(" Table \"%s\" uses charset/collation %s/%s, should be utf8mb4/%s. Fix? (y/N) ", q->value(0).toString().toUtf8().constData(), charset.toUtf8().constData(), - q->value(2).toString().toUtf8().constData()); + q->value(2).toString().toUtf8().constData(), + db_config->mysqlCollation().toUtf8().constData()); fflush(NULL); if(UserResponse()) { RewriteTable(q->value(0).toString(), charset,q->value(2).toString(), - "utf8mb4","utf8mb4_general_ci"); + "utf8mb4",db_config->mysqlCollation()); } } } @@ -206,14 +207,15 @@ void MainObject::CheckTableAttributes() while(q->next()) { if(q->value(0).toString()==db_mysql_database) { if((q->value(1).toString().toLower()!="utf8mb4")|| - (q->value(2).toString().toLower()!="utf8mb4_general_ci")) { - printf(" Database uses default charset/collation %s/%s, should be utf8mb4/utf8mb4_general_ci. Fix? (y/N) ", + (q->value(2).toString().toLower()!=db_config->mysqlCollation())) { + printf(" Database uses default charset/collation %s/%s, should be utf8mb4/%s. Fix? (y/N) ", q->value(1).toString().toUtf8().constData(), - q->value(2).toString().toUtf8().constData()); + q->value(2).toString().toUtf8().constData(), + db_config->mysqlCollation()); fflush(NULL); if(UserResponse()) { sql=QString("alter database `")+db_mysql_database+"` "+ - "character set utf8mb4 collate utf8mb4_general_ci"; + "character set utf8mb4 collate "+db_config->mysqlCollation(); RDSqlQuery::apply(sql); } } @@ -229,6 +231,14 @@ void MainObject::RewriteTable(const QString &tblname, const QString &new_charset, const QString &new_collation) { + /* + printf("RewriteTable('%s','%s','%s','%s','%s')\n", + tblname.toUtf8().constData(), + old_charset.toUtf8().constData(), + old_collation.toUtf8().constData(), + new_charset.toUtf8().constData(), + new_collation.toUtf8().constData()); + */ QString err_msg; QProcess *proc=NULL; QStringList args; diff --git a/utils/rddbmgr/revertschema.cpp b/utils/rddbmgr/revertschema.cpp index f09c8682..2f26b103 100644 --- a/utils/rddbmgr/revertschema.cpp +++ b/utils/rddbmgr/revertschema.cpp @@ -284,7 +284,7 @@ bool MainObject::RevertSchema(int cur_schema,int set_schema,QString *err_msg) "`ENCODER_ID` int not null,"+ "`CHANNELS` int not null,"+ "index `ENCODER_ID_IDX` (`ENCODER_ID`))"+ - " charset utf8mb4 collate utf8mb4_general_ci"+ + " charset utf8mb4 collate "+db_config->mysqlCollation()+ db_table_create_postfix; if(!RDSqlQuery::apply(sql,err_msg)) { return false; @@ -295,7 +295,7 @@ bool MainObject::RevertSchema(int cur_schema,int set_schema,QString *err_msg) "`ENCODER_ID` int not null,"+ "`BITRATES` int not null,"+ "index `ENCODER_ID_IDX` (`ENCODER_ID`))"+ - " charset utf8mb4 collate utf8mb4_general_ci"+ + " charset utf8mb4 collate "+db_config->mysqlCollation()+ db_table_create_postfix; if(!RDSqlQuery::apply(sql,err_msg)) { return false; @@ -306,7 +306,7 @@ bool MainObject::RevertSchema(int cur_schema,int set_schema,QString *err_msg) "`ENCODER_ID` int not null,"+ "`SAMPLERATES` int not null,"+ "index `ENCODER_ID_IDX` (`ENCODER_ID`))"+ - " charset utf8mb4 collate utf8mb4_general_ci"+ + " charset utf8mb4 collate "+db_config->mysqlCollation()+ db_table_create_postfix; if(!RDSqlQuery::apply(sql,err_msg)) { return false; @@ -319,7 +319,7 @@ bool MainObject::RevertSchema(int cur_schema,int set_schema,QString *err_msg) "`COMMAND_LINE` char(255),"+ "`DEFAULT_EXTENSION` char(16),"+ "index `NAME_IDX` (`NAME`,`STATION_NAME`))"+ - " charset utf8mb4 collate utf8mb4_general_ci"+ + " charset utf8mb4 collate "+db_config->mysqlCollation()+ db_table_create_postfix; if(!RDSqlQuery::apply(sql,err_msg)) { return false; @@ -397,7 +397,7 @@ bool MainObject::RevertSchema(int cur_schema,int set_schema,QString *err_msg) "`ACCESS_DATE` date not null,"+ "`ACCESS_COUNT` int unsigned not null default 0,"+ "unique index `KEY_NAME_CAST_ID_DATE_IDX` (`FEED_KEY_NAME`,`CAST_ID`,`ACCESS_DATE`))"+ - " charset utf8mb4 collate utf8mb4_general_ci"+ + " charset utf8mb4 collate "+db_config->mysqlCollation()+ db_table_create_postfix; if(!RDSqlQuery::apply(sql,err_msg)) { return false; @@ -468,7 +468,7 @@ bool MainObject::RevertSchema(int cur_schema,int set_schema,QString *err_msg) "`CHANNEL_XML` text,"+ "`ITEM_XML` text,"+ "index `NAME_IDX` (`NAME`)) "+ - " charset utf8mb4 collate utf8mb4_general_ci"+ + " charset utf8mb4 collate "+db_config->mysqlCollation()+ db_table_create_postfix; if(!RDSqlQuery::apply(sql,err_msg)) { return false; @@ -913,7 +913,7 @@ bool MainObject::RevertSchema(int cur_schema,int set_schema,QString *err_msg) // Maintainer's Note: // // All tables created above this point should use a character set - // of 'utf8mb4' and a collation of 'utf8mb4_general_ci'. + // of 'utf8mb4' and the collation returned by 'RDConfig::mysqlCollation()'. // // diff --git a/utils/rddbmgr/updateschema.cpp b/utils/rddbmgr/updateschema.cpp index a349d101..00c69920 100644 --- a/utils/rddbmgr/updateschema.cpp +++ b/utils/rddbmgr/updateschema.cpp @@ -9844,7 +9844,7 @@ bool MainObject::UpdateSchema(int cur_schema,int set_schema,QString *err_msg) return false; } - ModifyCharset("utf8mb4","utf8mb4_general_ci"); + ModifyCharset("utf8mb4",db_config->mysqlCollation()); WriteSchemaVersion(++cur_schema); } @@ -9853,7 +9853,7 @@ bool MainObject::UpdateSchema(int cur_schema,int set_schema,QString *err_msg) // Maintainer's Note: // // All tables created below this point should use a character set - // of 'utf8mb4' and a collation of 'utf8mb4_general_ci'. + // of 'utf8mb4' and the collation returned by 'RDConfig::mysqlCollation()'. // if((cur_schema<298)&&(set_schema>cur_schema)) { @@ -9878,7 +9878,7 @@ bool MainObject::UpdateSchema(int cur_schema,int set_schema,QString *err_msg) "`CART_NUMBER` int unsigned not null default 0,"+ "`SCHED_CODE` varchar(11) not null,"+ "index `SCHED_CODE_IDX` (`CART_NUMBER`,`SCHED_CODE`))"+ - " charset utf8mb4 collate utf8mb4_general_ci"+ + " charset utf8mb4 collate "+db_config->mysqlCollation()+ db_table_create_postfix; if(!RDSqlQuery::apply(sql,err_msg)) { return false; @@ -9947,7 +9947,7 @@ bool MainObject::UpdateSchema(int cur_schema,int set_schema,QString *err_msg) "`DESCRIPTION` varchar(191) default '[new]',"+ "`CONFIG` text not null,"+ "index `STATION_NAME_IDX` (`STATION_NAME`))"+ - " charset utf8mb4 collate utf8mb4_general_ci"+ + " charset utf8mb4 collate "+db_config->mysqlCollation()+ db_table_create_postfix; if(!RDSqlQuery::apply(sql,err_msg)) { return false; @@ -10020,7 +10020,7 @@ bool MainObject::UpdateSchema(int cur_schema,int set_schema,QString *err_msg) "`STACK_LINES_ID` int unsigned,"+ "`SCHED_CODE` varchar(10),"+ "index `SCHED_CODE_IDX` (`SCHED_CODE`))"+ - " charset utf8mb4 collate utf8mb4_general_ci"+ + " charset utf8mb4 collate "+db_config->mysqlCollation()+ db_table_create_postfix; if(!RDSqlQuery::apply(sql,err_msg)) { return false; @@ -10078,7 +10078,7 @@ bool MainObject::UpdateSchema(int cur_schema,int set_schema,QString *err_msg) "`RD_NAME` varchar(255),"+ "`NEXUS_NAME` varchar(255),"+ "`NEXUS_ID` int(11))"+ - " charset utf8mb4 collate utf8mb4_general_ci"+ + " charset utf8mb4 collate "+db_config->mysqlCollation()+ db_table_create_postfix; if(!RDSqlQuery::apply(sql,err_msg)) { return false; @@ -10089,7 +10089,7 @@ bool MainObject::UpdateSchema(int cur_schema,int set_schema,QString *err_msg) "`NOTIFICATION` varchar(255),"+ "`ERROR` varchar(255),"+ "`CREATED` timestamp default current_timestamp)"+ - " charset utf8mb4 collate utf8mb4_general_ci"+ + " charset utf8mb4 collate "+db_config->mysqlCollation()+ db_table_create_postfix; if(!RDSqlQuery::apply(sql,err_msg)) { return false; @@ -10100,7 +10100,7 @@ bool MainObject::UpdateSchema(int cur_schema,int set_schema,QString *err_msg) "`ADDRESS` varchar(50) NOT NULL,"+ "`PORT` int(11) NOT NULL DEFAULT 8080,"+ "`STATION_NAME` varchar(64))"+ - " charset utf8mb4 collate utf8mb4_general_ci"+ + " charset utf8mb4 collate "+db_config->mysqlCollation()+ db_table_create_postfix; if(!RDSqlQuery::apply(sql,err_msg)) { return false; @@ -10113,7 +10113,7 @@ bool MainObject::UpdateSchema(int cur_schema,int set_schema,QString *err_msg) "`RD_SERVICE` varchar(10) not null,"+ "`RD_GROUP_NAME` varchar(10) not null,"+ "`RD_SCHED_CODE` varchar(11) not null)"+ - " charset utf8mb4 collate utf8mb4_general_ci"+ + " charset utf8mb4 collate "+db_config->mysqlCollation()+ db_table_create_postfix; if(!RDSqlQuery::apply(sql,err_msg)) { return false; @@ -10267,7 +10267,7 @@ bool MainObject::UpdateSchema(int cur_schema,int set_schema,QString *err_msg) "index `MEMBER_FEED_ID_IDX` (`MEMBER_FEED_ID`),"+ "index `KEY_NAME_IDX` (`KEY_NAME`),"+ "index `MEMBER_KEY_NAME_IDX` (`MEMBER_KEY_NAME`)) "+ - " charset utf8mb4 collate utf8mb4_general_ci"+ + " charset utf8mb4 collate "+db_config->mysqlCollation()+ db_table_create_postfix; if(!RDSqlQuery::apply(sql,err_msg)) { return false; @@ -10319,7 +10319,7 @@ bool MainObject::UpdateSchema(int cur_schema,int set_schema,QString *err_msg) "`CHANNEL_XML` text,"+ "`ITEM_XML` text,"+ "index `NAME_IDX` (`NAME`)) "+ - " charset utf8mb4 collate utf8mb4_general_ci"+ + " charset utf8mb4 collate "+db_config->mysqlCollation()+ db_table_create_postfix; if(!RDSqlQuery::apply(sql,err_msg)) { return false; @@ -10347,7 +10347,7 @@ bool MainObject::UpdateSchema(int cur_schema,int set_schema,QString *err_msg) "`DATA` mediumblob not null,"+ "index `FEED_ID_IDX` (`FEED_ID`),"+ "index `FEED_KEY_NAME_IDX` (`FEED_KEY_NAME`)) "+ - " charset utf8mb4 collate utf8mb4_general_ci"+ + " charset utf8mb4 collate "+db_config->mysqlCollation()+ db_table_create_postfix; if(!RDSqlQuery::apply(sql,err_msg)) { return false; @@ -10704,7 +10704,7 @@ bool MainObject::UpdateSchema(int cur_schema,int set_schema,QString *err_msg) "`NORMALIZATION_LEVEL` int not null,"+ "`AUTOTRIM_LEVEL` int not null,"+ "unique index `NAME_IDX` (`NAME`))"+ - " charset utf8mb4 collate utf8mb4_general_ci"+ + " charset utf8mb4 collate "+db_config->mysqlCollation()+ db_table_create_postfix; if(!RDSqlQuery::apply(sql,err_msg)) { return false;