📄 umysqlclient.pas
字号:
{$IFDEF _WIN_}
fhost:=LOCAL_HOST_NAMEDPIPE;
{$ELSE}
fhost:='localhost';
{$ENDIF}
if (funix_socket='') or
{$IFDEF _WIN_}
(funix_socket<>MYSQL_NAMEDPIPE)
{$ELSE}
(funix_socket<>MYSQL_UNIX_ADDR)
{$ENDIF}
then
{$IFDEF _WIN_}
funix_socket:=MYSQL_NAMEDPIPE;
{$ELSE}
funix_socket:=MYSQL_UNIX_ADDR;
{$ENDIF}
end; //if not mark we don't use named pipe
if (fnet.vio_type<>VIO_TYPE_NAMEDPIPE)and(fnet.vio_type<>VIO_TYPE_SOCKET) then
begin
fnamed_pipe:=false;
funix_socket:='';
end;
end;
end
else
begin
fnet.net_open(VIO_TYPE_TCPIP,fhost,funix_socket,fport,fconnect_timeout,true);
funix_socket:='';
end;
//are we connected?
if fnet.net_connected then
begin
pkt_length:=fnet.net_safe_read;
if (pkt_length = packet_error) then
begin //if we got an error
fnet.net_close;
result:=false;
exit;
end;
//we have the start packet
fnet.protocol_version:= byte(pchar(fnet.read_pos)[0]);
if (fnet.protocol_version <> PROTOCOL_VERSION) and
(fnet.protocol_version <> PROTOCOL_VERSION-1) then
begin //do we speak same protocol?
fnet.last_errno:= CR_VERSION_ERROR;
fnet.last_error:=format(client_errors[(fnet.last_errno)-CR_MIN_ERROR], [protocol_version,PROTOCOL_VERSION]);
fnet.net_close;
result:=false;
exit;
end;
curpos:=1;
//read server version
fserver_version:=copy(pchar(fnet.read_pos+curpos),1,length(pchar(fnet.read_pos+curpos)));
curpos:=curpos+length(fserver_version);
//read thread id
fthread_id:= byte(pchar(longint(fnet.read_pos+curpos)+1)^)+
byte(pchar(longint(fnet.read_pos+curpos+2))^)shl 8+
byte(pchar(longint(fnet.read_pos+curpos+3))^)shl 16+
byte(pchar(longint(fnet.read_pos+curpos+4))^)shl 24;
curpos:=curpos+5;
//get scramble buffer
fscramble_buff:=copy(pchar(fnet.read_pos+curpos),1,8);
curpos:=curpos+9;
//read server capabilities
if (pkt_length >= (longint(fnet.read_pos+curpos)+1 - (fnet.read_pos))) then
fserver_capabilities:=byte(pchar(longint(fnet.read_pos+curpos))^)+
byte(pchar(longint(fnet.read_pos+curpos+1))^)shl 8;
//if we have server language and server status
if (pkt_length >= (longint(fnet.read_pos+curpos)+18 - fnet.read_pos)) then
begin
fserver_language:=byte(pchar(fnet.read_pos+curpos)[2]);
fserver_status:=byte(pchar(fnet.read_pos+curpos+3)[0])+byte(pchar(fnet.read_pos+curpos+3)[1])shl 8;
end;
//time to do some writing
fclient_flag:=fclient_flag or CLIENT_CAPABILITIES;
{$IFDEF HAVE_SSL}
if (fuse_ssl) then
fclient_flag:=fclient_flag or CLIENT_SSL;
{$ENDIF}
//if initial db is specified
if (fdb<>'') then
fclient_flag:=fclient_flag or CLIENT_CONNECT_WITH_DB;
//if we have compression can we enable it?
{$IFDEF HAVE_COMPRESS}
if ((fserver_capabilities and CLIENT_COMPRESS=CLIENT_COMPRESS) and
(fcompress or (fclient_flag and CLIENT_COMPRESS=CLIENT_COMPRESS))) then
fclient_flag:=fclient_flag or CLIENT_COMPRESS
else
{$ENDIF} // seems we don't use/need compression
fclient_flag:=fclient_flag and not(CLIENT_COMPRESS);
{$IFDEF HAVE_SSL}
if ((fserver_capabilities AND CLIENT_SSL=CLIENT_SSL) and
(fuse_ssl or (fclient_flag and CLIENT_SSL=CLIENT_SSL))) then
fclient_flag := fclient_flag or CLIENT_SSL //this does nothing
else
if (fclient_flag and CLIENT_SSL=CLIENT_SSL) then
begin
fclient_flag :=fclient_flag and (not (CLIENT_SSL));
fuse_ssl:=false;
end;
{$ENDIF}
//set client flags in buffer
buff[0]:=chr(fclient_flag);
buff[1]:=chr(fclient_flag shr 8);
{$IFDEF HAVE_SSL}
if (fclient_flag AND CLIENT_SSL=CLIENT_SSL) then
begin
if ((fnet.my_net_write(@buff,2)<>0) or (fnet.net_flush<>0)) then
begin
fnet.net_close;
result:=false;
exit;
end;
apc:=pchar(fssl_cipher);
fnet.SwitchToSSL(pchar(fssl_key),pchar(fssl_cert),pchar(fssl_ca),pchar(fssl_capath),apc, fconnect_timeout);
fssl_cipher:=apc;
if (fnet.vio_type<>VIO_TYPE_SSL)and(fclient_flag and CLIENT_SSL=CLIENT_SSL) then
begin
fclient_flag :=fclient_flag and (not (CLIENT_SSL));//clear ssl flag
result:=false; //mark error on ssl
fuse_ssl:=false;
SSL_ReadError;
exit;
end;
end;
{$ENDIF}
//set max allowed packet
pchar(longint(@buff)+2)[0]:=chr(max_allowed_packet);
pchar(longint(@buff)+2)[1]:= chr(max_allowed_packet shr 8);
pchar(longint(@buff)+2)[2]:= chr(max_allowed_packet shr 16);
//do we have an user name?
if (fuser <>'') then
begin
i:=length(fuser);
if i>32 then //is it longer than 32
i:=32;
move(pchar(fuser)[0],pchar(@buff[5])^,i); //copy it to the buffer
curpos:=i+5+1;
end
else
curpos:=6;
//if we have password
if (fpasswd<>'') then
begin
somp:=mysql_scramble(fpasswd,fscramble_buff);
i:=length(somp);
move(somp[0],pchar(@buff[curpos])^,i);
strdispose(somp);
curpos:=curpos+i+1;
end
else
inc(curpos);
//do we have a db?
if (fdb<>'') and ((fserver_capabilities and CLIENT_CONNECT_WITH_DB)=CLIENT_CONNECT_WITH_DB) then
begin
i:=length(fdb);
if i>NAME_LEN then
i:=NAME_LEN;
move(pchar(fdb)[0],pchar(@buff[curpos])^,i);
curpos:=curpos+i;
end
else
inc(curpos);
//we have the buffer filled, let's send it
if (fnet.my_net_write(@buff,curpos)<>0) then
begin //errors?
fnet.net_close;
result:=false;
exit;
end;
//let's flush it
if (fnet.net_flush<>0) then
begin //errors?
fnet.net_close;
result:=false;
exit;
end;
//did it got to the server? are we logged in?
if (fnet.net_safe_read = packet_error) then
begin //errors?
fnet.net_close;
result:=false;
exit;
end;
//we use compression? let's tell to net to activate it
if (fclient_flag and CLIENT_COMPRESS = CLIENT_COMPRESS)then
fnet.compress:=true
else
fnet.compress:=false;
//we are ready to work
fstatus:=MYSQL_STATUS_READY;
//if server does not support connect with db
//we need to select the db
if (fdb<>'') and (not ((fserver_capabilities and CLIENT_CONNECT_WITH_DB)=CLIENT_CONNECT_WITH_DB))and (not select_db(fdb)) then
begin //errors on select db?
fnet.net_close;
result:=false;
exit;
end;
end
else //we are not connected
result:=false;
end;
end;
////////////////////////////////////////////////////////////////////////////////
//sends a query to the server and attempts to read the result
// if StoreResult is true then it will create a result in store mode, else it will be used
// rather than creating an empty result to mark an ok executed query ExecutedOk variable
// will be set to true
// !! Pay attention to it since it is the only way to know if a query with no
// result set was executed ok
function TMysqlClient.query(const aquery: string; StoreResult:boolean; var ExecutedOk:boolean): TMysqlResult;
begin
result:=nil;
executedOk:=false;
if freconnect then
if not ping then//this will reconnect if we lost the connection in the mean time
exit;
if (simple_command(COM_QUERY,aquery,length(aquery),true,freconnect)=0) then
if read_query_result=0 then
begin
if StoreResult then
begin
result:=store_result;
fnet.net_pack;//we can pack the net now
end
else
result:=use_result;
executedOk:=true;
end
end;
////////////////////////////////////////////////////////////////////////////////
// tells to server to performs a refresh
function TMysqlClient.refresh(options: longint): boolean;
var buff:string[3];
begin
buff[0]:=chr(options);
buff[1]:=chr(options shr 8);
buff[2]:=chr(options shr 16);
buff[3]:=chr(options shr 24);
result:=simple_command(COM_REFRESH,buff,4,false,freconnect)=0;
end;
////////////////////////////////////////////////////////////////////////////////
// attempt to change the current selected db
function TMysqlClient.select_db(const newdb: string): boolean;
begin
result:=simple_command(COM_INIT_DB,newdb,length(newdb),false,freconnect)=0;
if result then
fdb:=newdb;
end;
////////////////////////////////////////////////////////////////////////////////
// tells to server to shutdown
// current logged in user will need permission to do that
function TMysqlClient.shutdown: boolean;
begin
result:=simple_command(COM_SHUTDOWN,'',0,false,freconnect)=0;
close;
end;
////////////////////////////////////////////////////////////////////////////////
// get the statistics from server
function TMysqlClient.stat: string;
begin
if (simple_command(COM_STATISTICS,'',0,false,freconnect)<>0) then //try to send the command
result:=''//fnet.last_error //there was an error
else //no error
begin
if pchar(fnet.read_pos)[0]=#0 then //did we got an empty string?
begin
fnet.last_errno:=CR_WRONG_HOST_INFO;
fnet.last_error:= client_errors[(fnet.last_errno)-CR_MIN_ERROR];
result:='';//fnet.last_error;
end
else
result:=pchar(fnet.read_pos); //return stats
end;
end;
////////////////////////////////////////////////////////////////////////////////
// reconnects to the server
// returns true if success
function TMysqlClient.reconnect: boolean;
begin
if (not freconnect) or
(fserver_status and SERVER_STATUS_IN_TRANS =SERVER_STATUS_IN_TRANS) then
begin
fserver_status:=fserver_status and not SERVER_STATUS_IN_TRANS;
result:=false;
exit;
end;
//fnet.net_close;
if not connect then
result:=false
else
result:=true;
end;
////////////////////////////////////////////////////////////////////////////////
// internal send file to server for use with load data infile on client machine
function TMysqlClient.send_file_to_server(const filename: string): longint;
var readcount:longint;
buf:array[0..IO_SIZE*15-1] of char;
f:file;
tmp:byte;
begin
//todo fn_format(buf,filename,"","",4);
assignfile(f,filename);
tmp:=filemode; //old filemode
filemode:=0; //read only
{$I-}
reset(f,1); //try to open the file
{$I+}
if (IOResult<> 0) then
begin
fnet.last_errno:=0;// EE_FILENOTFOUND
fnet.last_error:=copy(format('File ''%s'' not found (Errcode: %d)',[filename,IOResult]),1,length(fnet.last_error));
fnet.my_net_write('',0); //send empty packet to server
fnet.net_flush;
result:=-1;
filemode:=tmp;
exit;
end;
blockread(f,buf,sizeof(buf),readcount); //let's send the file
while (readcount > 0) do //while we still have things in file
begin
if (fnet.my_net_write(buf,readcount)<>0) then //maybe we have errors?
begin
fnet.last_errno:=CR_SERVER_LOST;
fnet.last_error:=client_errors[(fnet.last_errno)-CR_MIN_ERROR];
closefile(f);
result:=-1;
filemode:=tmp;
exit;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -