📄 libmysql.c
字号:
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 + -