Bug #72649 mysql_fetch_fields returns no array of MYSQL_FIELD under linux
Submitted: 14 May 2014 13:21 Modified: 4 Aug 2014 5:45
Reporter: Lyn Matten Email Updates:
Status: No Feedback Impact on me:
None 
Category:MySQL Server: C API (client library) Severity:S2 (Serious)
Version:5.5.34 OS:Linux (Ubuntu & Open Suse)
Assigned to: CPU Architecture:Any
Tags: array, MYSQL_FIELD

[14 May 2014 13:21] Lyn Matten
Description:
Calling mysql_fetch_field(MYSQL_RES *result) under Linux with actual mysql server version does not return an array of mysql_fields but only the first resultset.

Behavior seems to be the same as mysql_fetch_field.

Both have the same declaration:

MYSQL_FIELD *mysql_fetch_fields(MYSQL_RES *result)

MYSQL_FIELD *mysql_fetch_field(MYSQL_RES *result)

Under MAC OS X mysql_fetch_fields work as expected.

How to repeat:
Perform a SELECT over a table with several column.

Use MYSQL_RES *result to get all information about the fields:

Perform the example from the manual:

unsigned int num_fields;
unsigned int i;
MYSQL_FIELD *fields;

num_fields = mysql_num_fields(result);
fields = mysql_fetch_fields(result);
for(i = 0; i < num_fields; i++)
{
   printf("Field %u is %s\n", i, fields[i].name);
}

http://dev.mysql.com/doc/refman/5.0/en/mysql-fetch-fields.html

Program will stop with segementation fault for fields[i].name when i == 1.

Suggested fix:
Not sure why this works under MAC OS X. 

From my perspective the declaration should be an array over MYSQL_FIELD:

MYSQL_FIELD **mysql_fetch_fields(MYSQL_RES *result)
[4 Jul 2014 5:45] MySQL Verification Team
Hello Lyn,

Thank you for the report.
I could not repeat this on OL6 ad with 5.5.38/5.6.20.
Could you please provide complete repeatable test script(c script, schema, exact command used for compiling etc)?

Thanks,
Umesh
[4 Jul 2014 6:10] MySQL Verification Team
//

[root@cluster-repo mysql-5.5.38]# more bug72649.c
#include <stdlib.h>
#include <stdio.h>

#include <mysql.h>

int main(int argc, char **argv)
{
  MYSQL *mysql = NULL;

  mysql = mysql_init(mysql);

  if (!mysql) {
    puts("Init faild, out of memory?");
    return EXIT_FAILURE;
  }

  if (!mysql_real_connect(mysql, 
                          "localhost", 
                          "root", 
                          "",  
                          "test", 
                          0,     
                          "/tmp/mysql.sock",    
                          CLIENT_FOUND_ROWS  )) {
    puts("Connect failed\n");
  } else {
    mysql_query(mysql, "SET NAMES utf8");
    if (mysql_query(mysql, "SELECT id,name from  test.keyvalue LIMIT 4")) {
      printf("Query failed: %s\n", mysql_error(mysql));
    } else {
      MYSQL_RES *result = mysql_store_result(mysql);

      if (!result) {
        printf("Couldn't get results set: %s\n", mysql_error(mysql));
      } else {
        MYSQL_FIELD *fields;

        fields = mysql_fetch_fields(result);

        if (!fields) {
          printf("Faild fetching fields: %s\n", mysql_error(mysql));
        } else {
          unsigned int i, num_fields = mysql_num_fields(result);

          for (i = 0; i < num_fields; i++) {
            printf("FIELD #%d\n", i);
            printf("  %-20s %s\n", "Field name", fields[i].name);
#if MYSQL_VERSION_ID >= 40100
            printf("  %-20s %s\n", "Original name", fields[i].org_name);
#endif
            printf("  %-20s %s\n", "From table", fields[i].table);
            printf("  %-20s %s\n", "Original name", fields[i].org_table);
            printf("  %-20s %s\n", "Database", fields[i].db);
#if MYSQL_VERSION_ID >= 40100
            printf("  %-20s %s\n", "Catalog", fields[i].catalog);
#endif
            printf("  %-20s %s\n", "Default", fields[i].def);
            printf("  %-20s %lu\n", "CREATE field length", fields[i].length);
            printf("  %-20s %lu\n", "MAX field lengt", fields[i].max_length);
#if MYSQL_VERSION_ID >= 40100
            printf("  %-20s %u\n", "Field name length", fields[i].name_length);
            printf("  %-20s %u\n", "Original name length", fields[i].org_name_length);
            printf("  %-20s %u\n", "Table name length", fields[i].table_length);
            printf("  %-20s %u\n", "Original name length", fields[i].org_table_length);
            printf("  %-20s %u\n", "DB name length", fields[i].db_length);
            printf("  %-20s %u\n", "Catalog name length", fields[i].catalog_length);
            printf("  %-20s %u\n", "Default length", fields[i].def_length);
#endif
            /* TODO: decimals */
            printf("\n");
          }
        }
      }
    }
  }

  mysql_close(mysql);

  return EXIT_SUCCESS;
}

// 5.6
[root@cluster-repo mysql-advanced-5.6.20]# gcc bug72649.c -Wall -g -o bug72649 -L /data/ushastry/server/mysql-advanced-5.6.20/lib/ -I /data/ushastry/server/mysql-advanced-5.6.20/include/ -lmysqlclient_r -lz -lm
[root@cluster-repo mysql-advanced-5.6.20]# ./bug72649
FIELD #0
  Field name           id
  Original name        id
  From table           keyvalue
  Original name        keyvalue
  Database             test
  Catalog              def
  Default              (null)
  CREATE field length  20
  MAX field lengt      1
  Field name length    2
  Original name length 2
  Table name length    8
  Original name length 8
  DB name length       4
  Catalog name length  3
  Default length       0

FIELD #1
  Field name           name
  Original name        name
  From table           keyvalue
  Original name        keyvalue
  Database             test
  Catalog              def
  Default              (null)
  CREATE field length  750
  MAX field lengt      32
  Field name length    4
  Original name length 4
  Table name length    8
  Original name length 8
  DB name length       4
  Catalog name length  3
  Default length       0

// 5.5.38

[root@cluster-repo mysql-5.5.38]# gcc bug72649.c -Wall -g -o bug72649 -L /data/ushastry/server/mysql-5.5.38/lib/ -I /data/ushastry/server/mysql-5.5.38/include/ -lmysqlclient_r -lz -lm
[root@cluster-repo mysql-5.5.38]# ./bug72649
FIELD #0
  Field name           id
  Original name        id
  From table           keyvalue
  Original name        keyvalue
  Database             test
  Catalog              def
  Default              (null)
  CREATE field length  20
  MAX field lengt      1
  Field name length    2
  Original name length 2
  Table name length    8
  Original name length 8
  DB name length       4
  Catalog name length  3
  Default length       0

FIELD #1
  Field name           name
  Original name        name
  From table           keyvalue
  Original name        keyvalue
  Database             test
  Catalog              def
  Default              (null)
  CREATE field length  750
  MAX field lengt      32
  Field name length    4
  Original name length 4
  Table name length    8
  Original name length 8
  DB name length       4
  Catalog name length  3
  Default length       0
[5 Aug 2014 1:00] Bugs System
No feedback was provided for this bug for over a month, so it is
being suspended automatically. If you are able to provide the
information that was originally requested, please do so and change
the status of the bug back to "Open".