70.笔记 MySQL学习——C编写MySQL程序三出错处理和命令选项处理

来源:互联网 发布:淘宝超过三个月 编辑:程序博客网 时间:2024/06/05 07:30

70.笔记 MySQL学习——C编写MySQL程序三出错处理和命令选项处理

只要调用的MSYQL函数会失败,对它进行错误检查就是重要的。

错误处理

MYSQL客户端开发库里那些带有返回值的例程,通常会返回值是指针还是整数,来表明执行是否成功。

若返回非NULL指针,则表示成功,若返回NULL表示失败。

返回整数值的函数,通常是返回0表示成功,返回非零值表示失败。

并非所有API调用都有返回值,例如mysql_close就没有返回值。

           如果调用失败,可以通过API的3个函数来查明原因:

Mysql_error()返回一个包含出错消息的字符串

Mysql_errno()返回一个mysql特有的数字出错代码

Mysql_sqlstate返回一个SQLSTATE代码。

通过print_error函数会调用这3个函数,输出出错消息。

选项文件

           如果要从选项文件读取连接参数值,可以调用load_defaults。此函数会查找选项文件,解析其内容。

代码如下:

#include <my_global.h>

#include <my_sys.h>

#include <mysql.h>

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

int

main (int argc, char *argv[])

{

int i;

  printf("Original argument vector:\n");

  for (i = 0; i< argc; i++)

    printf("arg %d: %s\n", i, argv[i]);

 

  MY_INIT(argv[0]);

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

 

  printf("Modified argument vector:\n");

  for (i = 0; i< argc; i++)

    printf("arg %d: %s\n", i, argv[i]);

  exit (0);

}

l  代码解释

其中client_groups[]是一个字符串数组,存放从中获得选项的那些选项文件组的名字

Load_defaults用于读取选项文件,有4个参数:选项文件名的前缀、选项组名的数组,程序的参数计数器和向量的地址。不要直接传递计数器和向量的值。要传递它们的地址。

l  测试

如果想看load_defaults工作情况,在主目录下有一个名为/etc/my.cnf的文件,且client选项组里有一些选项。如下:

# cat.my.cnf

[client]

user=sampadmn

执行如下:

#./a.out  a b

Originalargument vector:

arg 0:./a.out

arg 1: a

arg 2: b

Modifiedargument vector:

arg 0:./a.out

arg 1:--user=test

arg 2: a

arg 3: b

如果想得到环境变量,必须使用getenv函数自己动手获取。

处理命令行参数

Load_defaults可以把所有参数都放到参数向量里,handle_options函数可以处理向量。

可以实现:

精确规范和法制的选项类型和取值范围

集成了帮助文本

提供了对标准选项—no-defaults,--print-defaults,--defaults-file和—defaults-extra-file的内建支持

支持标准的选项前缀,如—disable-,--enabled-和—loose-

实例程序如下:

#include<my_global.h>

#include<my_sys.h>

#include<mysql.h>

#include<my_getopt.h>

 

staticchar *opt_host_name = NULL;    /* serverhost (default=localhost) */

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

staticchar *opt_password = NULL;     /*password (default=none) */

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

staticchar *opt_socket_name = NULL;  /* socketname (use built-in value) */

 

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

 

staticstruct my_option my_opts[] =   /* optioninformation structures */

{

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

  NULL, NULL, NULL,

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

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

  (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', "Portnumber",

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

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

  {"socket", 'S', "Socketpath",

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

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

  {"user", 'u', "Username",

  (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 }

};

 

/* #@_GET_ONE_OPTION_ */

staticmy_bool

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

{

  switch (optid)

  {

  case '?':

    my_print_help (my_opts);  /* print help message */

    exit (0);

  }

  return (0);

}

/* #@_GET_ONE_OPTION_ */

 

int

main (intargc, char *argv[])

{

int i;

intopt_err;

 

  printf ("Original connectionparameters:\n");

  printf ("hostname: %s\n",opt_host_name ? opt_host_name : "(null)");

  printf ("username: %s\n",opt_user_name ? opt_user_name : "(null)");

  printf ("password: %s\n",opt_password ? opt_password : "(null)");

  printf ("port number: %u\n",opt_port_num);

  printf("socket filename: %s\n",

          opt_socket_name ? opt_socket_name :"(null)");

 

  printf ("Original argumentvector:\n");

  for (i = 0; i < argc; i++)

    printf ("arg %d: %s\n", i,argv[i]);

 

  MY_INIT (argv[0]);

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

 

  printf ("Argument vector after callingload_defaults():\n");

  for (i = 0; i < argc; i++)

    printf ("arg %d: %s\n", i,argv[i]);

 

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

    exit (opt_err);

 

  printf ("Connection parameters aftercalling handle_options():\n");

  printf ("hostname: %s\n",opt_host_name ? opt_host_name : "(null)");

  printf ("username: %s\n",opt_user_name ? opt_user_name : "(null)");

  printf ("password: %s\n",opt_password ? opt_password : "(null)");

  printf ("port number: %u\n",opt_port_num);

  printf ("socket filename: %s\n",

          opt_socket_name ? opt_socket_name :"(null)");

 

  printf ("Argument vector after callinghandle_options():\n");

  for (i = 0; i < argc; i++)

    printf ("arg %d: %s\n", i,argv[i]);

 

  exit (0);

}

l  代码解释

My_getopt.h文件定义了选项处理例程的接口

其中my_option结构的数组定义了一些必需的信息类型,为程序所能解读的每一个选项指定。

其中my_print_help函数是客户端开发库例程,根据my_opts数组里的选项名和注释串自动生成一条帮助信息。

l  测试

执行如下:

# ./a.out

Original connection parameters:

hostname: (null)

username: (null)

password: (null)

port number: 0

socket filename: (null)

Original argument vector:

arg 0: ./a.out

Argument vector after callingload_defaults():

arg 0: ./a.out

arg 1: --user=test

Connection parameters after callinghandle_options():

hostname: (null)

username: test

password: (null)

port number: 0

socket filename: (null)

Argument vector after callinghandle_options():

加入参数执行如下:

# ./a.out -h host2 --user=bill z

Original connection parameters:

hostname: (null)

username: (null)

password: (null)

port number: 0

socket filename: (null)

Original argument vector:

arg 0: ./a.out

arg 1: -h

arg 2: host2

arg 3: --user=bill

arg 4: z

Argument vector after callingload_defaults():

arg 0: ./a.out

arg 1: --user=test

arg 2: -h

arg 3: host2

arg 4: --user=bill

arg 5: z

Connection parameters after callinghandle_options():

hostname: host2

username: bill

password: (null)

port number: 0

socket filename: (null)

Argument vector after callinghandle_options():

arg 0: z

# ./a.out --help

Original connection parameters:

hostname: (null)

username: (null)

password: (null)

port number: 0

socket filename: (null)

Original argument vector:

arg 0: ./a.out

arg 1: --help

Argument vector after callingload_defaults():

arg 0: ./a.out

arg 1: --user=test

arg 2: --help

  -?,--help          Display this help andexit

  -h,--host=name     Host to connect to

  -p,--password[=name]

                      Password

  -P,--port=#        Port number

  -S,--socket=name   Socket path

  -u,--user=name     User name

选项处理合并客户端

代码如下:

#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 }

};

 

/* #@ _PRINT_ERROR_ */

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));

  }

}

/* #@ _PRINT_ERROR_ */

 

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);

}

 

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);

  }

 

/* #@ _INIT_CONNECT_ */

  /* 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);

  }

/* #@ _INIT_CONNECT_ */

 

  /* ... issuestatements and process results here ... */

 

  /* disconnectfrom server, terminate client library */

  mysql_close(conn);

 mysql_library_end ();

  exit (0);

}

允许命令行参数方式指定默认数据库

如果密码输入在参数向量里,get_one_option将复制它,并会改写,防止被PS等程序看到

如果只给出密码选项,则提示输入密码

l  测试

运行如下:

# ./a.out  -h192.168.1.200 -u root -p

Enter password:

也可以连接到远程的服务器上,如:

# ./a.out  -h192.168.1.3 -u root -p

Enter password:

PS:需要增加权限> grant allprivileges on *.* to 'root'@'%' identified by 'passsword' with grant option;

关于编译

使用如下脚本

gcc `mysql_config --include` `mysql_config --libs` $1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

阅读全文
0 0
原创粉丝点击