73.笔记 MySQL学习——C编写MySQL程序六交互式语句执行

时间:2022-03-23 00:14:46

73.笔记 MySQL学习——C编写MySQL程序六交互式语句执行

本节实现一个简单的交互式语句执行客户端程序。

在connect2.c代码上进行加工。

代码如下:

l  exec_stmt.c

#include <my_global.h>

#include <my_sys.h>

#include <m_string.h>   /* for strdup() */

#include <mysql.h>

#include <my_getopt.h>

 

static char *opt_host_name = NULL;    /* server host (default=localhost) */

static char *opt_user_name = NULL;    /* username (default=login name) */

static char *opt_password = NULL;     /* password (default=none) */

static unsigned int opt_port_num = 0; /* port number(use built-in value) */

static char *opt_socket_name = NULL;  /* socket name (use built-in value) */

static char *opt_db_name = NULL;      /* database name (default=none) */

static unsigned int opt_flags = 0;    /* connection flags (none) */

 

static int ask_password = 0;          /* whether to solicit password */

 

static MYSQL *conn;                   /* pointer to connectionhandler */

 

static const char *client_groups[] = {"client", NULL };

 

static struct my_option my_opts[] =   /* option information structures */

{

 {"help", '?', "Display this help and exit",

  NULL, NULL,NULL,

  GET_NO_ARG,NO_ARG, 0, 0, 0, 0, 0, 0},

 {"host", 'h', "Host to connect to",

  (uchar **)&opt_host_name, NULL, NULL,

  GET_STR,REQUIRED_ARG, 0, 0, 0, 0, 0, 0},

 {"password", 'p', "Password",

  (uchar **)&opt_password, NULL, NULL,

  GET_STR,OPT_ARG, 0, 0, 0, 0, 0, 0},

 {"port", 'P', "Port number",

  (uchar **)&opt_port_num, NULL, NULL,

  GET_UINT,REQUIRED_ARG, 0, 0, 0, 0, 0, 0},

 {"socket", 'S', "Socket path",

  (uchar **)&opt_socket_name, NULL, NULL,

  GET_STR,REQUIRED_ARG, 0, 0, 0, 0, 0, 0},

 {"user", 'u', "User name",

  (uchar **)&opt_user_name, NULL, NULL,

  GET_STR,REQUIRED_ARG, 0, 0, 0, 0, 0, 0},

  { NULL, 0,NULL, NULL, NULL, NULL, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }

};

 

/*

 * Printdiagnostic message. If conn is non-NULL, print error information

 * returned byserver.

 */

 

static void

print_error (MYSQL *conn, char *message)

{

  fprintf(stderr, "%s\n", message);

  if (conn !=NULL)

  {

    fprintf(stderr, "Error %u (%s): %s\n",

            mysql_errno (conn), mysql_sqlstate (conn), mysql_error (conn));

  }

}

 

static my_bool

get_one_option (int optid, const struct my_option*opt, char *argument)

{

  switch(optid)

  {

  case '?':

   my_print_help (my_opts);  /* printhelp message */

    exit (0);

  case'p':                   /* password */

    if(!argument)            /* no value given;solicit it later */

     ask_password = 1;

    else                      /* copy password,overwrite original */

    {

     opt_password = strdup (argument);

      if(opt_password == NULL)

      {

       print_error (NULL, "could not allocate password buffer");

        exit(1);

      }

      while(*argument)

       *argument++ = 'x';

     ask_password = 0;

    }

    break;

  }

  return (0);

}

 

#include "process_result_set.c"

 

#include "process_statement.c"

 

int

main (int argc, char *argv[])

{

int opt_err;

 

  MY_INIT(argv[0]);

  load_defaults("my", client_groups, &argc, &argv);

 

  if ((opt_err= handle_options (&argc, &argv, my_opts, get_one_option)))

    exit(opt_err);

 

  /* solicitpassword if necessary */

  if(ask_password)

   opt_password = get_tty_password (NULL);

 

  /* getdatabase name if present on command line */

  if (argc >0)

  {

    opt_db_name= argv[0];

    --argc;++argv;

  }

 

  /* initializeclient library */

  if(mysql_library_init (0, NULL, NULL))

  {

    print_error(NULL, "mysql_library_init() failed");

    exit (1);

  }

 

  /* initializeconnection handler */

  conn =mysql_init (NULL);

  if (conn ==NULL)

  {

    print_error(NULL, "mysql_init() failed (probably out of memory)");

    exit (1);

  }

 

  /* connect toserver */

  if(mysql_real_connect (conn, opt_host_name, opt_user_name, opt_password,

     opt_db_name, opt_port_num, opt_socket_name, opt_flags) == NULL)

  {

    print_error(conn, "mysql_real_connect() failed");

    mysql_close(conn);

    exit (1);

  }

 

/* #@ _MAIN_LOOP_ */

  while (1)

  {

    char  buf[10000];

 

    fprintf(stderr, "query> ");                  /* print prompt */

    if (fgets(buf, sizeof (buf), stdin) == NULL) /* read statement */

      break;

    if (strcmp(buf, "quit\n") == 0 || strcmp (buf, "\\q\n") == 0)

      break;

   process_statement (conn, buf);                /* execute it */

  }

/* #@ _MAIN_LOOP_ */

 

  /* disconnectfrom server, terminate client library */

  mysql_close(conn);

 mysql_library_end ();

  exit (0);

}

l  process_result_set.c

void

print_dashes (MYSQL_RES *res_set)

{

MYSQL_FIELD  *field;

unsigned int i, j;

 

 mysql_field_seek (res_set, 0);

  fputc ('+',stdout);

  for (i = 0; i< mysql_num_fields (res_set); i++)

  {

    field =mysql_fetch_field (res_set);

    for (j = 0;j < field->max_length + 2; j++)

      fputc('-', stdout);

    fputc ('+',stdout);

  }

  fputc ('\n',stdout);

}

 

void

process_result_set (MYSQL *conn, MYSQL_RES *res_set)

{

MYSQL_ROW    row;

/* #@ _COL_WID_CALC_VARS_ */

MYSQL_FIELD  *field;

unsigned long col_len;

unsigned int i;

/* #@ _COL_WID_CALC_VARS_ */

 

/* #@ _COL_WID_CALCULATIONS_ */

  /* determinecolumn display widths; requires result set to be */

  /* generatedwith mysql_store_result(), not mysql_use_result() */

 mysql_field_seek (res_set, 0);

  for (i = 0; i< mysql_num_fields (res_set); i++)

  {

    field =mysql_fetch_field (res_set);

    col_len =strlen (field->name);

    if (col_len< field->max_length)

      col_len =field->max_length;

    if (col_len< 4 && !IS_NOT_NULL (field->flags))

      col_len =4;  /* 4 = length of the word"NULL" */

   field->max_length = col_len; /* reset column info */

  }

/* #@ _COL_WID_CALCULATIONS_ */

 

  print_dashes(res_set);

  fputc ('|',stdout);

 mysql_field_seek (res_set, 0);

  for (i = 0; i< mysql_num_fields (res_set); i++)

  {

    field =mysql_fetch_field (res_set);

/* #@ _PRINT_TITLE_ */

    printf(" %-*s |", (int) field->max_length, field->name);

/* #@ _PRINT_TITLE_ */

  }

  fputc ('\n',stdout);

  print_dashes(res_set);

 

  while ((row =mysql_fetch_row (res_set)) != NULL)

  {

   mysql_field_seek (res_set, 0);

    fputc ('|',stdout);

    for (i = 0;i < mysql_num_fields (res_set); i++)

    {

      field =mysql_fetch_field (res_set);

/* #@ _PRINT_ROW_VAL_ */

      if(row[i] == NULL)       /* print the word"NULL" */

        printf(" %-*s |", (int) field->max_length, "NULL");

      else if(IS_NUM (field->type))  /* print valueright-justified */

        printf(" %*s |", (int) field->max_length, row[i]);

      else              /* print value left-justified */

        printf(" %-*s |", (int) field->max_length, row[i]);

/* #@ _PRINT_ROW_VAL_ */

    }

    fputc('\n', stdout);

  }

  print_dashes(res_set);

  printf("Number of rows returned: %lu\n",

         (unsigned long) mysql_num_rows (res_set));

}

l  process_statement.c

void

process_statement (MYSQL *conn, char *stmt_str)

{

MYSQL_RES *res_set;

 

  if(mysql_query (conn, stmt_str) != 0)  /*the statement failed */

  {

    print_error(conn, "Could not execute statement");

    return;

  }

 

  /* thestatement succeeded; determine whether it returned data */

  res_set =mysql_store_result (conn);

  if(res_set)      /* a result set wasreturned */

  {

    /* processrows and free the result set */

   process_result_set (conn, res_set);

   mysql_free_result (res_set);

  }

  else              /* no result set was returned */

  {

    /*

     * does thelack of a result set mean that the statement didn't

     * returnone, or that it should have but an error occurred?

     */

    if(mysql_field_count (conn) == 0)

    {

      /*

       *statement generated no result set (it was not a SELECT,

       * SHOW,DESCRIBE, etc.); just report rows-affected value.

       */

      printf("Number of rows affected: %lu\n",

             (unsigned long) mysql_affected_rows (conn));

    }

    else  /* an error occurred */

    {

     print_error (conn, "Could not retrieve result set");

    }

  }

}

代码解释

总共3个文件,如上。

exec_stmt.c调用另外两个文件,如下:

#include "process_result_set.c"

#include "process_statement.c"

在主循环中,其他部件主要辅助的小TIPS,主要的是那个WHILE循环。

在WHILE循环中一直输出

Query>

接受输入后进行执行。主要是调用process_statement.c文件中的

process_statement函数,该函数调用mysql_query函数,使用mysql_store_result处理结果集。

process_statement函数会调用process_result_set.c文件中的process_result_set函数来处理结果输出。

 

执行

# ./a.out  -uroot

query> show databases;

+--------------------+

| Database           |

+--------------------+

| information_schema |

| mysql              |

| performance_schema |

| test               |

+--------------------+

Number of rows returned: 4

query> use test;

Number of rows affected: 0

query> show tables;

+----------------+

| Tables_in_test |

+----------------+

+----------------+

Number of rows returned: 0