Пряме підключення до РСКБД

 

Пряме підключення до РСКБД

           Розглянемо модуль прямого доступу до РСКБД. Модуль використовує бібліотеку яка йде разом із інсталяцією середовища, і не прив’язується до його версії, тобто якщо в системі інстальовано будь-яку версію, або ж в каталозі з програмою поміщена бібліотека libmysql.dll підключення відбудеться в режимі сумісності. В випадку коли РСКБД розміщується на комп’ютері відмінному від клієнта, потрібно лише одна бібліотека, при чому вона не має бути точно такою як версія сервера.

 

unit sqlc;

interface

 

Uses Windows,mysql,SysUtils,Grids,dialogs,inifiles,Graphics,ComObj,ComCtrls,StdCtrls,Classes,Forms;

 

type

 TMySqlConnection=class {Опис классу під’єднання}

  _ip,_port,_login,_pwd:String; {Реквізити користувача, та розміщення серверу}

  character_set,server_info:String; {Кодування, та службова інформація про сервер}

  Connected:Boolean; {Стан підключення}

  LibHandle: PMYSQL; {Вказівник на бібліотеку}

  mySQL_Res: PMYSQL_RES; {Вказівник на результат}

  Destructor Destroy; {Знищує клас}

  Constructor Create; {Створює клас}

  Function Connect(ip,port,login,pwd:String):Boolean; {Підключення по заданим параметрам}

  Function Connect2:Boolean; {Підключення з використанням параметрів класу _ip,_port,_login,_pwd }

  Function SetCharacterSet(chs:String):Boolean;{Задання кодування}

 end;

 

 TMySqlQuery=class

  _sql,_db:string; {Змінні запиту та поточної БД}

  mySQL_Res: PMYSQL_RES; {Вказівник на результат}

  ColCount,RowCount:Integer; {Кількість стовпців, рядків}

  Function GetCell(Row,Col:Integer):String; {Повертає рядок на перетині Row,Col }

  Procedure FetchResult; {Процедура підготовки результату}

  Destructor Destroy; {Знищує клас}

  Constructor Create; {Створює клас}

  Function Run(sql:String;Connection:TMySqlConnection):Boolean; {Виконує запит спираючись на задані параметри}

  Function Run2(Connection:TMySqlConnection):Boolean; {Виконує запит із _sql }

  Function UseDB(db:String;Connection:TMySqlConnection):Boolean; {Вибирає БД за замоченням}

 end;

 

 Procedure FillStringGrid(Q:TMySqlQuery;G:TStringGrid); {Заповнює сітку данними з результату запиту}

 Procedure ResizeStringGrid(G:TStringGrid;MaxCellWidth,MaxCellHeight:Integer); {Масштабує клітинки сітки згідно вмісту}

 

{Пропустимо кільканадцять процедур та функцій які не стосуються прямого підключення ло РСКБД}

 

implementation

 

{Пропустимо кільканадцять процедур та функцій які не стосуються прямого підключення ло РСКБД}

 

ResizeStringGrid(G:TStringGrid;MaxCellWidth,MaxCellHeight:Integer);

Var

 s,sh,sh1,mh,m,s1,r,c:Integer;

Begin

 G.Canvas.Font:=G.Font;

 m:=MaxCellWidth;

 mh:=MaxCellHeight;

if MaxCellWidth=0 then m:=32736;

if MaxCellHeight=0 then mh:=32736;

for c:=0 to G.ColCount-1 do

 Begin

  s:=0;

  for r:=0 to G.RowCount-1 do

  Begin

   s1:=G.Canvas.TextWidth(G.Cells[c,r]);

  if s<s1 then s:=s1;

  End;

 if s<m then G.ColWidths[c]:=s+2 else G.ColWidths[c]:=m;

 End;

for r:=0 to G.RowCount-1 do

 Begin

  sh:=0;

  for c:=0 to G.ColCount-1 do

  Begin

   sh1:=G.Canvas.TextHeight(G.Cells[c,r]);

  if sh<sh1 then sh:=sh1;

  End;

 if sh<mh then G.RowHeights[r]:=sh+2 else G.RowHeights[r]:=mh;

 End;

End;

 

Procedure FillStringGrid(Q:TMySqlQuery;G:TStringGrid);

Var

 R,C:Integer;

Begin

 Q.FetchResult;

 G.RowCount:=Q.RowCount;

 G.ColCount:=Q.ColCount;

 G.FixedCols:=0;

if G.RowCount>1 then G.FixedRows:=1;

for R:=0 to Q.RowCount-1 do

 for C:=0 to Q.ColCount-1 do

  G.Cells[C,R]:=Q.GetCell(R,C);

End;

 

Function TMySqlQuery.GetCell(Row: Integer; Col: Integer):String;

var

  MYSQL_ROW: PMYSQL_ROW; {Змінна рядка}

  mySQL_Field: PMYSQL_FIELD; {Змінна поля}

begin

if mySQL_Res<>nil then {Якщо результат не порожній}

 Begin

 if (Row=0) then {Рядок з назвами стовпців}

  begin

   mySQL_Field := mysql_fetch_field_direct(mySQL_Res, Col); {дізнаємося назву Col стовпця}

  if mySQL_Field<>nil then {Якщо назву дізнались}

   begin

    Result:=UnicodeString(mysql_field_name(mySQL_Field));

   end;

    end else

   if (Row>0) and (Row<=mysql_num_rows(mySQL_Res)) then{якщо рядок не імен стовпців, і такий рядок присутній в результаті}

    begin

     mysql_data_seek(mySQL_Res, Row-1); {переходимо на потрібний рядок}

     MYSQL_ROW := mysql_fetch_row(mySQL_Res); {Витягуємо рядок}

    if MYSQL_ROW<>nil then {Успішно}

     begin

      Result:=UnicodeString(MYSQL_ROW^[Col]); {Повертаємо потрібну клітинку}

     end;

    end;

 End;

end;

 

Procedure TMySqlQuery.FetchResult;

begin

if mySQL_Res<>nil then {якщо результат не порожній}

 Begin

  ColCount:=mysql_num_fields(mySQL_Res); {Кількість стовпців}

  RowCount:=mysql_num_rows(mySQL_Res)+1; {Кількість рядків + заголовки}

 End;

end;

 

Function TMySqlQuery.UseDB(db: string;Connection:TMySqlConnection):Boolean;

Var

 r:Integer; {Змінна помизки}

begin

 Result:=True; {вважаемо що результат буде успішним}

 _db:=db; {Ініціалізуємо змінну класу}

 r:=mysql_select_db(Connection.LibHandle,PAnsiChar(AnsiString(db))); {Пробуємо змінити БД}

if r<>0 then Begin {Якщо закралася помилка}

Result:=False; {Неуспішний результат}

MessageBoxA(HWND_DESKTOP,PAnsiChar(mysql_error(Connection.LibHandle)),'Error!',MB_ICONERROR); {Виводимо помилку}

End;

end;

 

Function TMySqlQuery.Run(sql: string; Connection: TMySqlConnection):Boolean;

begin

 _sql:=sql; {Ініціалізуємо змінну класу}

 Result:=True; {Вважаємо, що результат успішний}

if mysql_real_query(Connection.LibHandle,PAnsiChar(AnsiString(sql)),Length(sql))<>0 {Виконуємо запит} then

 Begin {Виявлено помилку}

Result:=False;MessageBoxA(HWND_DESKTOP,PAnsiChar(mysql_error(Connection.LibHandle)),'Error!',MB_ICONERROR);End; {Відображаємо помилку}

 mySQL_Res := mysql_store_result(Connection.LibHandle); {Присвоюємо результат виконання в класс}

end;

 

Function TMySqlQuery.Run2(Connection: TMySqlConnection):Boolean;

begin

 Result:=False;

if _sql='' then MessageBoxA(HWND_DESKTOP,'Sql Query not set!','Error',MB_ICONERROR) else

 Result:=Run(_sql,Connection);

end;

 

Destructor TMySqlQuery.Destroy;

begin

if mySQL_Res<>nil then mysql_free_result(mySQL_Res);

 mySQL_Res := nil;

end;

 

Constructor TMySqlQuery.Create;

begin

 _sql:='';_db:='';

 mySQL_Res:=nil;

end;

 

Constructor TMySqlConnection.Create;

begin

 _ip:='';_port:='';_login:='';_pwd:='';

 character_set:='';server_info:='';

 Connected:=False;

end;

 

Function TMySqlConnection.Connect(ip: string; port: string; login: string; pwd: string):Boolean;

begin

 Result:=True; {Вважаємо, що результат буде успішним}

 _ip:=ip;_port:=port;_login:=login;_pwd:=pwd; {Ініціалізуємо змінні класу}

 libmysql_fast_load(nil); {Завантажуємо бібліотеку}

 if mySQL_Res<>nil then mysql_free_result(mySQL_Res); {Якщо результат не порожній очищуємо його}

 mySQL_Res := nil; {Маркуємо, як порожній}

if LibHandle<>nil then {Якщо покажчик бібліотеки не порожній}

 begin

  mysql_close(LibHandle); {Очищуємо покажчик бібліотеки}

  LibHandle := nil;

 end;

 LibHandle := mysql_init(nil); {Ініціалізуємо РСКБД}

if LibHandle=nil then {Трапилась помилка}

 Begin MessageBoxA(HWND_DESKTOP,'MySQL Initialization FAILED!','Error',MB_ICONERROR);Result:=False;End; {Виводимо поилку}

if mysql_real_connect(LibHandle,PAnsiChar(AnsiString(ip)),

PAnsiChar(AnsiString(login)),PAnsiChar(AnsiString(pwd)),nil,StrToInt(port), nil, 0)=nil {З’єднуємось}

  then

  Begin {Помилка при з’єднанні}

Result:=False;MessageBoxA(HWND_DESKTOP,PAnsiChar(mysql_error(LibHandle)),'Error!',MB_ICONERROR);End;

 {Дізнаємося інформацію про сервер}

 server_info:=UnicodeString(mysql_get_server_info(LibHandle));

{Дізнаємося кодування}

 character_set:=UnicodeString(mysql_character_set_name(LibHandle));

 Connected:=Result; {Міняємо статус підключення}

end;

 

Function TMySqlConnection.Connect2;

begin

 Result:=false;

if _port='' then _port:='3306';

if _ip='' then MessageBoxA(HWND_DESKTOP,'IP adress not set!','Error',MB_ICONERROR) else

if _login='' then MessageBoxA(HWND_DESKTOP,'Login not set!','Error',MB_ICONERROR) else

if _pwd='' then MessageBoxA(HWND_DESKTOP,'Password not set!','Error',MB_ICONERROR) else

 Result:=Connect(_ip,_port,_login,_pwd);

end;

 

Function TMySqlConnection.SetCharacterSet(chs: string):Boolean;

Var

 s:String;

begin

 s:='SET NAMES '''+chs+''';';

 Result:=True;

if mysql_real_query(LibHandle, PAnsiChar(AnsiString(s)),Length(s))<>0 then

 Begin Result:=False;MessageBoxA(HWND_DESKTOP,PAnsiChar(mysql_error(LibHandle)),'Error!',MB_ICONERROR);End;

 character_set:=UnicodeString(mysql_character_set_name(LibHandle));

end;

 

Destructor TMySqlConnection.Destroy;

begin

if mySQL_Res<>nil then mysql_free_result(mySQL_Res);

 mySQL_Res := nil;

if LibHandle<>nil then

 begin

  mysql_close(LibHandle);

  LibHandle := nil;

 end;

 Connected:=False;

end;

 

end.