Wietse Venema via Postfix-users:
> > My conclusion to hard-solve this issue on my system is transform all 
> > tables to utf8mb4.
> > 
> > But:

> > - I don't see any option to change default charset on mysql_table 
> > connector, maybe should be interesting add this option on configuration 
> > file.
> 
> Is there such an API?

Based on documentation, perhaps mysql_set_character_set() can do that. 
https://dev.mysql.com/doc/c-api/8.0/en/mysql-set-character-set.html

Attached is patch 20230417-mysql-charset-patch.txt that adds a
"charset" parameter to the Postfix MySQL configuration file.  

I don't have a MySQL testbed; someone else would have to test this,
or this would have to wait until I have time to set up MySQL.

> > - mix collation error should raise 1 error, but next queries should be 
> > work ok, this could be considered and issue right?.
> 
> For the Postfix MySQL client the expected result of a query is:
> 
> - found,
> 
> - not found,
> 
> - error.
> 
> The client does not distinguish between errors, and all errors have
> the same result (skip this connection for 60s). That code is almost
> 20 years old, so I wonder if you are doing something unusal that
> other people aren't doing.
> 
> Based on https://dev.mysql.com/doc/c-api/8.0/en/mysql-next-result.html
> I suppose that the client could distinguish between
> errors that indicate a connection error and other errors. But that
> would be a major code change.

It is possible to distinguish between errors without having tp
restructure code.

Attached is patch 20230417-mysql-retry-patch.txt that more selectively
backs off from a server connection. 

Again if someone else can test this, great, otherwise this will
have to wait.

        Wietse
20230417

        Cleanup: in the MySQL client, temporarily stay away from a
        server only if the last error was caused by connection-level
        failure. File: global/dict_mysql.c.

diff '--exclude=man' '--exclude=html' '--exclude=README_FILES' 
'--exclude=INSTALL' '--exclude=.indent.pro' -r -ur 
/var/tmp/postfix-3.9-20230416/src/global/dict_mysql.c ./src/global/dict_mysql.c
--- /var/tmp/postfix-3.9-20230416/src/global/dict_mysql.c       2023-04-16 
16:44:39.000000000 -0400
+++ ./src/global/dict_mysql.c   2023-04-17 11:07:47.000000000 -0400
@@ -108,6 +108,7 @@
 /* Application-specific. */
 
 #include "dict_mysql.h"
+#include "mysql/errmsg.h"
 
 /* MySQL 8.x API change */
 
@@ -546,7 +547,14 @@
         * See what we got.
         */
        if (query_error) {
-           plmysql_down_host(host);
+           switch (mysql_errno(host->db)) {
+           case CR_COMMANDS_OUT_OF_SYNC:
+           case CR_SERVER_GONE_ERROR:
+           case CR_SERVER_LOST:
+               plmysql_down_host(host);
+           default:
+               break;
+           }
            if (errno == 0)
                errno = ENOTSUP;
            if (first_result) {
diff '--exclude=man' '--exclude=html' '--exclude=README_FILES' 
'--exclude=INSTALL' '--exclude=.indent.pro' -r -ur 
/var/tmp/postfix-3.9-20230416/HISTORY ./HISTORY
--- /var/tmp/postfix-3.9-20230416/HISTORY       2023-04-16 17:09:29.000000000 
-0400
+++ ./HISTORY   2023-04-17 11:01:00.531589777 -0400
@@ -27055,3 +27055,9 @@
        Cleanup: in source-code comments, replaced redundant (and
        sometimes incomplete) lookup table configuration info with
        a reference to the corresponding *_table(5) manpage.
+
+20230417
+
+       Cleanup: in the MySQL client, make the default characterset
+       (and collation) configurable (the MySQL defaults are latin1
+       and latin1_swedish_ci). File: global/dict_mysql.c.
diff '--exclude=man' '--exclude=html' '--exclude=README_FILES' 
'--exclude=INSTALL' '--exclude=.indent.pro' -r -ur 
/var/tmp/postfix-3.9-20230416/proto/mysql_table ./proto/mysql_table
--- /var/tmp/postfix-3.9-20230416/proto/mysql_table     2022-12-27 
18:01:00.000000000 -0500
+++ ./proto/mysql_table 2023-04-17 11:24:16.000000000 -0400
@@ -79,6 +79,11 @@
 # .nf
 #          dbname = customer_database
 # .fi
+# .IP "\fBcharset\fR (empty for backwards compatibility)"
+#      The default client character set (and implicitly, the
+#      collation order). According to MySQL documentation the
+#      built-in default is "latin1"; for SMTP, "utf8" would be
+#      more appropriate.
 # .IP "\fBquery\fR"
 #      The SQL query template used to search the database, where \fB%s\fR
 #      is a substitute for the address Postfix is trying to resolve,
diff '--exclude=man' '--exclude=html' '--exclude=README_FILES' 
'--exclude=INSTALL' '--exclude=.indent.pro' -r -ur 
/var/tmp/postfix-3.9-20230416/src/global/dict_mysql.c ./src/global/dict_mysql.c
--- /var/tmp/postfix-3.9-20230416/src/global/dict_mysql.c       2023-04-16 
16:44:39.000000000 -0400
+++ ./src/global/dict_mysql.c   2023-04-17 11:09:35.000000000 -0400
@@ -147,6 +147,7 @@
     char   *username;
     char   *password;
     char   *dbname;
+    char   *charset;
     ARGV   *hosts;
     PLMYSQL *pldb;
 #if defined(MYSQL_VERSION_ID) && MYSQL_VERSION_ID >= 40000
@@ -602,6 +603,13 @@
                           host->port,
                           (host->type == TYPEUNIX ? host->name : 0),
                           CLIENT_MULTI_RESULTS)) {
+       if (*dict_mysql->charset != 0
+           && mysql_set_character_set(host->db, dict_mysql->charset) != 0) {
+           msg_warn("dict_mysql: mysql_set_character_set '%s' failed: %s",
+                    dict_mysql->charset, mysql_error(host->db));
+           plmysql_down_host(host);
+           return;
+       }
        if (msg_verbose)
            msg_info("dict_mysql: successful connection to host %s",
                     host->hostname);
@@ -646,6 +654,7 @@
     dict_mysql->username = cfg_get_str(p, "user", "", 0, 0);
     dict_mysql->password = cfg_get_str(p, "password", "", 0, 0);
     dict_mysql->dbname = cfg_get_str(p, "dbname", "", 1, 0);
+    dict_mysql->charset = cfg_get_str(p, "charset", "", 1, 0);
     dict_mysql->result_format = cfg_get_str(p, "result_format", "%s", 1, 0);
     dict_mysql->option_file = cfg_get_str(p, "option_file", NULL, 0, 0);
     dict_mysql->option_group = cfg_get_str(p, "option_group", "client", 0, 0);
@@ -826,6 +835,7 @@
     myfree(dict_mysql->username);
     myfree(dict_mysql->password);
     myfree(dict_mysql->dbname);
+    myfree(dict_mysql->charset);
     myfree(dict_mysql->query);
     myfree(dict_mysql->result_format);
     if (dict_mysql->option_file)
_______________________________________________
Postfix-users mailing list -- postfix-users@postfix.org
To unsubscribe send an email to postfix-users-le...@postfix.org

Reply via email to