Стаття delphi і interbase

Delphi і Interbase. Частина I, вона ж вступна.

Ліричний відступ, або "Що це буде"

Всім привіт! Буде це, мабуть, цикл статей про принципи побудови баз на IB і його клони. Цикл тому, що вкладеться в кілька листів на цю тему неможливо в принципі, а розглянути хотілося б безліч речей, яких немає ні в довідках, ні в літературі, причому прийшовши до розуміння цих речей поступово, починаючи з найпростіших азів. Ну а фіналом буде написання повноцінної мережевої програми. Відразу обмовлюся, що "по ходу п'єси" доведеться розглядати безліч питань, необхідних для осмисленої роботи, і IB (а найчастіше - і Delphi) власне, що не стосуються. Наберіться терпіння, якщо ви цього не знаєте (потім все одно стане в нагоді :)) або пропустіть, якщо вам це і так зрозуміло.

І ще одна, остання, але важлива, застереження. Багато речей, які будуть тут обговорюватися, в т.ч. приклади, можуть бути реалізовані кількома способами. Я буду орієнтуватися виключно на способи програмні. Наприклад, в наступному розділі мова піде про створення першої бази даних. Це робиться менш, ніж за хвилину в тому ж IbExpert'е, але ми все це зробимо руками за допомогою написаної спеціально для цього програми. Кому-то це може здатися "китайським комунізмом", але, як показав досвід, людина, яка чітко знає як, з якими параметрами створюється база в коді, набагато швидше розбереться, як цю базу створити в будь-який оболонці. А ось зворотне твердження, як правило, не вірно. Якщо ви все життя тикали кнопки в оболонці, а потім раптом зіткнулися з необхідністю створювати базу в runtime, швидше за все, у вас будуть труднощі. Подібний принцип буде сповідатися протягом усього циклу статей.

Підготовка до першого побачення

Власне, установка проблем представляти не повинна: ​​ви просто запускаєте скачав setup і все, що потрібно, буде встановлене. Тепер десь на диску у вас сидить каталог з СУБД, і вам потрібно створити базу, підключитися до неї, і, заради цікавості, глянути, а що ж там є. (Думаєте, нічого немає? Помиляєтеся!)
Запустіть Delphi, створіть новий проект, і збережіть його на диск. Починаючи з версії 5.0 до складу Delphi входить вже згадуваний набір компонентів IBX, або Interbase Express, що дозволяють працювати з Interbase і його клонами через рідне api, а не ODBC-підключення. Ми будемо користуватися саме ними, і в даний момент нас буде цікавити компонент
TIbDatabase. На цьому посиланню ви зможете коротко ознайомитися з тим, що він вміє. Не переживайте, якщо раптом вам нічого не зрозуміло, все в свій час :)
На форму помістіть Toolbar, ActionList і ImageList. (При бажанні можна обійтися просто однією кнопкою на формі, але я б все-таки радив робити спочатку осмислений інтерфейс, з тим, щоб в майбутньому його можна було безболісно нарощувати). Зв'яжіть між собою ці компоненти установкою властивості Images у ActionList і ToolaBar'а, і вставте в ImageList картинку, яка, на вашу думку, відповідає процесу створення бази даних.

Я б також радив перейменувати компоненти. Як - як кому подобається. Наприклад, у мене все назви починаються з одного або декількох букв, що відображають тип компонента, а решта вказують на призначення цього компонента. Наприклад, в будь-якому своєму проекті я знаю, що головна форма завжди називається fMain, головний ToolBar - tbMain і так далі. А якщо мені треба, наприклад, знайти кнопку, що відповідає за мінімізацію дочірніх вікон, що не дивлячись можу сказати, що вона буде називатися btnWindowMinimizeAll, відповідний їй пункт меню - miWindowMinimizeAll, заголовний пункт меню, в якому він знаходиться - miWindow, а обробник всього цього буде прописаний в aWindowMinimizeAllExecute (TAction). Звичайно, це займає час, але Новомосковскбельность коду зростає в багато разів, а головне, набагато полегшує орієнтування в будь-якому своєму проекті, навіть якщо ви писали його кілька років тому.

Тепер створіть в ActionList новий пункт, вкажіть йому потрібний малюнок, а кнопці надайте цей новостворений Action. На цьому етапі ви повинні бачити перед собою приблизно наступне:

Стаття delphi і interbase


Тепер двічі клацнувши на свій Action в ActionList, ви отримаєте можливість прописати для нього якийсь оброблювач. Цей самий обробник, за задумом, і буде займатися створенням бази. Якщо ви дали собі працю перегорнути опис компонента
TIbDatabase, то у нього був відповідний метод (CreateDatabase) на створення бази даних. Зараз ми розберемося, як цей метод працює.

Створення бази даних

Форма для введення мінімальних параметрів

Очевидно, що необхідні для створення БД параметри, нам доведеться якось вводити. тобто від створення діалогу тут не відкрутишся. Стало бути, додаємо в проект нову форму (dlgDbCreate), і тикаємо на неї потрібні нам поля введення. Вийде приблизно наступне:

Стаття delphi і interbase


Оскільки створення бази даних - справа аж ніяк не щоденне, має сенс прибрати цю форму зі списку створюваних автоматично і написати процедуру, яка при виклику буде створювати цю форму динамічно, отримувати у користувача потрібні значення, і повертати їх нам у вигляді параметрів. Заходимо в Project / Options, переносимо dlgDbCreate в список доступних форм, і пишемо простенький код:

type
TdlgDbCreate = class # 40; TForm # 41;
btnOk. TBitBtn;
btnCancel. TBitBtn;
lDbName. TLabel;
lDialect. TLabel;
lLogin. TLabel;
lPassword. TLabel;
eDbName. TEdit;
cbDialect. TComboBox;
eLogin. TEdit;
ePassword. TEdit;
Bevel1. TBevel;
private

public

class function fDlgDbCreate. TDlgDbCreate;
end;

var
dlgDbCreate. TdlgDbCreate;

function GetDbParams # 40; var DBName. string; var Dialect. integer;
var UserName. Password. string # 41 ;. boolean;

function GetDbParams # 40; var DBName. string; var Dialect. integer;
var UserName. Password. string # 41 ;. boolean;
begin
with TDlgDbCreate. fDlgDbCreate do begin
Result. = # 40; ShowModal = mrOk # 41; ;
if Result then begin
DbName. = EDbName. Text;
Dialect. = StrToInt # 40; cbDialect. Text # 41; ;
UserName. = ELogin. Text;
Password. = EPassword. Text;
end;
end;
end;

class function TdlgDbCreate. fDlgDbCreate. TDlgDbCreate;
begin
if dlgDbCreate = nil then
dlgDbCreate. = Self. Create # 40; nil # 41; ;
Result. = DlgDbCreate;
end;

FreeAndNil # 40; dlgDbCreate # 41; ;
end.

Offtopic: Використання методів класу для роботи з об'єктами, які не створюються автоматично

Передача параметрів сервера

На даний момент нам залишилася одна забава: згодувати все отримані параметри компоненту
TIbDatabase і викликати його метод CreateDatabase. Все досить тривіально, нижче я просто наведу код, звернути увагу слід тільки на один момент: структуру параметрів при виклику методу на створення бази. Вона дещо відрізняється від тієї, яка використовується при підключенні. Сам обробник прописаний в aDatabaseCreate.OnExecute (TAction), який присвоєно нашою єдиною поки кнопці.

procedure TfMain. aDatabaseCreateExecute # 40; Sender. TObject # 41; ;
var
DbName. string;
Dialect. integer;
UserName. string;
Password. string;

begin
if GetDbParams # 40; DbName. Dialect. UserName. Password # 41; then
with dbMain do begin
Connected. = FALSE;
DatabaseName. = DbName;
SQLDialect. = Dialect;
Params. Clear;
Params. Add # 40; 'USER "' + UserName + '"' # 41; ;
Params. Add # 40; 'PASSWORD "' + Password + '"' # 41; ;

try
CreateDatabase;
MessageDlg # 40; Format # 40; csDatabaseCreatedMsg. # 91; DbName # 93; # 41 ;. mtInformation. # 91; mbOk # 93 ;. 0 # 41; ;
except
on E. Exception do
MessageDlg # 40; Format # 40; csDatabaseCreateError. # 91; E. Message # 93; # 41 ;. mtError. # 91; mbOk # 93 ;. 0 # 41; ;
end;
end;
end;


За замовчуванням, логіном / паролем є sysdba / masterkey. Експериментувати можна і з ними, але ось для серйозної роботи пароль адміністратора слід змінити спочатку (логін, sysdba, змінити не можна).

Повідомлення, що видаються програмою винесені в окремі константи, оголошені до того ж як строкові ресурси. Зроблено це для того, щоб згодом ці константи можна було спокійно редагувати безпосередньо в екзешник (привіт хацкери :)). Ось, власне, і все. Тепер натиснувши на кнопку, заповнивши поля форми і натисніть "Готово" ви опинитеся щасливим володарем нової бази даних. При найменуванні бази варто дотримуватися традицій, тобто розширення файлу вказати "* .GDB". Якщо в зазначеному вами місці на диску з'явився відповідний файл, то можна рухатися далі, а саме - подивитися, що ж в ньому лежить.

Підключення до бази даних

Знову таки, справа смаку, але я пішов по шляху многооконного інтефейс (MDI), щоб на кожну відкривається базу створювалося нове дочірнє вікно, в якому з цією базою можна буде працювати. Відповідно, головною формою виставляємо аттрибут FormStyle = fsMDIForm, заводимо нову форму, прибираємо з автоматично створюваних, їй вказуємо FormStyle = fsMDIChild, і кладемо на неї ще один
TIbDatabase (dbChild) для здійснення безпосереднього підключення. На головній формі заводимо ще один TAction (aDatabaseOpen), пов'язану з ним кнопку (btnDatabaseOpen) і додаємо ще один малюнок в TImageList (ilMain). Ще для відкриття файлу нам буде потрібно діалог TOpenDialog (OpenDlg) з відповідними настройками. Саме підключення найкраще прописати в дочірню форму, однією процедурою, якою буде передаватися шлях до файлу БД, порлученний з OpenDlg. Крім усього іншого процедура буде створювати нову форму і звільняти її в разі, якщо підключення не вдалося. У вас вийде приблизно наступний код:

procedure OpenDatabase # 40; DbName. string # 41; ;
begin
with TfChild. Create # 40; Application # 41; do begin
dbChild. DatabaseName. = DbName;
dbChild. SQLDialect. = 3;
try
dbChild. Connected. = TRUE;
LoadObjects;
Caption. = DbName;
Show;
except
on E. Exception do begin
MessageDlg # 40; Format # 40; csDatabaseOpenError. # 91; E. Message # 93; # 41 ;. mtError. # 91; mbOk # 93 ;. 0 # 41; ;
Free;
end;
end;
end;
end;


Єдиний нюанс - це установка діалекту, рівного трьом. Насправді у бази він може дорівнювати і одному. Тут справа в механізмі обробки невідповідностей діалектів: можна підключитися до бази з "завищеними" в порівнянні з реальним діалектом (він автоматично буде знижений і виникне подія OnDialectDowngradeWarning), але не навпаки. (Див. Властивість SqlDialect)

В основній формі виклик обробника простий до неподобства:

procedure TfMain. aDatabaseOpenExecute # 40; Sender. TObject # 41; ;
begin
if OpenDlg. Execute then
OpenDatabase # 40; OpenDlg. FileName # 41; ;
end;

Отримання списку таблиць і полів

У цій справі нам допоможуть дві процедури все того ж компонента
TIbDatabase. GetTableNames і GetFieldNames. Для зручності я помістив в дочірню форму TTreeView (tvObject), в якому ми виведемо це все у вигляді дерева, приблизно як це робить той же IbExpert. Сам процедура завантаження нічого незвичайного з себе не представляє, нижче наведено її код:

procedure TfChild. LoadObjects;
var
Node.
TableNode. TTreeNode;
slTables.
slFields. TStrings;
i. j. integer;
begin
with tvObjects. Items do begin
BeginUpdate;
try
Clear;
Node. = Add # 40; nil. 'Oaaeeou' # 41; ;
slTables. = TStringList. Create;
slFields. = TStringList. Create;
try
dbChild. GetTableNames # 40; slTables. TRUE # 41; ;
for i. = 0 to slTables. Count - 1 do begin
TableNode. = AddChild # 40; Node. slTables # 91; i # 93; # 41; ;
dbChild. GetFieldNames # 40; slTables # 91; i # 93 ;. slFields # 41; ;
for j. = 0 to slFields. Count - 1 do
AddChild # 40; TableNode. slFields # 91; j # 93; # 41; ;
end;
finally
slFields. Free;
slTables. Free;
end;
finally
EndUpdate;
end;
end;
end;


Тобто для кожної таблиці ми отримуємо список її полів. Викликається ця процедура з написаної раніше OpenDatabase безпосередньо після установки Connected в TRUE. На екрані результат буде виглядати приблизно так:

Стаття delphi і interbase


Як бачимо, в "порожній" бази даних виявилося просто купа всяких таблиць! Пояснюється це тим, що при виклику процедури GetTableNames ми передали другий параметр [System: boolean] рівним TRUE. І все, що ми бачимо, це не що інше, як системні таблиці. Забігаючи вперед скажу, що саме вони відповідають за зберігання метаданих, управління цілісністю і багато іншого.

У наступній статті ми навчимося створювати таблиці самостійно, переглядати їх, і більш докладно зупинимося на внутрішній архітектурі СУБД Interbase.

Питання і рішення приймаються як на мило, так і в форум. Исходник злегка причесаний проги для Delphi5 можна взяти тут.

За сім - до зустрічей, всім удачі.

Схожі статті