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

📄 umysqlclient.pas

📁 用delphi连接mysql的组件
💻 PAS
📖 第 1 页 / 共 5 页
字号:
            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 + -