⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 libmysql.c

📁 MySQL数据库的ODBC接口程序源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
					    sizeof(MYSQL_ROWS))) ||
	!(cur->data= ((MYSQL_ROW)
		      alloc_root(&result->alloc,
				     (fields+1)*sizeof(char *)+pkt_len))))
    {
      free_rows(result);
      net->last_errno=CR_OUT_OF_MEMORY;
      strmov(net->last_error,ER(net->last_errno));
      DBUG_RETURN(0);
    }
    *prev_ptr=cur;
    prev_ptr= &cur->next;
    to= (char*) (cur->data+fields+1);
    for (field=0 ; field < fields ; field++)
    {
      if ((len=net_field_length(&cp)) == NULL_LENGTH)
      {						/* null field */
	cur->data[field] = 0;
      }
      else
      {
	cur->data[field] = to;
	memcpy(to,(char*) cp,len); to[len]=0;
	to+=len+1;
	cp+=len;
	if (mysql_fields)
	{
	  if (mysql_fields[field].max_length < len)
	    mysql_fields[field].max_length=len;
	}
      }
    }
    cur->data[field]=to;			/* End of last field */
    if ((pkt_len=net_safe_read(mysql)) == packet_error)
    {
      free_rows(result);
      DBUG_RETURN(0);
    }
  }
  *prev_ptr=0;					/* last pointer is null */
  DBUG_PRINT("exit",("Got %d rows",result->rows));
  DBUG_RETURN(result);
}


/*
** Read one row. Uses packet buffer as storage for fields.
** When next package is read, the previous field values are destroyed
*/


static int
read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, uint *lengths)
{
  uint field,pkt_len,len;
  uchar *pos,*prev_pos;

  if ((pkt_len=(uint) net_safe_read(mysql)) == packet_error)
    return -1;
  if (pkt_len == 1 && mysql->net.buff[0] == 254)
    return 1;				/* End of data */
  prev_pos= 0;				/* allowed to write at packet[-1] */
  pos=mysql->net.buff;
  for (field=0 ; field < fields ; field++)
  {
    if ((len=net_field_length(&pos)) == NULL_LENGTH)
    {						/* null field */
      row[field] = 0;
      *lengths++=0;
    }
    else
    {
      row[field] = (char*) pos;
      pos+=len;
      *lengths++=len;
    }
    if (prev_pos)
      *prev_pos=0;				/* Terminate prev field */
    prev_pos=pos;
  }
  row[field]=(char*) prev_pos+1;		/* End of last field */
  *prev_pos=0;					/* Terminate last field */
  return 0;
}


/**************************************************************************
** Connect to sql server
** If host == 0 then use localhost
**************************************************************************/

MYSQL * STDCALL
mysql_connect(MYSQL *mysql,const char *host,
	      const char *user, const char *passwd)
{
  return mysql_real_connect(mysql,host,user,passwd,NullS,0,NullS,0);
}


MYSQL * STDCALL
mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
		   const char *passwd, const char *db,
		   uint port, const char *unix_socket,uint client_flag)
{
  char		buff[100],scramble_buff[9],*end,*host_info;
  int		sock;
  ulong		ip_addr;
  struct	sockaddr_in sock_addr;
  uint		pkt_length;
  NET		*net;
#ifndef MSDOS
  char		*env;
  int		opt;
  struct servent *serv_ptr;
#endif

#ifdef HAVE_SYS_UN_H
  struct	sockaddr_un UNIXaddr;
#endif
  DBUG_ENTER("mysql_connect");

#ifndef DONT_USE_MYSQL_PWD
  if (!passwd)
    passwd=getenv("MYSQL_PWD");  /* read Password from environment (haneke) */
#endif
  if (!mysql_client_init)
  {
    mysql_client_init=1;
    my_init();
    init_client_errs();
    if (!mysql_port)
    {
      mysql_port = MYSQL_PORT;
#ifndef MSDOS
      if ((serv_ptr = getservbyname("mysql", "tcp")))
	mysql_port = (uint) ntohs((ushort) serv_ptr->s_port);
      if ((env = getenv("MYSQL_TCP_PORT")))
	mysql_port =(uint) atoi(env);
#endif
    }
#ifndef MSDOS
    if (!mysql_unix_port)
    {
      mysql_unix_port = MYSQL_UNIX_ADDR;
      if ((env = getenv("MYSQL_UNIX_PORT")))
	mysql_unix_port = env;
    }
#endif
    mysql_debug(NullS);
  }

  DBUG_PRINT("enter",("host: %s  db: %s",host ? host : "(Null)",
		      db ? db : "(Null)"));
  if (!mysql)
  {
    if (!(mysql=(MYSQL*) my_malloc(sizeof(*mysql),MYF(MY_WME | MY_ZEROFILL))))
      DBUG_RETURN(0);
    mysql->free_me=1;
  }
  else
    bzero(mysql,sizeof(*mysql));
  remember_connection(mysql);
  mysql->reconnect=1;			/* Reconnect as default */
  net= &mysql->net;
  net->fd= -1;				/* If something goes wrong */
  if (!host && !(host=getenv("MYSQL_HOST")) || !host[0])
    host=LOCAL_HOST;

  /*
  ** Grab a socket and connect it to the server
  */

#ifdef HAVE_SYS_UN_H
  if (!strcmp(host,LOCAL_HOST) && (unix_socket || mysql_unix_port))
  {
    if (!unix_socket)
      unix_socket=mysql_unix_port;
    host_info=ER(CR_LOCALHOST_CONNECTION);
    DBUG_PRINT("info",("Using UNIX sock '%s'",unix_socket));
    if ((sock = socket(AF_UNIX,SOCK_STREAM,0)) == SOCKET_ERROR)
    {
      net->last_errno=CR_SOCKET_CREATE_ERROR;
      strmov(net->last_error,ER(net->last_errno));
      goto error;
    }
    net->fd=sock;
    opt = 1;
    (void) setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&opt,
		      sizeof(opt));

    bzero(&UNIXaddr,sizeof(UNIXaddr));
    UNIXaddr.sun_family = AF_UNIX;
    strmov(UNIXaddr.sun_path, unix_socket);
    if (connect(sock,(struct sockaddr *) &UNIXaddr, sizeof(UNIXaddr)) <0)
    {
      DBUG_PRINT("error",("Got error %d on connect to local server",ERRNO));
      net->last_errno=CR_CONNECTION_ERROR;
      strmov(net->last_error,ER(net->last_errno));
      goto error;
    }
  }
  else
#endif
  {
    if (!port)
      port=mysql_port;
    sprintf(host_info=buff,ER(CR_TCP_CONNECTION),host);
    DBUG_PRINT("info",("Server name: '%s'.  TCP sock: %d", host,port));
    if ((sock = socket(AF_INET,SOCK_STREAM,0)) == SOCKET_ERROR)
    {
      net->last_errno=CR_IPSOCK_ERROR;
      strmov(net->last_error,ER(net->last_errno));
      goto error;
    }
    net->fd=sock;
#ifndef MSDOS
    opt = 1;
    (void) setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&opt,
		      sizeof(opt));
#endif
    bzero(&sock_addr,sizeof(sock_addr));
    sock_addr.sin_family = AF_INET;

    /*
    ** The server name may be a host name or IP address
    */

    if ((int) (ip_addr = inet_addr(host)) != (int) INADDR_NONE)
    {
      memcpy(&sock_addr.sin_addr,&ip_addr,sizeof(ip_addr));
    }
    else
#if defined(HAVE_GETHOSTBYNAME_R) && defined(_REENTRANT) && defined(THREAD)
    {
      int tmp_errno;
      struct hostent tmp_hostent,*hp;
      char buff2[2048];
      hp = gethostbyname_r(host,&tmp_hostent,buff2,sizeof(buff2),&tmp_errno);
      if (!hp)
      {
	net->last_errno=CR_UNKNOWN_HOST;
	sprintf(net->last_error, ER(CR_UNKNOWN_HOST), host, tmp_errno);
	goto error;
      }
      memcpy(&sock_addr.sin_addr,hp->h_addr, (size_t) hp->h_length);
    }
#else
    {
      struct hostent *hp;
      if (!(hp=gethostbyname(host)))
      {
	net->last_errno=CR_UNKNOWN_HOST;
	sprintf(net->last_error, ER(CR_UNKNOWN_HOST), host, errno);
	goto error;
      }
      memcpy(&sock_addr.sin_addr,hp->h_addr, (size_t) hp->h_length);
    }
#endif
    sock_addr.sin_port = (ushort) htons((u_short) port);
    if (connect(sock,(struct sockaddr *) &sock_addr, sizeof(sock_addr))<0)
    {
      DBUG_PRINT("error",("Got error %d on connect to '%s'",ERRNO,host));
      net->last_errno= CR_CONN_HOST_ERROR;
      sprintf(net->last_error ,ER(CR_CONN_HOST_ERROR), host, ERRNO);
      goto error;
    }
  }

#if defined(SIGPIPE)
  (void) signal(SIGPIPE,SIG_IGN);
#endif
  DBUG_PRINT("info",("Connection socket %d",sock));
  if (my_net_init(net,sock))
    goto error;
  /* Get version info */
  mysql->protocol_version= PROTOCOL_VERSION;	/* Assume this */
  if ((pkt_length=net_safe_read(mysql)) == packet_error)
    goto error;

  /* Check if version of protocoll matches current one */

  mysql->protocol_version= net->buff[0];
  DBUG_DUMP("packet",(char*) net->buff,10);
  DBUG_PRINT("info",("mysql protocol version %d, server=%d",
		     PROTOCOL_VERSION, mysql->protocol_version));
  if (mysql->protocol_version != PROTOCOL_VERSION &&
      mysql->protocol_version != PROTOCOL_VERSION-1)
  {
    net->last_errno= CR_VERSION_ERROR;
    sprintf(net->last_error, ER(CR_VERSION_ERROR), mysql->protocol_version,
	    PROTOCOL_VERSION);
    goto error;
  }
  end=strend((char*) net->buff+1);
  mysql->thread_id=uint4korr(end+1);
  end+=5;
  strmov(scramble_buff,end);
  if (pkt_length > (uint) (end+9 - (char*) net->buff))
    mysql->server_capabilities=uint2korr(end+9);

  /* Save connection information */
  if (!user) user="";
  if (!passwd) passwd="";
  if (!my_multi_malloc(MYF(0),
		      &mysql->host_info,strlen(host_info)+1,
		      &mysql->host,strlen(host)+1,
		      &mysql->user,strlen(user)+1,
		      &mysql->passwd,strlen(passwd)+1,
		      &mysql->unix_socket,unix_socket ? strlen(unix_socket)+1
		      :1,
		      &mysql->server_version,(uint) (end - (char*) net->buff),
		      NullS))
  {
    strmov(net->last_error, ER(net->last_errno=CR_OUT_OF_MEMORY));
    goto error;
  }
  strmov(mysql->host_info,host_info);
  strmov(mysql->host,host);
  strmov(mysql->user,user);
  strmov(mysql->passwd,passwd);
  if (unix_socket)
    strmov(mysql->unix_socket,unix_socket);
  else
    mysql->unix_socket=0;
  strmov(mysql->server_version,(char*) net->buff+1);
  mysql->port=port;
  mysql->client_flag=client_flag;
  DBUG_PRINT("info",("Server version = '%s'",mysql->server_version));

  /* Send client information for access check */
  client_flag|=CLIENT_CAPABILITIES;
  if (db)
    client_flag|=CLIENT_CONNECT_WITH_DB;
  int2store(buff,client_flag);
  int3store(buff+2,max_allowed_packet);
  if (user && user[0])
    strmake(buff+5,user,32);
  else
    read_user_name((char*) buff+5);
  DBUG_PRINT("info",("user: %s",buff+5));
  end=scramble(strend(buff+5)+1, scramble_buff, passwd,
	       (my_bool) (mysql->protocol_version == 9));
  if (db && (mysql->server_capabilities & CLIENT_CONNECT_WITH_DB))
  {
    end=strmov(end+1,db);
    mysql->db=my_strdup(db,MYF(MY_WME));
    db=0;
  }
  if (my_net_write(net,buff,(uint) (end-buff)) || net_flush(net) ||
      net_safe_read(mysql) == packet_error)
    goto error;
  if (db && mysql_select_db(mysql,db))
    goto error;
  DBUG_PRINT("exit",("Mysql handler: %lx",mysql));
  DBUG_RETURN(mysql);

error:
  DBUG_PRINT("error",("message: %u (%s)",net->last_errno,net->last_error));
  end_server(mysql);
  if (mysql->free_me)
    my_free((gptr) mysql,MYF(0));
  DBUG_RETURN(0);
}


/**************************************************************************
** Set current database
**************************************************************************/

int STDCALL
mysql_select_db(MYSQL *mysql, const char *db)
{
  int error;
  DBUG_ENTER("mysql_select_db");
  DBUG_PRINT("enter",("db: '%s'",db));

  if ((error=simple_command(mysql,COM_INIT_DB,db,strlen(db),0)))
    DBUG_RETURN(error);
  my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR));
  mysql->db=my_strdup(db,MYF(MY_WME));
  DBUG_RETURN(0);
}


/*************************************************************************
** Send a QUIT to the server and close the connection
** If handle is alloced by mysql connect free it.
*************************************************************************/

void STDCALL
mysql_close(MYSQL *mysql)
{
  DBUG_ENTER("mysql_close");
  if (mysql)					/* Some simple safety */
  {
    if (mysql->net.fd >= 0)
    {
      free_old_query(mysql);
      mysql->status=MYSQL_STATUS_READY; /* Force command */
      simple_command(mysql,COM_QUIT,NullS,0,1);
      end_server(mysql);
    }
    my_free((gptr) mysql->host_info,MYF(MY_ALLOW_ZERO_PTR));
    my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR));
    mysql->host_info=mysql->db=0;
    if (mysql->free_me)
      my_free((gptr) mysql,MYF(0));
  }
  DBUG_VOID_RETURN;
}


/**************************************************************************
** Do a query. If query returned rows, free old rows.
** Read data by mysql_store_result or by repeat call of mysql_fetch_row
**************************************************************************/

int STDCALL
mysql_query(MYSQL *mysql, const char *query)
{
  return mysql_real_query(mysql,query,strlen(query));
}


int STDCALL
mysql_real_query(MYSQL *mysql, const char *query,uint length)
{
  uchar *pos;
  uint field_count;
  MYSQL_DATA *fields;
  DBUG_ENTER("mysql_real_query");
  DBUG_PRINT("enter",("handle: %lx",mysql));
  DBUG_PRINT("query",("Query = \"%s\"",query));

  if (simple_command(mysql,COM_QUERY,query,length,1) ||
      (length=net_safe_read(mysql)) == packet_error)
    DBUG_RETURN(-1);
  free_old_query(mysql);			/* Free old result */
  pos=(uchar*) mysql->net.buff;
  if ((field_count=(uint) net_field_length(&pos)) == 0)
  {
    mysql->affected_rows= net_field_length(&pos);
    mysql->insert_id=	  net_field_length(&pos);
    if (pos < mysql->net.buff+length && net_field_length(&pos))
      mysql->info=(char*) pos;
    DBUG_RETURN(0);
  }
  mysql->extra_info= net_field_length(&pos); /* Maybe number of rec */
  if (!(fields=read_rows(mysql,(MYSQL_FIELD*) 0,5)))
    DBUG_RETURN(-1);
  if (!(mysql->fields=unpack_fields(fields,&mysql->field_alloc,field_count,0,
				    (my_bool) test(mysql->server_capabilities &
						CLIENT_LONG_FLAG))))
    DBUG_RETURN(-1);
  mysql->status=MYSQL_STATUS_GET_RESULT;
  mysql->field_count=field_count;
  DBUG_RETURN(0);
}


/**************************************************************************
** Alloc result struct for buffered results. All rows are read to buffer.
** mysql_data_seek may be used.
**************************************************************************/

MYSQL_RES * STDCALL
mysql_store_result(MYSQL *mysql)
{
  MYSQL_RES *result;
  DBUG_ENTER("mysql_store_result");

  if (!mysql->fields)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -