Пряме підключення до РСКБД
Пряме підключення до РСКБД
Розглянемо модуль прямого доступу до РСКБД. Модуль використовує бібліотеку яка йде разом із інсталяцією середовища, і не прив’язується до його версії, тобто якщо в системі інстальовано будь-яку версію, або ж в каталозі з програмою поміщена бібліотека 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.