📄 umysqlclient.pas
字号:
funix_socket:='';
end;
//are we connected?
if fnet.net_connected then
begin
pkt_length:=fnet.net_safe_read(fclient_flag);
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);
if pos('4.1.0', fserver_version)=1 then
FUse410Password:=true
else
FUse410Password:=false;
//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 >= curpos+18) 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;
FWarningCount:= 0;
inc(curpos,18);
if (pkt_length >= curpos + 12) then
fscramble_buff:=format('%s%s',[fscramble_buff,copy(pchar(fnet.read_pos+curpos),0,12)])
else
if not FUse410Password then
fserver_capabilities:= fserver_capabilities and (not CLIENT_SECURE_CONNECTION);
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);
if (fclient_flag and CLIENT_CHANGE_USER = CLIENT_CHANGE_USER) and
(fserver_capabilities and (CLIENT_RESERVED or CLIENT_SECURE_CONNECTION or CLIENT_MULTI_RESULTS) = 0) then
fclient_flag :=fclient_flag and (not (CLIENT_RESERVED or CLIENT_CHANGE_USER or CLIENT_SECURE_CONNECTION or CLIENT_MULTI_STATEMENTS or CLIENT_MULTI_RESULTS));
{$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}
if fclient_flag and CLIENT_RESERVED = CLIENT_RESERVED then
begin
//set client flags in buffer
buff[0]:=chr(fclient_flag);
buff[1]:=chr(fclient_flag shr 8);
buff[2]:=chr(fclient_flag shr 16);
buff[3]:=chr(fclient_flag shr 24);
//set max allowed packet
buff[4]:=chr(max_allowed_packet);
buff[5]:= chr(max_allowed_packet shr 8);
buff[6]:= chr(max_allowed_packet shr 16);
buff[7]:= chr(max_allowed_packet shr 24);
buff[8]:= chr(fserver_language);
curpos:= 32;
end
else
begin
//set client flags in buffer
buff[0]:=chr(fclient_flag);
buff[1]:=chr(fclient_flag shr 8);
//set max allowed packet
buff[2]:=chr(max_allowed_packet);
buff[3]:= chr(max_allowed_packet shr 8);
buff[4]:= chr(max_allowed_packet shr 16);
curpos:=5;
end;
{$IFDEF HAVE_SSL}
if (fclient_flag AND CLIENT_SSL=CLIENT_SSL) then
begin
if ((fnet.my_net_write(@buff,curpos)<>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}
//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[curpos])^,i); //copy it to the buffer
curpos:=curpos+i;
end;
inc(curpos);
//if we have password
if (fpasswd<>'') then
begin
if (fserver_capabilities and CLIENT_SECURE_CONNECTION = CLIENT_SECURE_CONNECTION) then
begin
if FUse410Password then
begin
for i:=0 to 7 do
begin
buff[curpos]:='x';
inc(curpos);
end;
inc(curpos);
end
else
begin
buff[curpos]:=chr(20);
inc(curpos);
newscramble(pchar(@buff[curpos]), pchar(@fscramble_buff[1]), pchar(@fpasswd[1]));
inc(curpos,20);
end;
end
else
begin
somp:=mysql_scramble(fpasswd,copy(fscramble_buff,1,8));
i:=length(somp);
move(somp[0],pchar(@buff[curpos])^,i);
strdispose(somp);
curpos:=curpos+i+1;
end;
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;
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 not mysql_authenticate 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;
finally
if FThreaded then
FCriticalSection.Leave;
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
if FThreaded then
FCriticalSection.Enter;
try
result:=nil;
executedOk:=false;
if aquery='' then
exit;
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,pchar(@aquery[1]),length(aquery),true,freconnect)=0) then
if read_query_result=0 then
begin
fnet.last_errno:= 0;
if StoreResult then
begin
result:=store_result;
fnet.net_pack;//we can pack the net now
end
else
result:=use_result;
if fnet.last_errno = 0 then
executedOk:=true;
end
finally
if FThreaded then
FCriticalSection.Leave;
end;
end;
////////////////////////////////////////////////////////////////////////////////
// tells to server to performs a refresh
function TMysqlClient.refresh(options: longint): boolean;
var
buff:string[3];
begin
if FThreaded then
FCriticalSection.Enter;
try
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,pchar(@buff[0]),4,false,freconnect)=0;
finally
if FThreaded then
FCriticalSection.Leave;
end;
end;
////////////////////////////////////////////////////////////////////////////////
// attempt to change the current selected db
function TMysqlClient.select_db(const newdb: string): boolean;
begin
if FThreaded then
FCriticalSection.Enter;
try
if newdb<>'' then
result:=simple_command(COM_INIT_DB,pchar(@newdb[1]),length(newdb),false,freconnect)=0
else
result:=false;
if result then
fdb:=newdb;
finally
if FThreaded then
FCriticalSection.Leave;
end;
end;
////////////////////////////////////////////////////////////////////////////////
// tells to server to shutdown
// current logged in user will need permission to do that
function TMysqlClient.shutdown: boolean;
begin
if FThreaded then
FCriticalSection.Enter;
try
result:=simple_command(COM_SHUTDOWN,'',0,false,freconnect)=0;
finally
if FThreaded then
FCriticalSection.Leave;
end;
close;
end;
////////////////////////////////////////////////////////////////////////////////
// get the statistics from server
function TMysqlClient.stat: string;
begin
if FThreaded then
FCriticalSection.Enter;
try
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;
finally
if FThreaded then
FCriticalSection.Leave;
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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -