Bug #88878 mysqldump poorly outputs gtid purged
Submitted: 12 Dec 2017 15:01 Modified: 13 Dec 2017 9:43
Reporter: Trey Raymond Email Updates:
Status: Verified Impact on me:
None 
Category:MySQL Server: mysqldump Command-line Client Severity:S3 (Non-critical)
Version:5.7.20 OS:Any
Assigned to: CPU Architecture:Any

[12 Dec 2017 15:01] Trey Raymond
Description:
https://github.com/mysql/mysql-server/blob/5.7/client/mysqldump.c#L5696-L5705

this code outputs the values on separate lines, i.e.:

SET @@GLOBAL.GTID_PURGED='0a957e3f-36ec-11e5-b3a9-90b11c23336d:1-1302380655,
580ad872-e2bd-11e6-9963-90b11c23336d:1-14415080,
a7879d33-3f43-11e5-aa0f-90b11c2589f1:1-29302014,
a9731db7-de82-11e6-bdcf-90b11c23336d:1-548';

Not only does this deviate from the de facto standard used by all other SET lines, it makes scripts using dumps that use grep or sed unnecessarily complicated.

How to repeat:
mysqldump on a gtid enabled server with default settings

Suggested fix:
The value should be output all on the same line, as one would expect.
[12 Dec 2017 15:19] Trey Raymond
It looks like the code was originally going to output them on one line, but the entire FOR loop gets skipped, as mysql_num_rows will always be 1.
The bug here is that it expects each line to be a new row, when in fact it's a string with newlines in a single row.  without the loop running, the line
fprintf(md_result_file,"%s';\n", (char*)gtid_set[0]);
outputs the whole value, newlines and all.
[12 Dec 2017 15:24] Trey Raymond
this should work:

static my_bool add_set_gtid_purged(MYSQL *mysql_con)
{
  MYSQL_RES  *gtid_purged_res;
  MYSQL_ROW  gtid_set;
  ulonglong  num_sets, idx;

  /* query to get the GTID_EXECUTED */
  if (mysql_query_with_error_report(mysql_con, &gtid_purged_res,
                  "SELECT replace(@@GLOBAL.GTID_EXECUTED,'\n','')"))
    return TRUE;

  /* Proceed only if gtid_purged_res is non empty */
  if ((num_sets= mysql_num_rows(gtid_purged_res)) > 0)
  {
    if (opt_comments)
      fprintf(md_result_file,
          "\n--\n-- GTID state at the beginning of the backup \n--\n\n");

    fprintf(md_result_file,"SET @@GLOBAL.GTID_PURGED='");

    gtid_set= mysql_fetch_row(gtid_purged_res);
    /* close the SET expression */
    fprintf(md_result_file,"%s';\n", (char*)gtid_set[0]);
  }
  mysql_free_result(gtid_purged_res);

  return FALSE;  /*success */
}
[12 Dec 2017 15:26] Trey Raymond
changing to s3 as the code existing is not actually working, so it's a bug, not a feature req
[13 Dec 2017 9:43] MySQL Verification Team
Hello Trey Raymond,

Thank you for the report and feedback.

Thanks,
Umesh