2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-08-22 09:57:34 +00:00

postfix-3.2-20161226-nonprod

This commit is contained in:
Wietse Venema 2016-12-26 00:00:00 -05:00 committed by Viktor Dukhovni
parent 551bd26bfa
commit 5b0b13c24e
8 changed files with 233 additions and 192 deletions

1
postfix/.indent.pro vendored
View File

@ -223,6 +223,7 @@
-TMVECT
-TMYSQL
-TMYSQL_NAME
-TMYSQL_RES
-TNAMADR_LIST
-TNAME_ASSIGNMENT
-TNAME_CODE

View File

@ -22702,3 +22702,11 @@ Apologies for any names omitted.
Cleanup: simplified code structure in the MySQL client
support for stored procedures. File: global/dict_mysql.c.
20161226
Cleanup: more MySQL client code simplification, better error
messages, new per-database "require_result_set" parameter
(default: yes) which can be set to "no" to avoid the need
for dummy SELECT statements in stored procedures. Files:
global/dict_mysql.c, proto/mysql_table, postconf/postconf_dbms.c.

View File

@ -101,47 +101,52 @@ MYSQL_TABLE(5) MYSQL_TABLE(5)
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
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>]
@ -149,50 +154,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.
@ -201,14 +206,14 @@ MYSQL_TABLE(5) MYSQL_TABLE(5)
<b>domain (default: no domain list)</b>
This is a list of domain names, paths to files, or dictionaries.
When specified, only fully qualified search keys with a
*non-empty* localpart and a matching domain are eligible for
When specified, only fully qualified search keys with 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.
@ -217,35 +222,41 @@ 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
"<b>no</b>", treat the absence of a result set as "not found".
This parameter is available with Postfix 3.2 and later.
<b>tls_cert_file</b>
File containing client's X509 certificate.
@ -284,25 +295,18 @@ MYSQL_TABLE(5) MYSQL_TABLE(5)
The previously described '%' expansions can be used in the parameter(s)
to the stored procedure.
The stored procedure must return data with a single result set, that is
the stored procedure must execute exactly one SELECT statement on every
code path. If you have complex logic and for some paths you want to
return no result you will need to include a SELECT statement that
returns no rows. One example of a query that returns no rows is
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
"not found".
SELECT 1 FROM DUAL WHERE FALSE
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).
but you may use your own query.
Stored procedures that return multiple result sets containing data,
that is stored procedures that execute multiple SELECT statements, are
not supported. Stored procedures in mysql produce an additional result
set without data which indicates the final status of the stored proce-
dure. If this final status is an error then any previous returned data
will not be used.
The following is an example of a stored procedure returning a single
result set containing data:
The following is an example of a stored procedure returning a single
result set:
CREATE [DEFINER=`user`@`host`] PROCEDURE
`lookup`(IN `param` VARCHAR(255))
@ -313,13 +317,13 @@ MYSQL_TABLE(5) MYSQL_TABLE(5)
END
<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>]
@ -328,7 +332,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>
@ -376,5 +380,10 @@ MYSQL_TABLE(5) MYSQL_TABLE(5)
Stored-procedure support by John Fawcett.
Wietse Venema
Google, Inc.
111 8th Avenue
New York, NY 10011, USA
MYSQL_TABLE(5)
</pre> </body> </html>

View File

@ -132,6 +132,11 @@ e.g.
query = SELECT replacement FROM aliases WHERE mailbox = '%s'
.fi
By default, every query must return a result set (instead
of storing its results in a table); with "\fBrequire_result_set
= no\fR" (Postfix 3.2 and later), the absence of a result
set is treated as "not found".
This parameter supports the following '%' expansions:
.RS
.IP "\fB%%\fR"
@ -277,6 +282,12 @@ group settings unless a non\-empty \fBoption_file\fR or
specify, for example, "\fBoption_group = client\fR".
.sp
This parameter is available with Postfix 2.11 and later.
.IP "\fBrequire_result_set (default: yes)\fR"
If "\fByes\fR", require that every query returns a result
set. If "\fBno\fR", treat the absence of a result set as
"not found".
.sp
This parameter is available with Postfix 3.2 and later.
.IP "\fBtls_cert_file\fR"
File containing client's X509 certificate.
.sp
@ -316,29 +327,19 @@ instead of using a SELECT statement in the query, e.g.
The previously described '%' expansions can be used in the
parameter(s) to the stored procedure.
The stored procedure must return data with a single result
set, that is the stored procedure must execute exactly one
SELECT statement on every code path. If you have complex
logic and for some paths you want to return no result you
will need to include a SELECT statement that returns no
rows. One example of a query that returns no rows is
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 "\fBrequire_result_set = no\fR", the
absence of a result set is treated as "not found".
.nf
SELECT 1 FROM DUAL WHERE FALSE
.fi
but you may use your own query.
Stored procedures that return multiple result sets containing
data, that is stored procedures that execute multiple SELECT
statements, are not supported. Stored procedures in mysql
produce an additional result set without data which indicates
the final status of the stored procedure. If this final
status is an error then any previous returned data will not
be used.
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 result set containing data:
a single result set:
.nf
CREATE [DEFINER=`user`@`host`] PROCEDURE
@ -356,7 +357,7 @@ CREATE [DEFINER=`user`@`host`] PROCEDURE
.fi
This section describes an interface that is deprecated as
of Postfix 2.2. It is replaced by the more general \fBquery\fR
interface described above. If the \fBquery\fR parameter
interface described above. If the \fBquery\fR 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.
@ -437,3 +438,8 @@ P.O. BOX 1\-764
RO\-014700 Bucharest, ROMANIA
Stored\-procedure support by John Fawcett.
Wietse Venema
Google, Inc.
111 8th Avenue
New York, NY 10011, USA

View File

@ -120,6 +120,11 @@
# query = SELECT replacement FROM aliases WHERE mailbox = '%s'
# .fi
#
# By default, every query must return a result set (instead
# of storing its results in a table); with "\fBrequire_result_set
# = no\fR" (Postfix 3.2 and later), the absence of a result
# set is treated as "not found".
#
# This parameter supports the following '%' expansions:
# .RS
# .IP "\fB%%\fR"
@ -265,6 +270,12 @@
# specify, for example, "\fBoption_group = client\fR".
# .sp
# This parameter is available with Postfix 2.11 and later.
# .IP "\fBrequire_result_set (default: yes)\fR"
# If "\fByes\fR", require that every query returns a result
# set. If "\fBno\fR", treat the absence of a result set as
# "not found".
# .sp
# This parameter is available with Postfix 3.2 and later.
# .IP "\fBtls_cert_file\fR"
# File containing client's X509 certificate.
# .sp
@ -302,29 +313,19 @@
# The previously described '%' expansions can be used in the
# parameter(s) to the stored procedure.
#
# The stored procedure must return data with a single result
# set, that is the stored procedure must execute exactly one
# SELECT statement on every code path. If you have complex
# logic and for some paths you want to return no result you
# will need to include a SELECT statement that returns no
# rows. One example of a query that returns no rows is
# 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 "\fBrequire_result_set = no\fR", the
# absence of a result set is treated as "not found".
#
# .nf
# SELECT 1 FROM DUAL WHERE FALSE
# .fi
#
# but you may use your own query.
#
# Stored procedures that return multiple result sets containing
# data, that is stored procedures that execute multiple SELECT
# statements, are not supported. Stored procedures in mysql
# produce an additional result set without data which indicates
# the final status of the stored procedure. If this final
# status is an error then any previous returned data will not
# be used.
# 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 result set containing data:
# a single result set:
#
# .nf
# CREATE [DEFINER=`user`@`host`] PROCEDURE
@ -340,7 +341,7 @@
# .fi
# This section describes an interface that is deprecated as
# of Postfix 2.2. It is replaced by the more general \fBquery\fR
# interface described above. If the \fBquery\fR parameter
# interface described above. If the \fBquery\fR 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.
@ -411,4 +412,9 @@
# RO-014700 Bucharest, ROMANIA
#
# Stored-procedure support by John Fawcett.
#
# Wietse Venema
# Google, Inc.
# 111 8th Avenue
# New York, NY 10011, USA
#--

View File

@ -96,6 +96,8 @@
/* location.
/* .IP option_group
/* Read options from the given group.
/* .IP require_result_set
/* Require that every query produces a result set.
/* .IP tls_cert_file
/* File containing client's X509 certificate.
/* .IP tls_key_file
@ -132,44 +134,25 @@
/* where_field = alias
/* .br
/* hosts = host1.some.domain host2.some.domain
/* .IP additional_conditions
/* Backward compatibility when \fIquery\fR is not set, additional
/* conditions to the WHERE clause.
/* .IP hosts
/* List of hosts to connect to.
/* .PP
/* For example, if you want the map to reference databases of
/* the name "your_db" and execute a query like this: select
/* forw_addr from aliases where alias like '<some username>'
/* against any database called "vmailer_info" located on hosts
/* host1.some.domain and host2.some.domain, logging in as user
/* "vmailer" and password "passwd" then the configuration file
/* should read:
/* .PP
/* user = vmailer
/* .br
/* password = passwd
/* .br
/* dbname = vmailer_info
/* .br
/* table = aliases
/* .br
/* select_field = forw_addr
/* .br
/* where_field = alias
/* .br
/* hosts = host1.some.domain host2.some.domain
/* .PP
/* SEE ALSO
/* dict(3) generic dictionary manager
/* AUTHOR(S)
/* Scott Cotton
/* Scott Cotton, Joshua Marcus
/* IC Group, Inc.
/* scott@icgroup.com
/*
/* Joshua Marcus
/* IC Group, Inc.
/* josh@icgroup.com
/* Liviu Daia
/* Institute of Mathematics of the Romanian Academy
/* P.O. BOX 1-764
/* RO-014700 Bucharest, ROMANIA
/*
/* John Fawcett
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/
/* System library. */
@ -258,6 +241,7 @@ typedef struct {
int tls_verify_cert;
#endif
#endif
int require_result_set;
} DICT_MYSQL;
#define STATACTIVE (1<<0)
@ -273,7 +257,7 @@ typedef struct {
/* internal function declarations */
static PLMYSQL *plmysql_init(ARGV *);
static MYSQL_RES *plmysql_query(DICT_MYSQL *, const char *, VSTRING *);
static int plmysql_query(DICT_MYSQL *, const char *, VSTRING *, MYSQL_RES **);
static void plmysql_dealloc(PLMYSQL *);
static void plmysql_close_host(HOST *);
static void plmysql_down_host(HOST *);
@ -383,10 +367,12 @@ static const char *dict_mysql_lookup(DICT *dict, const char *name)
return (0);
/* do the query - set dict->error & cleanup if there's an error */
if ((query_res = plmysql_query(dict_mysql, name, query)) == 0) {
if (plmysql_query(dict_mysql, name, query, &query_res) == 0) {
dict->error = DICT_ERR_RETRY;
return (0);
}
if (query_res == 0)
return (0);
numrows = mysql_num_rows(query_res);
if (msg_verbose)
msg_info("%s: retrieved %d rows", myname, numrows);
@ -508,18 +494,20 @@ static void dict_mysql_event(int unused_event, void *context)
}
/*
* plmysql_query - process a MySQL query. Return MYSQL_RES* on success.
* plmysql_query - process a MySQL query. Return 'true' on success.
* On failure, log failure and try other db instances.
* on failure of all db instances, return 0;
* on failure of all db instances, return 'false';
* close unnecessary active connections
*/
static MYSQL_RES *plmysql_query(DICT_MYSQL *dict_mysql,
const char *name,
VSTRING *query)
static int plmysql_query(DICT_MYSQL *dict_mysql,
const char *name,
VSTRING *query,
MYSQL_RES **result)
{
HOST *host;
MYSQL_RES *res = 0;
MYSQL_RES *first_result = 0;
int query_error;
/*
* Helper to avoid spamming the log with warnings.
@ -533,7 +521,6 @@ static MYSQL_RES *plmysql_query(DICT_MYSQL *dict_mysql,
} while (0)
while ((host = dict_mysql_get_active(dict_mysql)) != NULL) {
int query_error = 0;
#if defined(MYSQL_VERSION_ID) && MYSQL_VERSION_ID >= 40000
@ -549,56 +536,77 @@ static MYSQL_RES *plmysql_query(DICT_MYSQL *dict_mysql,
dict_mysql->active_host = 0;
#endif
query_error = 0;
errno = 0;
/*
* The query must complete.
*/
if (mysql_query(host->db, vstring_str(query)) != 0) {
query_error = 1;
msg_warn("mysql query failed: %s", mysql_error(host->db));
msg_warn("%s:%s: query failed: %s",
dict_mysql->dict.type, dict_mysql->dict.name,
mysql_error(host->db));
}
/*
* The query must return at least one result.
*/
else if ((res = mysql_store_result(host->db)) == 0) {
query_error = 1;
msg_warn("mysql query failed: no result set containing data");
}
/*
* Are there more results? -1 = no, 0 = yes, > 0 = error. We must
* collect all results to avoid synchronization errors.
* Collect all result sets to avoid synchronization errors.
*/
else {
int next_res_status;
MYSQL_RES *temp_res;
while ((next_res_status = mysql_next_result(host->db)) >= 0) {
if (next_res_status > 0) {
SET_ERROR_AND_WARN_ONCE(query_error,
"mysql query failed (mysql_next_result): %s",
mysql_error(host->db));
}
do {
MYSQL_RES *temp_result;
/*
* The result must not contain data.
* Keep the first result set. Reject multiple result sets.
*/
else if ((temp_res = mysql_store_result(host->db)) != 0) {
SET_ERROR_AND_WARN_ONCE(query_error,
"mysql query failed: multiple result sets "
"returning data are not supported");
mysql_free_result(temp_res);
if ((temp_result = mysql_store_result(host->db)) != 0) {
if (first_result == 0) {
first_result = temp_result;
} else {
SET_ERROR_AND_WARN_ONCE(query_error,
"%s:%s: query failed: multiple result sets "
"returning data are not supported",
dict_mysql->dict.type,
dict_mysql->dict.name);
mysql_free_result(temp_result);
}
}
/*
* There must be no errors: mysql_field_count() must return 0
* to indicate that the "no data" result was expected.
* No result: the mysql_field_count() function must return 0
* to indicate that mysql_store_result() completed normally.
*/
else if (mysql_field_count(host->db) != 0) {
SET_ERROR_AND_WARN_ONCE(query_error,
"mysql query failed (mysql_field_count): %s",
"%s:%s: query failed (mysql_store_result): %s",
dict_mysql->dict.type,
dict_mysql->dict.name,
mysql_error(host->db));
}
/*
* Are there more results? -1 = no, 0 = yes, > 0 = error.
*/
if ((next_res_status = mysql_next_result(host->db)) > 0) {
SET_ERROR_AND_WARN_ONCE(query_error,
"%s:%s: query failed (mysql_next_result): %s",
dict_mysql->dict.type,
dict_mysql->dict.name,
mysql_error(host->db));
}
} while (next_res_status == 0);
/*
* Enforce the require_result_set setting.
*/
if (first_result == 0 && dict_mysql->require_result_set) {
SET_ERROR_AND_WARN_ONCE(query_error,
"%s:%s: query failed: query returned no result set"
"(require_result_set = yes)",
dict_mysql->dict.type,
dict_mysql->dict.name);
}
}
@ -609,13 +617,14 @@ static MYSQL_RES *plmysql_query(DICT_MYSQL *dict_mysql,
plmysql_down_host(host);
if (errno == 0)
errno = ENOTSUP;
if (res) {
mysql_free_result(res);
res = 0;
if (first_result) {
mysql_free_result(first_result);
first_result = 0;
}
} else {
if (msg_verbose)
msg_info("dict_mysql: successful query result from host %s",
msg_info("%s:%s: successful query result from host %s",
dict_mysql->dict.type, dict_mysql->dict.name,
host->hostname);
event_request_timer(dict_mysql_event, (void *) host,
IDLE_CONN_INTV);
@ -623,7 +632,8 @@ static MYSQL_RES *plmysql_query(DICT_MYSQL *dict_mysql,
}
}
return res;
*result = first_result;
return (query_error == 0);
}
/*
@ -717,6 +727,7 @@ static void mysql_parse_config(DICT_MYSQL *dict_mysql, const char *mysqlcf)
dict_mysql->tls_verify_cert = cfg_get_bool(p, "tls_verify_cert", -1);
#endif
#endif
dict_mysql->require_result_set = cfg_get_bool(p, "require_result_set", 1);
/*
* XXX: The default should be non-zero for safety, but that is not

View 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 "20161225"
#define MAIL_RELEASE_DATE "20161226"
#define MAIL_VERSION_NUMBER "3.2"
#ifdef SNAPSHOT

View File

@ -100,8 +100,8 @@ static const char *pcf_ldap_suffixes[] = {
static const char *pcf_mysql_suffixes[] = {
"additional_conditions", "dbname", "domain", "expansion_limit",
"hosts", "password", "query", "result_format", "select_field",
"table", "user", "where_field", 0,
"hosts", "password", "query", "result_format", "require_result_set",
"select_field", "table", "user", "where_field", 0,
};
/* See pgsql_table(5). */