]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-3.9-20230419
authorWietse Venema <wietse@porcupine.org>
Wed, 19 Apr 2023 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <postfix-users@dukhovni.org>
Fri, 28 Apr 2023 04:20:04 +0000 (00:20 -0400)
postfix/HISTORY
postfix/RELEASE_NOTES
postfix/WISHLIST
postfix/html/mysql_table.5.html
postfix/man/man5/mysql_table.5
postfix/proto/mysql_table
postfix/proto/stop
postfix/proto/stop.spell-cc
postfix/src/global/dict_mysql.c
postfix/src/global/dict_pgsql.c
postfix/src/global/mail_version.h

index b0a131ba17ef733879329029e66d764312dc8eb4..baaf4922ac175096bdf2c8189e121d5ef9fd7570 100644 (file)
@@ -27055,3 +27055,26 @@ Apologies for any names omitted.
        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 configuration file, the default
+       characterset is now configurable with the "charset" attribute.
+       Previously, the default was determined by the MySQL
+       implementation (utf8mb4 as of MySQL 8.0, latin1 with older
+       versions). This setting implicitly controls the collation
+       order. Files: proto/mysql_table, global/dict_mysql.c.
+
+20230418
+
+       Bugfix (introduced: Postfix 3.2): the MySQL client could
+       return "not found" instead of "error" (for example, resulting
+       in a 5XX SMTP status instead of 4XX) during the time that
+       all MySQL server connections were turned down after error.
+       Found during code maintenance. File: global/dict_mysql.c.
+
+20230419
+
+       Cleanup: in the PostgreSQL client, cosmetic changes to make
+       the code easier to maintain (in preparation for adding new
+       functionality). File: global/dict_pgsql.c.
index 2f93d92575cb33d8f3193e2af3f7c618b52b4b04..fb8922265b5563b1f0d28193fb0fe032a1799668 100644 (file)
@@ -25,3 +25,11 @@ now also distributed with the more recent Eclipse Public License
 (EPL) 2.0. Recipients can choose to take the software under the
 license of their choice. Those who are more comfortable with the
 IPL can continue with that license.
+
+Incompatible changes with snapshot 20230419
+===========================================
+
+The MySQL client default characterset is now configurable with the
+"charset" configuration file attribute. The default is "utf8mb4",
+consistent with the MySQL 8.0 built-in default, but different from
+earlier MySQL versions where the built-in default was "latin1".
index bc52ebc0118b329b7b022818a6a67aaff6cce97b..43f0baadc41fb2bc9c5f68aae47f3a0716dc4c49 100644 (file)
@@ -18,6 +18,9 @@ Wish list:
 
        Follow https://github.com/vdukhovni/postfix/commits/rpk
 
+       Figure out which mysql_*escape_string*() variant to use and
+       handle error results accordingly.
+
        Multi-recipient support in sender/recipient_bcc_maps and
        always_bcc.
 
index 4971e57c413f44df19db95fdabb7f9e03442ef67..2b499b7498ce682536f21de820c5946efaba8f67 100644 (file)
@@ -72,56 +72,64 @@ MYSQL_TABLE(5)                                                  MYSQL_TABLE(5)
        <b>dbname</b> The database name on the servers. Example:
                   dbname = customer_database
 
-       <b>query</b>  The SQL query template used to search the database, where <b>%s</b>  is
-              a  substitute for the address Postfix is trying to resolve, e.g.
+       <b>charset (default: utf8mb4)</b>
+              The default MySQL client character set; this  also  implies  the
+              collation order.
+
+              This  parameter  is  available with Postfix 3.9 and later.  With
+              earlier Postfix versions, the default was chosen  by  the  MySQL
+              implementation (<b>utf8mb4</b> as of MySQL 8.0, <b>latin1</b> historically).
+
+       <b>query</b>  The  SQL query template used to search the database, where <b>%s</b> is
+              a substitute for the address Postfix is trying to resolve,  e.g.
                   query = SELECT replacement FROM aliases WHERE mailbox = '%s'
 
-              By default, every query must return a  result  set  (instead  of
-              storing  its results in a table); with "<b>require_result_set = no</b>"
-              (Postfix 3.2 and later), the absence of a result set is  treated
+              By  default,  every  query  must return a result set (instead of
+              storing its results in a table); with "<b>require_result_set =  no</b>"
+              (Postfix  3.2 and later), the absence of a result set is treated
               as "not found".
 
               This parameter supports the following '%' expansions:
 
               <b>%%</b>     This is replaced by a literal '%' character.
 
-              <b>%s</b>     This  is  replaced by the input key.  SQL quoting is used
-                     to make sure that the input key does not  add  unexpected
+              <b>%s</b>     This is replaced by the input key.  SQL quoting  is  used
+                     to  make  sure that the input key does not add unexpected
                      metacharacters.
 
               <b>%u</b>     When the input key is an address of the form user@domain,
-                     <b>%u</b> is replaced by  the  SQL  quoted  local  part  of  the
-                     address.   Otherwise, <b>%u</b> is replaced by the entire search
-                     string.  If the localpart is empty,  the  query  is  sup-
+                     <b>%u</b>  is  replaced  by  the  SQL  quoted  local part of the
+                     address.  Otherwise, <b>%u</b> is replaced by the entire  search
+                     string.   If  the  localpart  is empty, the query is sup-
                      pressed and returns no results.
 
               <b>%d</b>     When the input key is an address of the form user@domain,
-                     <b>%d</b> is replaced by the  SQL  quoted  domain  part  of  the
-                     address.   Otherwise, the query is suppressed and returns
+                     <b>%d</b>  is  replaced  by  the  SQL  quoted domain part of the
+                     address.  Otherwise, the query is suppressed and  returns
                      no results.
 
               <b>%[SUD]</b> The upper-case equivalents of the above expansions behave
-                     in  the  <b>query</b>  parameter identically to their lower-case
-                     counter-parts.  With  the  <b>result_format</b>  parameter  (see
-                     below),  they expand the input key rather than the result
+                     in the <b>query</b> parameter identically  to  their  lower-case
+                     counter-parts.   With  the  <b>result_format</b>  parameter (see
+                     below), they expand the input key rather than the  result
                      value.
 
-              <b>%[1-9]</b> The patterns %1, %2, ... %9 are replaced  by  the  corre-
-                     sponding  most  significant  component of the input key's
-                     domain. If the input key is  <i>user@mail.example.com</i>,  then
+              <b>%[1-9]</b> The  patterns  %1,  %2, ... %9 are replaced by the corre-
+                     sponding most significant component of  the  input  key's
+                     domain.  If  the input key is <i>user@mail.example.com</i>, then
                      %1 is <b>com</b>, %2 is <b>example</b> and %3 is <b>mail</b>. If the input key
-                     is unqualified or does not have enough domain  components
-                     to  satisfy all the specified patterns, the query is sup-
+                     is  unqualified or does not have enough domain components
+                     to satisfy all the specified patterns, the query is  sup-
                      pressed and returns no results.
 
-              The <b>domain</b> parameter described below limits the  input  keys  to
-              addresses  in  matching  domains.  When  the <b>domain</b> parameter is
+              The  <b>domain</b>  parameter  described below limits the input keys to
+              addresses in matching domains.  When  the  <b>domain</b>  parameter  is
               non-empty, SQL queries for unqualified addresses or addresses in
               non-matching domains are suppressed and return no results.
 
-              This  parameter is available with Postfix 2.2. In prior releases
-              the  SQL  query  was  built  from   the   separate   parameters:
-              <b>select_field</b>,  <b>table</b>, <b>where_field</b> and <b>additional_conditions</b>. The
+              This parameter is available with Postfix 2.2. In prior  releases
+              the   SQL   query   was  built  from  the  separate  parameters:
+              <b>select_field</b>, <b>table</b>, <b>where_field</b> and <b>additional_conditions</b>.  The
               mapping from the old parameters to the equivalent query is:
 
                   SELECT [<b>select_field</b>]
@@ -129,50 +137,50 @@ MYSQL_TABLE(5)                                                  MYSQL_TABLE(5)
                   WHERE [<b>where_field</b>] = '%s'
                         [<b>additional_conditions</b>]
 
-              The '%s' in the <b>WHERE</b>  clause  expands  to  the  escaped  search
-              string.   With  Postfix  2.2 these legacy parameters are used if
+              The  '%s'  in  the  <b>WHERE</b>  clause  expands to the escaped search
+              string.  With Postfix 2.2 these legacy parameters  are  used  if
               the <b>query</b> parameter is not specified.
 
               NOTE: DO NOT put quotes around the query parameter.
 
        <b>result_format (default: %s</b>)
               Format template applied to result attributes. Most commonly used
-              to  append  (or prepend) text to the result. This parameter sup-
+              to append (or prepend) text to the result. This  parameter  sup-
               ports the following '%' expansions:
 
               <b>%%</b>     This is replaced by a literal '%' character.
 
-              <b>%s</b>     This is replaced by the value of  the  result  attribute.
+              <b>%s</b>     This  is  replaced  by the value of the result attribute.
                      When result is empty it is skipped.
 
               <b>%u</b>     When the result attribute value is an address of the form
-                     user@domain, <b>%u</b> is replaced by  the  local  part  of  the
-                     address.  When  the  result  has an empty localpart it is
+                     user@domain,  <b>%u</b>  is  replaced  by  the local part of the
+                     address. When the result has an  empty  localpart  it  is
                      skipped.
 
-              <b>%d</b>     When a result attribute value is an address of  the  form
-                     user@domain,  <b>%d</b>  is  replaced  by the domain part of the
-                     attribute value. When the result  is  unqualified  it  is
+              <b>%d</b>     When  a  result attribute value is an address of the form
+                     user@domain, <b>%d</b> is replaced by the  domain  part  of  the
+                     attribute  value.  When  the  result is unqualified it is
                      skipped.
 
               <b>%[SUD1-9]</b>
-                     The  upper-case  and decimal digit expansions interpolate
-                     the parts of the input key rather than the result.  Their
-                     behavior  is  identical to that described with <b>query</b>, and
-                     in fact because  the  input  key  is  known  in  advance,
-                     queries  whose  key  does not contain all the information
-                     specified in  the  result  template  are  suppressed  and
+                     The upper-case and decimal digit  expansions  interpolate
+                     the  parts of the input key rather than the result. Their
+                     behavior is identical to that described with  <b>query</b>,  and
+                     in  fact  because  the  input  key  is  known in advance,
+                     queries whose key does not contain  all  the  information
+                     specified  in  the  result  template  are  suppressed and
                      return no results.
 
               For example, using "result_format = <a href="smtp.8.html">smtp</a>:[%s]" allows one to use
               a mailHost attribute as the basis of a <a href="transport.5.html">transport(5)</a> table. After
-              applying  the result format, multiple values are concatenated as
+              applying the result format, multiple values are concatenated  as
               comma  separated  strings.  The  expansion_limit  and  parameter
-              explained  below  allows one to restrict the number of values in
+              explained below allows one to restrict the number of  values  in
               the result, which is especially useful for maps that must return
               at most one value.
 
-              The  default value <b>%s</b> specifies that each result value should be
+              The default value <b>%s</b> specifies that each result value should  be
               used as is.
 
               This parameter is available with Postfix 2.2 and later.
@@ -180,15 +188,15 @@ MYSQL_TABLE(5)                                                  MYSQL_TABLE(5)
               NOTE: DO NOT put quotes around the result format!
 
        <b>domain (default: no domain list)</b>
-              This is a list of domain names, paths to files, or  "<a href="DATABASE_README.html">type:table</a>"
+              This  is a list of domain names, paths to files, or "<a href="DATABASE_README.html">type:table</a>"
               databases. When specified, only fully qualified search keys with
-              a *non-empty* localpart and a matching domain are  eligible  for
+              a  *non-empty*  localpart and a matching domain are eligible for
               lookup:  'user'  lookups,  bare  domain  lookups  and  "@domain"
-              lookups are not performed. This  can  significantly  reduce  the
+              lookups  are  not  performed.  This can significantly reduce the
               query load on the MySQL server.
                   domain = postfix.org, <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/searchdomains
 
-              It  is best not to use SQL to store the domains eligible for SQL
+              It is best not to use SQL to store the domains eligible for  SQL
               lookups.
 
               This parameter is available with Postfix 2.2 and later.
@@ -197,37 +205,37 @@ MYSQL_TABLE(5)                                                  MYSQL_TABLE(5)
               the input keys are always unqualified.
 
        <b>expansion_limit (default: 0)</b>
-              A  limit  on  the total number of result elements returned (as a
+              A limit on the total number of result elements  returned  (as  a
               comma separated list) by a lookup against the map.  A setting of
-              zero  disables the limit. Lookups fail with a temporary error if
-              the limit is exceeded.  Setting the  limit  to  1  ensures  that
+              zero disables the limit. Lookups fail with a temporary error  if
+              the  limit  is  exceeded.   Setting  the limit to 1 ensures that
               lookups do not return multiple values.
 
        <b>option_file</b>
-              Read  options  from the given file instead of the default my.cnf
-              location. This reads options from  the  <b>[client]</b>  option  group,
+              Read options from the given file instead of the  default  my.cnf
+              location.  This  reads  options  from the <b>[client]</b> option group,
               optionally  followed  by  options  from  the  group  given  with
               <b>option_group</b>.
 
               This parameter is available with Postfix 2.11 and later.
 
        <b>option_group (default: Postfix</b> &gt;<b>=3.2: client,</b> &lt;<b>= 3.1: empty)</b>
-              Read options from the given group of  the  mysql  options  file,
+              Read  options  from  the  given group of the mysql options file,
               after reading options from the <b>[client]</b> group.
 
-              Postfix  3.2  and  later  read <b>[client]</b> option group settings by
-              default. To disable this  specify  no  <b>option_file</b>  and  specify
+              Postfix 3.2 and later read <b>[client]</b>  option  group  settings  by
+              default.  To  disable  this  specify  no <b>option_file</b> and specify
               "<b>option_group =</b>" (i.e. an empty value).
 
-              Postfix  3.1  and  earlier don't read <b>[client]</b> option group set-
-              tings unless a non-empty <b>option_file</b> or <b>option_group</b>  value  are
+              Postfix 3.1 and earlier don't read <b>[client]</b>  option  group  set-
+              tings  unless  a non-empty <b>option_file</b> or <b>option_group</b> value are
               specified. To enable this, specify, for example, "<b>option_group =</b>
               <b>client</b>".
 
               This parameter is available with Postfix 2.11 and later.
 
        <b>require_result_set (default: yes)</b>
-              If "<b>yes</b>", require that every query returns  a  result  set.   If
+              If  "<b>yes</b>",  require  that  every query returns a result set.  If
               "<b>no</b>", treat the absence of a result set as "not found".
 
               This parameter is available with Postfix 3.2 and later.
@@ -238,19 +246,19 @@ MYSQL_TABLE(5)                                                  MYSQL_TABLE(5)
               This parameter is available with Postfix 2.11 and later.
 
        <b>tls_key_file</b>
-              File  containing the private key corresponding to <b>tls_cert_file</b>.
+              File containing the private key corresponding to  <b>tls_cert_file</b>.
 
               This parameter is available with Postfix 2.11 and later.
 
        <b>tls_CAfile</b>
-              File containing certificates for all of the  X509  Certification
-              Authorities  the  client  will recognize.  Takes precedence over
+              File  containing  certificates for all of the X509 Certification
+              Authorities the client will recognize.   Takes  precedence  over
               <b>tls_CApath</b>.
 
               This parameter is available with Postfix 2.11 and later.
 
        <b>tls_CApath</b>
-              Directory containing X509 Certification  Authority  certificates
+              Directory  containing  X509 Certification Authority certificates
               in separate individual files.
 
               This parameter is available with Postfix 2.11 and later.
@@ -261,13 +269,13 @@ MYSQL_TABLE(5)                                                  MYSQL_TABLE(5)
               This parameter is available with Postfix 2.11 and later.
 
        <b>tls_verify_cert (default: no)</b>
-              Verify  that  the  server's  name matches the common name in the
+              Verify that the server's name matches the  common  name  in  the
               certificate.
 
               This parameter is available with Postfix 2.11 and later.
 
 <b>USING MYSQL STORED PROCEDURES</b>
-       Postfix 3.2 and later support calling a  stored  procedure  instead  of
+       Postfix  3.2  and  later  support calling a stored procedure instead of
        using a SELECT statement in the query, e.g.
 
            <b>query</b> = CALL lookup('%s')
@@ -275,17 +283,17 @@ MYSQL_TABLE(5)                                                  MYSQL_TABLE(5)
        The previously described '%' expansions can be used in the parameter(s)
        to the stored procedure.
 
-       By default, every stored procedure call must return a result set,  i.e.
-       every  code  path must execute a SELECT statement that returns a result
+       By  default, every stored procedure call must return a result set, i.e.
+       every code path must execute a SELECT statement that returns  a  result
        set   (instead   of   storing   its   results   in   a   table).   With
-       "<b>require_result_set  =  no</b>",  the absence of a result set is treated as
+       "<b>require_result_set = no</b>", the absence of a result set  is  treated  as
        "not found".
 
-       A stored procedure must not return  multiple  result  sets.   That  is,
-       there  must  be  no  code path that executes multiple SELECT statements
+       A  stored  procedure  must  not  return multiple result sets.  That is,
+       there must be no code path that  executes  multiple  SELECT  statements
        that return a result (instead of storing their results in a table).
 
-       The following is an example of a stored procedure  returning  a  single
+       The  following  is  an example of a stored procedure returning a single
        result set:
 
        CREATE [DEFINER=`user`@`host`] PROCEDURE
@@ -297,26 +305,26 @@ MYSQL_TABLE(5)                                                  MYSQL_TABLE(5)
            END
 
 <b>OBSOLETE MAIN.CF PARAMETERS</b>
-       For  compatibility  with  other Postfix lookup tables, MySQL parameters
-       can also be defined in <a href="postconf.5.html">main.cf</a>.  In order to do that, specify as  MySQL
-       source  a  name  that  doesn't  begin with a slash or a dot.  The MySQL
-       parameters will then be accessible as the name you've given the  source
-       in  its  definition, an underscore, and the name of the parameter.  For
-       example, if the map is specified as  "<a href="mysql_table.5.html">mysql</a>:<i>mysqlname</i>",  the  parameter
+       For compatibility with other Postfix lookup  tables,  MySQL  parameters
+       can  also be defined in <a href="postconf.5.html">main.cf</a>.  In order to do that, specify as MySQL
+       source a name that doesn't begin with a slash  or  a  dot.   The  MySQL
+       parameters  will then be accessible as the name you've given the source
+       in its definition, an underscore, and the name of the  parameter.   For
+       example,  if  the  map is specified as "<a href="mysql_table.5.html">mysql</a>:<i>mysqlname</i>", the parameter
        "hosts" would be defined in <a href="postconf.5.html">main.cf</a> as "<i>mysqlname</i>_hosts".
 
-       Note:  with  this form, the passwords for the MySQL sources are written
-       in <a href="postconf.5.html">main.cf</a>, which is normally world-readable.  Support  for  this  form
+       Note: with this form, the passwords for the MySQL sources  are  written
+       in  <a href="postconf.5.html">main.cf</a>,  which  is normally world-readable.  Support for this form
        will be removed in a future Postfix version.
 
 <b>OBSOLETE QUERY INTERFACE</b>
-       This  section  describes  an interface that is deprecated as of Postfix
-       2.2. It is replaced by  the  more  general  <b>query</b>  interface  described
-       above.  If  the  <b>query</b>  parameter  is  defined,  the  legacy parameters
-       described here ignored.  Please migrate to the  new  interface  as  the
+       This section describes an interface that is deprecated  as  of  Postfix
+       2.2.  It  is  replaced  by  the  more general <b>query</b> interface described
+       above. If  the  <b>query</b>  parameter  is  defined,  the  legacy  parameters
+       described  here  ignored.   Please  migrate to the new interface as the
        legacy interface may be removed in a future release.
 
-       The  following  parameters  can  be  used  to fill in a SELECT template
+       The following parameters can be used  to  fill  in  a  SELECT  template
        statement of the form:
 
            SELECT [<b>select_field</b>]
@@ -325,7 +333,7 @@ MYSQL_TABLE(5)                                                  MYSQL_TABLE(5)
                  [<b>additional_conditions</b>]
 
        The specifier %s is replaced by the search string, and is escaped so if
-       it  contains single quotes or other odd characters, it will not cause a
+       it contains single quotes or other odd characters, it will not cause  a
        parse error, or worse, a security problem.
 
        <b>select_field</b>
index 2b01aca8cabe26c96c9d2dba4580124f89e1e80f..40f5234e9b9c0b03dcd27e967964b047e59f42cb 100644 (file)
@@ -89,6 +89,14 @@ The database name on the servers. Example:
 .nf
     dbname = customer_database
 .fi
+.IP "\fBcharset (default: utf8mb4)\fR"
+The default MySQL client character set; this also implies
+the collation order.
+
+This parameter is available with Postfix 3.9 and later.
+With earlier Postfix versions, the default was chosen by
+the MySQL implementation (\fButf8mb4\fR as of MySQL 8.0,
+\fBlatin1\fR historically).
 .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,
index a018e58b5634e2d4ace3d013a954ce886b7cfd7d..94e8ac65da3886815672c214e60cfea204197d9f 100644 (file)
 # .nf
 #          dbname = customer_database
 # .fi
+# .IP "\fBcharset (default: utf8mb4)\fR"
+#      The default MySQL client character set; this also implies
+#      the collation order.
+#
+#      This parameter is available with Postfix 3.9 and later.
+#      With earlier Postfix versions, the default was chosen by
+#      the MySQL implementation (\fButf8mb4\fR as of MySQL 8.0,
+#      \fBlatin1\fR historically).
 # .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,
index 0ad35112d384afce8a8da346ff219f532dcfbc18..1026d9c4b47a66eaf7f7773d32a78c39d00a8c73 100644 (file)
@@ -1577,3 +1577,6 @@ Korbar
 ffdhe
 srv
 stderr
+charset
+latin
+utf
index 3da66902586915dda2cc10fe71c18f20b4ffc765..84fcd87586669dc28ff2f52e12e6e63f5ce234c8 100644 (file)
@@ -1443,7 +1443,7 @@ tv
 txn
 TXT
 Typechecking
-TYPECONNSTRING
+TYPECONNSTR
 typedef
 typedefs
 TYPEINET
index c3151d7f84c301f25a5467c60f3b8337fa3ab753..2a9d424260cc3055a4d5ed9054b536c0a7ee63ef 100644 (file)
@@ -147,6 +147,7 @@ typedef struct {
     char   *username;
     char   *password;
     char   *dbname;
+    char   *charset;
     ARGV   *hosts;
     PLMYSQL *pldb;
 #if defined(MYSQL_VERSION_ID) && MYSQL_VERSION_ID >= 40000
@@ -439,7 +440,7 @@ static int plmysql_query(DICT_MYSQL *dict_mysql,
 {
     HOST   *host;
     MYSQL_RES *first_result = 0;
-    int     query_error;
+    int     query_error = 1;
 
     /*
      * Helper to avoid spamming the log with warnings.
@@ -602,6 +603,12 @@ static void plmysql_connect_single(DICT_MYSQL *dict_mysql, HOST *host)
                           host->port,
                           (host->type == TYPEUNIX ? host->name : 0),
                           CLIENT_MULTI_RESULTS)) {
+       if (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 +653,7 @@ static void mysql_parse_config(DICT_MYSQL *dict_mysql, const char *mysqlcf)
     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", "utf8mb4", 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 +834,7 @@ static void dict_mysql_close(DICT *dict)
     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)
index 599213583cdedbb25be51df41b70d15e93c7465e..ac1123e01b9bb22b5443d9a3647611827a4d56fa 100644 (file)
 
 #define TYPEUNIX                       (1<<0)
 #define TYPEINET                       (1<<1)
-#define TYPECONNSTRING                 (1<<2)
+#define TYPECONNSTR                    (1<<2)
 
 #define RETRY_CONN_MAX                 100
 #define RETRY_CONN_INTV                        60      /* 1 minute */
@@ -119,7 +119,7 @@ typedef struct {
     char   *hostname;
     char   *name;
     char   *port;
-    unsigned type;                     /* TYPEUNIX | TYPEINET | TYPECONNSTRING */
+    unsigned type;                     /* TYPEUNIX | TYPEINET | TYPECONNSTR */
     unsigned stat;                     /* STATUNTRIED | STATFAIL | STATCUR */
     time_t  ts;                                /* used for attempting reconnection */
 } HOST;
@@ -152,12 +152,11 @@ typedef struct {
 
 /* internal function declarations */
 static PLPGSQL *plpgsql_init(ARGV *);
-static PGSQL_RES *plpgsql_query(DICT_PGSQL *, const char *, VSTRING *, char *,
-                                       char *, char *, char *);
+static PGSQL_RES *plpgsql_query(DICT_PGSQL *, const char *, VSTRING *);
 static void plpgsql_dealloc(PLPGSQL *);
 static void plpgsql_close_host(HOST *);
 static void plpgsql_down_host(HOST *);
-static void plpgsql_connect_single(HOST *, char *, char *, char *, char *);
+static void plpgsql_connect_single(DICT_PGSQL *, HOST *);
 static const char *dict_pgsql_lookup(DICT *, const char *);
 DICT   *dict_pgsql_open(const char *, int, int);
 static void dict_pgsql_close(DICT *);
@@ -324,11 +323,7 @@ static const char *dict_pgsql_lookup(DICT *dict, const char *name)
        return (0);
 
     /* do the query - set dict->error & cleanup if there's an error */
-    if ((query_res = plpgsql_query(dict_pgsql, name, query,
-                                  dict_pgsql->dbname,
-                                  dict_pgsql->encoding,
-                                  dict_pgsql->username,
-                                  dict_pgsql->password)) == 0) {
+    if ((query_res = plpgsql_query(dict_pgsql, name, query)) == 0) {
        dict->error = DICT_ERR_RETRY;
        return 0;
     }
@@ -404,8 +399,7 @@ static HOST *dict_pgsql_find_host(PLPGSQL *PLDB, unsigned stat, unsigned type)
 
 /* dict_pgsql_get_active - get an active connection */
 
-static HOST *dict_pgsql_get_active(PLPGSQL *PLDB, char *dbname, char *encoding,
-                                          char *username, char *password)
+static HOST *dict_pgsql_get_active(DICT_PGSQL *dict_pgsql, PLPGSQL *PLDB)
 {
     const char *myname = "dict_pgsql_get_active";
     HOST   *host;
@@ -414,7 +408,7 @@ static HOST *dict_pgsql_get_active(PLPGSQL *PLDB, char *dbname, char *encoding,
     /* try the active connections first; prefer the ones to UNIX sockets */
     if ((host = dict_pgsql_find_host(PLDB, STATACTIVE, TYPEUNIX)) != NULL ||
        (host = dict_pgsql_find_host(PLDB, STATACTIVE, TYPEINET)) != NULL ||
-       (host = dict_pgsql_find_host(PLDB, STATACTIVE, TYPECONNSTRING)) != NULL) {
+     (host = dict_pgsql_find_host(PLDB, STATACTIVE, TYPECONNSTR)) != NULL) {
        if (msg_verbose)
            msg_info("%s: found active connection to host %s", myname,
                     host->hostname);
@@ -432,11 +426,11 @@ static HOST *dict_pgsql_get_active(PLPGSQL *PLDB, char *dbname, char *encoding,
            (host = dict_pgsql_find_host(PLDB, STATUNTRIED | STATFAIL,
                                         TYPEINET)) != NULL ||
            (host = dict_pgsql_find_host(PLDB, STATUNTRIED | STATFAIL,
-                                        TYPECONNSTRING)) != NULL)) {
+                                        TYPECONNSTR)) != NULL)) {
        if (msg_verbose)
            msg_info("%s: attempting to connect to host %s", myname,
                     host->hostname);
-       plpgsql_connect_single(host, dbname, encoding, username, password);
+       plpgsql_connect_single(dict_pgsql, host);
        if (host->stat == STATACTIVE)
            return host;
     }
@@ -464,18 +458,14 @@ static void dict_pgsql_event(int unused_event, void *context)
 
 static PGSQL_RES *plpgsql_query(DICT_PGSQL *dict_pgsql,
                                        const char *name,
-                                       VSTRING *query,
-                                       char *dbname,
-                                       char *encoding,
-                                       char *username,
-                                       char *password)
+                                       VSTRING *query)
 {
     PLPGSQL *PLDB = dict_pgsql->pldb;
     HOST   *host;
     PGSQL_RES *res = 0;
     ExecStatusType status;
 
-    while ((host = dict_pgsql_get_active(PLDB, dbname, encoding, username, password)) != NULL) {
+    while ((host = dict_pgsql_get_active(dict_pgsql, PLDB)) != NULL) {
 
        /*
         * The active host is used to escape strings in the context of the
@@ -570,13 +560,14 @@ static PGSQL_RES *plpgsql_query(DICT_PGSQL *dict_pgsql,
  * used to reconnect to a single database when one is down or none is
  * connected yet. Log all errors and set the stat field of host accordingly
  */
-static void plpgsql_connect_single(HOST *host, char *dbname, char *encoding, char *username, char *password)
+static void plpgsql_connect_single(DICT_PGSQL *dict_pgsql, HOST *host)
 {
-    if (host->type == TYPECONNSTRING) {
+    if (host->type == TYPECONNSTR) {
        host->db = PQconnectdb(host->name);
     } else {
        host->db = PQsetdbLogin(host->name, host->port, NULL, NULL,
-                               dbname, username, password);
+                               dict_pgsql->dbname, dict_pgsql->username,
+                               dict_pgsql->password);
     }
     if (host->db == NULL || PQstatus(host->db) != CONNECTION_OK) {
        msg_warn("connect to pgsql server %s: %s",
@@ -584,9 +575,9 @@ static void plpgsql_connect_single(HOST *host, char *dbname, char *encoding, cha
        plpgsql_down_host(host);
        return;
     }
-    if (PQsetClientEncoding(host->db, encoding) != 0) {
+    if (PQsetClientEncoding(host->db, dict_pgsql->encoding) != 0) {
        msg_warn("dict_pgsql: cannot set the encoding to %s, skipping %s",
-                encoding, host->hostname);
+                dict_pgsql->encoding, host->hostname);
        plpgsql_down_host(host);
        return;
     }
@@ -764,7 +755,7 @@ static HOST *host_init(const char *hostname)
      * Modern syntax: "postgresql://connection-info".
      */
     if (strncmp(d, "postgresql:", 11) == 0) {
-       host->type = TYPECONNSTRING;
+       host->type = TYPECONNSTR;
        host->name = mystrdup(d);
        host->port = 0;
     }
index 8f86357bad1340a251a01b0f7a47c48f96c9b38c..775fa2a8c4d1fc01ca9719738bdc4743425c242c 100644 (file)
@@ -20,7 +20,7 @@
   * Patches change both the patchlevel and the release date. Snapshots have no
   * patchlevel; they change the release date only.
   */
-#define MAIL_RELEASE_DATE      "20230416"
+#define MAIL_RELEASE_DATE      "20230419"
 #define MAIL_VERSION_NUMBER    "3.9"
 
 #ifdef SNAPSHOT