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

📄 umysqlclient.pas

📁 RO模拟器!!适合玩仙境传说的玩家们呦~
💻 PAS
📖 第 1 页 / 共 5 页
字号:
          end;
          blockread(f,buf,sizeof(buf),readcount); //read next chunk
     end;
     closefile(f); //close the file
     if (fnet.my_net_write('',0)<>0) or (fnet.net_flush<>0) then //send empty packet to mark eof
     begin
          fnet.last_errno:=CR_SERVER_LOST;
          fnet.last_error:=client_errors[(fnet.last_errno)-CR_MIN_ERROR];
          result:=-1;
          filemode:=tmp;
          exit;
     end;
     if (readcount < 0) then //did by any chance we had an error while reading?
     begin
          fnet.last_errno:=2;//EE_READ
          fnet.last_error:=copy(format('Error reading file ''%s'' (Errcode: %d)',[filename,IOResult]),1,sizeof(fnet.last_error)-1);
          result:=-1;
          filemode:=tmp;
          exit;
     end;
     filemode:=tmp; //restore filemode
     result:=0;
end;

////////////////////////////////////////////////////////////////////////////////
//returns client version
function TMysqlClient.GetClientInfo: string;
begin
     result:=MYSQL_SERVER_VERSION;
end;

////////////////////////////////////////////////////////////////////////////////
// returns protocol version - one should read this only after connecting
// or else will be 0
function TMysqlClient.Getprotocol_version: cardinal;
begin
     result:=fnet.protocol_version;
end;

////////////////////////////////////////////////////////////////////////////////
//internal function to send a command to the server
function TMysqlClient.simple_command(command: TEnumServerCommand;
  arg: string; lengt: Integer; skipp_check: boolean; retry:boolean): longint;
var pl:longint;
begin
     result:= -1; //mark error unless ok
     if not fnet.net_connected then //are we connected?
     begin
          if not(reconnect) then //attempt to reconnect
          begin
               //preserve the error on connect
               //fnet.last_errno:=CR_SERVER_GONE_ERROR;
               //fnet.last_error:=client_errors[(fnet.last_errno)-CR_MIN_ERROR];
               exit;
          end
     end;
     if (fstatus <> MYSQL_STATUS_READY) then //can we execute this command?
     begin
          fnet.last_errno:=CR_COMMANDS_OUT_OF_SYNC;
          fnet.last_error:=client_errors[(fnet.last_errno)-CR_MIN_ERROR];
          exit;
     end;
     fnet.last_error:=''; //init for command
     fnet.last_errno:=0;
     finfo:='';
     faffected_rows:= 0;
     finsert_id:=0;
     fnet.net_clear;
     if (fnet.net_write_command(chr(ord(command)),pchar(arg),lengt )<>0) then //let's try to send
     begin
          fnet.net_close;//end_server
          free_old_query;
          if reconnect or (fnet.net_write_command(chr(ord(command)),pchar(arg),lengt)<>0)then //another attempt to reconnect end send
          begin
               //failed
               fnet.last_errno:=CR_SERVER_GONE_ERROR;
               fnet.last_error:=client_errors[(fnet.last_errno)-CR_MIN_ERROR];
               exit;
          end;
     end;
     result:=0; //no error
     if (not skipp_check) then //if we need to check if server got it
     begin
          pl:=fnet.net_safe_read; //read length of next packet
          if pl = packet_error then //if there is something
          begin
               if fnet.last_errno=CR_SERVER_LOST then
                  close;
               if retry then //one more time, but in order to not make it infinite loop this time will not retry
                  result:=simple_command(command,arg,lengt,skipp_check,false) //this time we do not retry
               else
                   result:=-1;
          end
          else
              result:=0; //ok
     end;
end;

////////////////////////////////////////////////////////////////////////////////
// returns last error string (mapped on NET, actually down to VIO)
function TMysqlClient.GetLastError: string;
begin
     result:=fnet.last_error;
end;

////////////////////////////////////////////////////////////////////////////////
// reads one row from the server
// returns 0 if no error
// returns 1 if there arent anymore rows
function TMysqlClient.read_one_row(fields:longint;row:TMysql_Row;lengths:PCardinal): longint;
var field:longint;
    pkt_len,_len:longint;
    _pos,prev_pos:PChar;
begin
     // is there anything to read?
     pkt_len:=fnet.net_safe_read;
     if (pkt_len=packet_error) then
     begin
          result:=-1;
          exit;
     end;
     // is it the last row?
     if (pkt_len = 1) and(pchar(fnet.read_pos)[0] = #254) then
     begin
          result:=1;
          exit;
     end;
     //free row content
     for field:=0 to fields -1 do
         strdispose(TPPCA(row)[field]);
     //read next row
     prev_pos:= nil;
     _pos:=pchar(fnet.read_pos);
     // for each field value
     for field:=0 to fields-1 do
     begin
          //get field value size
          _len:=net_field_length(longint(_pos));
          if (_len=NULL_LENGTH) or (_len=0) then
             begin
                  TPPCA(row)[field]:=nil; //empty value
                  TPCA(lengths)[field]:=0;
             end
          else
              begin
                    TPPCA(row)[field]:=StrAlloc(_len+1);
                    //copy field content
                    move(_pos[0],TPPCA(row)[field]^,_len);
                    TPPCA(row)[field][_len]:=#0;// if one uses pchar
                    _pos:=_pos+_len;
                    TPCA(lengths)[field]:=_len;
              end;
          if (prev_pos<>nil)and(prev_pos[0]<>#0)then //if previous field value didnt ended by #0
             prev_pos[0]:=#0;
          prev_pos:=_pos; //move to next
     end;
     prev_pos[0]:=#0; //set the last #0
     result:=0;
end;

////////////////////////////////////////////////////////////////////////////////
// reads rows from the server
// returns data if no error
// returns nil if there were any errors
function TMysqlClient.read_rows(mysql_fields: PMysql_FieldDef; fields: Integer; var hadErrors:boolean): PMYSQL_DATA;
var pkt_len,field,len1:longint;
    cp:pchar;
    prev_ptr:PMysql_Rows;
    cur:PMysql_Rows;
begin
     result:=nil;
     hadErrors:=true;
     pkt_len:=fnet.net_safe_read; //is there any data?
     if (pkt_len= packet_error) then
        exit;
     new(result);
     if (result=nil) then //out of memory?
     begin
          fnet.last_errno:=CR_OUT_OF_MEMORY;
          fnet.last_error:=client_errors[(fnet.last_errno)-CR_MIN_ERROR];
          exit;
     end;
     result.data:=nil;
     prev_ptr:= nil;
     result.rows:=0;
     result.fields:=fields;
     cp:=pchar(fnet.read_pos);
     while not (( byte(cp[0]) = 254) and (pkt_len = 1)) do //do this until we get last row
     begin
          //here you could add a progress or something
          //like an event onNewRow <-disadvantage you can't tell how many left
          inc(result.rows); //we have new row
          //let's grab some memory for the new row
          new(cur);
          if cur<>nil then
             cur.data:=allocmem((fields)*sizeof(pchar));
          if (cur=nil) or (cur.data=nil) then
          begin //mmm.. we are running out of memory
               free_rows(result);
               fnet.last_errno:=CR_OUT_OF_MEMORY;
               fnet.last_error:=client_errors[(fnet.last_errno)-CR_MIN_ERROR];
               result:=nil;
               exit;
          end;
          cur.Next:=nil; //so far we assume no more rows
          cur.prior:=prev_ptr; //double link
          if prev_ptr<>nil then
             prev_ptr.Next:= cur //preserve next link
          else
              result.data:=cur;//it is the first / head
          prev_ptr:=cur;
          for field:=0 to fields-1 do //for each field
          begin
               len1:=net_field_length(longint(cp));
               if (len1 = 0)or(len1 = NULL_LENGTH) then //if it is an empty field
                  TPPCA(cur.data)[field]:=nil
               else
               begin
                    //let's grab some memory
                    TPPCA(cur.data)[field]:=StrAlloc(len1+1);
                    //copy field content
                    move(cp[0],TPPCA(cur.data)[field]^,len1);
                    TPPCA(cur.data)[field][len1]:=#0;// if one uses pchar
	            cp:=pchar(longint(cp)+len1); //we can move to next field
	            if (mysql_fields<>nil) then //if we passed fields structure
                    begin //we can check max_length
                         if  TPFDA(mysql_fields)[field].Max_Length < cardinal(len1) then
                             TPFDA(mysql_fields)[field].Max_Length := cardinal(len1);
                    end;
               end;
          end;
          pkt_len:=fnet.net_safe_read; //let's try to read next row /if any
          if ( pkt_len= packet_error) then
          begin //maybe we got an error
               free_rows(result); //we can free the rows
               result:=nil;
               exit;
          end;
          cp:=pchar(fnet.read_pos); //here we go again .. next row
     end;
     hadErrors:=false;
end;

////////////////////////////////////////////////////////////////////////////////
// internal decode of PMysql_Data into fields structure
function TMysqlClient.unpack_fields(data: PMYSQL_DATA; fields: Integer; long_flag_protocol: boolean): PMysql_FieldDef;
var field:PMysql_FieldDef;
    row:PMysql_Rows;
    aFieldVal:pchar;
begin
     //let's grab some memory
     getmem(result,sizeof(TMysql_FieldDef)*fields);
     field:=result;
     if (result=nil) then //out of memory?
        exit;
     row:=data.data; //first row=first field def
     while row<>nil do
     begin
          //table
          aFieldVal:=TPPCA(row.data)[0];
          field.Table:=StrNew(aFieldVal);
          //name
          aFieldVal:=TPPCA(row.data)[1];
          field.Name:=strnew(aFieldVal);
          //length
          aFieldVal:=TPPCA(row.data)[2];
          if aFieldVal<>nil then
             field.length:= (byte(pchar(aFieldVal)[0]))+
                            (byte(pchar(aFieldVal)[1]))shl 8+
                            (byte(pchar(aFieldVal)[2]))shl 16;
          //field type
          aFieldVal:=TPPCA(row.data)[3];
          if aFieldVal<>nil then
             field.FieldType:= byte(pchar(aFieldVal)[0]);
          //NUM_FLAG is not send from server so it needs to be set
          if (field.FieldType<=FIELD_TYPE_INT24) AND ((field.FieldType<>FIELD_TYPE_TIMESTAMP) OR (field.Length=14) OR (field.Length=8)) OR (field.FieldType=FIELD_TYPE_YEAR) then
             field.flags:=field.flags or NUM_FLAG;
          //flags and decimals
          aFieldVal:=TPPCA(row.data)[4];
          if aFieldVal<>nil then
          begin
               if (long_flag_protocol) then
               begin
                    field.flags:= (byte(pchar(aFieldVal)[0]))+
                                  (byte(pchar(aFieldVal)[1]))shl 8;
                    field.decimals:=byte(pchar(aFieldVal)[2]);
               end
               else
               begin
                    field.flags:= byte(pchar(aFieldVal)[0]);
                    field.decimals:=byte(pchar(aFieldVal)[1]);
               end;
          end;
          //default value
          //field.def:=nil; //*** removed
          //aFieldVal:=TPPCA(row.data)[5];
          //if (aFieldVal<>nil)and(data.fields=6) then //if there are 6 fields on PMysql_Data
             //field.def:=strnew(aFieldVal);
          field.Max_Length:= 0; //for the moment we don't know the max_length
          row := row.next; //next field def
          field:=@TPFDA(field)[1];
     end;
     free_rows(data); //we can now free data since all values are in fields
end;

////////////////////////////////////////////////////////////////////////////////
// closes the connection to mysql server
procedure TMysqlClient.close;
var rec:boolean;
begin
     //init internal variables
     fscramble_buff:='';
     fthread_id:=0;
     faffected_rows:=0;
     finsert_id:=0;
     fstatus:=MYSQL_STATUS_READY;
     fserver_version:='';
     fserver_capabilities:=0;
     fserver_status:=SERVER_STATUS_AUTOCOMMIT;
     fserver_language:=0;
     fextra_info:=0;
     finfo:='';
     if fnet.net_connected then //are we connected?
     begin
          free_old_query; //if we have anything in buffer
          fstatus:=MYSQL_STATUS_READY;
          rec:=freconnect; //preserve reconnect state
          freconnect:=false;
          simple_command(COM_QUIT,'',0,true,freconnect); //tell the server we go
          fnet.net_close;
          freconnect:=rec;
          //should init all server variables
     end;
     if assigned(fusedresult) then
     begin
          fusedresult.fhandle:=nil; //break the link
          fusedresult:=nil;
     end;
end;

⌨️ 快捷键说明

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