C programming in MySQL

Have some C code that works on MySQL version 8.0 compiled with libmysqlclient-dev and for which I want to refactor the error messages on line 17 and 18:

// Compilation: gcc commerce.c -g -lm `mysql_config --cflags --libs` -Wall -o commerce
// Usage: ./commerce
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mysql/mysql.h>

#define FAIL_IF(EXP, MSG) ({ if (EXP) { printf(MSG "\n"); exit(EXIT_FAILURE); }})

int main (int argc, char *argv[]) {
  MYSQL *conn = mysql_init(NULL);
  FAIL_IF (conn == NULL, "mysql_init() failed\n");
  FAIL_IF (mysql_real_connect(conn, "localhost", "root", "obfuscated", "commerce", 0, NULL, 0) == NULL, "Connection cannot be established because of incorrect credentials");

  mysql_query(conn, "elect * from customers;");
  MYSQL_RES *result = mysql_store_result(conn);
  if (result == NULL) { printf("Error %d: %s\n", mysql_errno(conn), mysql_error(conn)); }
  FAIL_IF (result == NULL, "An error was encountered.");

  MYSQL_FIELD *field;

  // print column names
  printf("A total of %ld rows were returned with the following columns: ", mysql_num_rows(result));
  while ((field = mysql_fetch_field(result))) {
    printf("%s, ", field->name);
  }
  printf("\n");

  mysql_free_result(result);
  mysql_close(conn);
}

Note the deliberate typo in the query.
A test database has been created as follows:

create database commerce;
use commerce;
create table customers (id int);
insert into customers values (1000), (1001);

How do I refactor the error messages into a oneliner?:

  if (result == NULL) { printf("Error %d: %s\n", mysql_errno(conn), mysql_error(conn)); }
  FAIL_IF (result == NULL, "An error was encountered.");

I am looking for something like FAIL_IF (result == NULL, sprintf("Error %d: %s\n", mysql_errno(conn), mysql_error(conn)));

sprintf takes one more argument than printf: the first arg has to be a character buffer that is large enough to contain the longest message that the sprintf() can create.

It also does not return the address of the buffer, and I assume FAIL_IF requires a plain string (i.e. not a function call).

I would think you want to declare char FileMsg [100]; just below the main().

Then replace your two lines with these statements:

if (result == NULL) {
    sprintf(FileMsg, "Error %d: %s\n", mysql_errno(conn), mysql_error(conn));
    printf ("%s", FileMsg);
}
FAIL_IF (result == NULL, FileMsg);

This is never going to be a one-liner, because the stdout printf message and the FAIL_IF take different argument types. But it does only evaluate the message once.

Note I know nothing about MySql. This is just intuited from your example plus some C knowledge.

Agreed on the approach. It is still executing the same test twice: result == NULL, so I am also looking for something tidier.

That result == NULL test is very cheap, but it is untidy.

I don't know what restrictions may exist for MySql constructs within C. The FAIL_IF could possible be wrapped inside the C test, in which case you could pass it a constant true value (could be 1, or some predefined truthy value):

if (result == NULL) {
    sprintf(FileMsg, "Error %d: %s\n", mysql_errno(conn), mysql_error(conn));
    printf ("%s", FileMsg);
    FAIL_IF (TRUE, FileMsg);
}

Or there may be a direct FAIL() version that would always exit if the block was entered, like: FAIL (FileMsg);

In that case I will just drop the FAIL_IF macro call. I use it to quickly spot the error messages I have defined in my code. Hence it will be just the following:

if (result == NULL) { printf("Error %d: %s\n", mysql_errno(conn), mysql_error(conn)); }

in which case I dont need the additional variable FileMsg either. Thank you for your help.