firebirdUtils.pas
Kod: Tümünü seç
{*
Veritabani uzerinde yapilan degisiklikleri
script dosyalari vasitasiyla otomatik hale getirmek icin
kullanilan siniflarin yeraldigi unittir.
@Author Sadettin POLAT
@Version 09 Subat 2007 1.3
}
unit dbUtils;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs,IBQuery, StdCtrls,
dateutils,IBDatabase,IBSQL,
strutils, ib,ibscript;
{*
script dosyalarinin yer aldigi dizin.
}
const cntDDLPath='dbUpdates\'; /// script dosyalarinin yer aldigi dizin.
type
{*
Yapilan veritabani degisikliklerini script dosyasindan okuyarak
bagli bulundugu veritabanina uygulayan siniftir.
yeni bir tablo , domain , field eklenecegi zaman oncelikle
sinifin varolan metodlari kullanilarak ilgili nesnenin
daha onceden veritanina eklenip eklenmedigi belirlenir
eger eklenmemisse uygun script dosyasi belirtilerek
nesnenin veritabanina eklenmesi saglanir...
}
TFirebirdUtils = class
strict private
FDB:TIBDatabase; /// guncellemenin yapilacagi veritabani
FIBQuery:TIBQuery; ///guncelleme yapmadan once ilgili nesnelerin veritabaninda olup olmadigini sorgulamak icin kullanilan bilesen
FIBScript:TIBScript; ///script dosyalarini calistiran nesne
FTableDDL: TStrings; ///buna gerek yok. bunun icin FIBScript.script kullanilacak
procedure SetTableDDL(const Value: TStrings); ///FIBScript.scriptten sonra buna da gerek kalmadi
procedure ShowError(aCustomErrorMessage:String;aException:Exception); ///islemler sirasinda meydana gelen hatalari isleyen ve kullaniciya gosteren metod
published
{ Private declarations }
public
constructor Create(aDB:TIBDatabase);
destructor Destroy;override;
procedure ExecuteScript(aScriptFile:String);
function isDomainExist(aDomainName:String):Boolean;
function isTableExist(aTableName:string):Boolean;
function isFieldExist(aTableName,aFieldName:string):Boolean;
function isIndexExist(aIndexName:String):Boolean;
//zaten isIndexAlready adli bu isi yapan bir fonksiyon varmis :) neyse fazla mal göz cikarmaz ehehehe
function isFieldTypeOld(aTableName,aFieldName,aNewFieldType:string):Boolean;
function isIndexUnique(aTableName:string;aIndexName:string):Boolean;
function isIndexAlready(aTableName:string;aIndexName:string):Boolean;
function getIndexFieldCount(aIndexName:String):Byte;
property TableDDL:TStrings read FTableDDL write SetTableDDL;
{ Public declarations }
end;
implementation
{ TDBTable }
{*
dbTable nesnesinin calisabilmesi icin gerekli olan
ilk islemlerin yapilmasindan sorumlu olan metod.
Script dosyalarini calistiracak olan IBScript ve
nesnelerin varolup olmadigini kontrol etmek icin
IBQuery burda olusturulur...
@param aDB degisikliklerin uygulanacagi veritabani
@author Sadettin POLAT
@version 1.1
}
constructor TFirebirdUtils.Create(aDB: TIBDatabase);
begin
FDB :=aDB;
FTableDDL :=TStringList.Create; //fibscript.script ozelligi oldugu icin buna artik gerek yok...
FIBQuery :=TIBQuery.Create(nil);
FIBQuery.Database :=FDB;
FIBQuery.Transaction :=FDB.DefaultTransaction;
FIBScript := TIBScript.Create(nil);
FIBScript.Database :=FDB;
FIBScript.Transaction :=FDB.DefaultTransaction;
end;
{*
dbTable nesnesi calismasini bitirdikten sonra
Create meotunda olusturulan nesneler burda yok edilir.
@author Sadettin POLAT
@version 1.1
}
destructor TFirebirdUtils.Destroy;
begin
FreeAndNil(FTableDDL);
FreeAndNil(FIBQuery);
FreeAndNil(FIBScript);
inherited;
end;
{*
Script dosyasini cntDDLPath adresinden IBScript
nesnesine yukleyerek calistiran metod.
@param aScriptFile Scriptin yer aldigi dosyanin adi
@author Sadettin POLAT
@version 1.1
}
procedure TFirebirdUtils.ExecuteScript(aScriptFile: String);
begin
if FileExists(cntDDLPath+aScriptFile) = false then Exit;
TableDDL.Clear;
TableDDL.LoadFromFile(cntDDLPath+aScriptFile);
if trim(TableDDL.Text)='' then exit;
//raise Exception.Create('DDL ifadesi girilmemiş...');
FIBScript.Script := TableDDL;
if FIBScript.ValidateScript = false then
raise Exception.Create('Hatalı Script(' + aScriptFile+')');
try
FIBScript.ExecuteScript;
except
on e:Exception do
begin
FIBScript.Transaction.RollbackRetaining;
ShowError(aScriptFile + ' scripti çalışırken hatalar oluştu',e);
exit;
end;
end;
FIBScript.Transaction.CommitRetaining;
ShowMessage(aScriptFile +' adlı script basarili bir sekilde calistirildi...');
end;
{*
Parametre olarak verilen indexin kac tane alan uzerinde
olusturulmus oldugunu geriye donderir.
A indexi b,c fieldlerinin birlesiminden olusan bir index ise
geriye 2 degerini donderir...
@param aIndexName Field sayisi bulunacak olan index adi
@return Indexin kac tane field uzerinde olusturuldugunu geri donderir.
@author Sadettin POLAT
@version 1.1
}
function TFirebirdUtils.getIndexFieldCount(aIndexName: String): Byte;
begin
{
select count(*) from rdb$index_segments r
where r.rdb$index_name = 'TABLO_IDX2'
dikkat !!! RDB$INDICES tablosundaki RDB$SEGMENT_COUNT alanindan da bulunabilirdi...
}
FIBQuery.SQL.Clear;
FIBQuery.SQL.Add('select count(*) from rdb$index_segments r');
FIBQuery.SQL.Add('where r.rdb$index_name = :PRM_INDEXNAME');
FIBQuery.Params[0].AsString :=aIndexName;
FIBQuery.Open;
Result := FIBQuery.Fields[0].AsInteger;
end;
{*
Bir domainin veritabaninda olup olmadigini kontrol eder.
@param aDomainName Kontrol edilecek domain adi
@return Domain veritabaninda varsa True yoksa False degeri alir.
@author Sadettin POLAT
@version 1.1
}
function TFirebirdUtils.isDomainExist(aDomainName: String): Boolean;
begin
FIBQuery.SQL.Clear;
FIBQuery.SQL.Add('select * from rdb$fields r');
FIBQuery.SQL.Add('where r.rdb$system_flag = 0');
FIBQuery.SQL.Add('and r.rdb$field_name = :PRM_DOMAINNAME');
FIBQuery.Params[0].AsString :=aDomainName;
FIBQuery.Open;
Result := FIBQuery.Fields[0].IsNull=False;
end;
{*
Bir tablonun belirtilen field alanina sahip olup olmadigini kontrol eder.
Fieldin tipi bu metotda kontrol edilmez !!!
@param aTableName Fieldin yer aldigi tablo adi
@param aFieldName Kontrol edilecek field adi
@return Belirtilen field belirtilen tabloda varsa true yoksa false degeri alir
@author Sadettin POLAT
@version 1.1
}
function TFirebirdUtils.isFieldExist(aTableName, aFieldName: string): Boolean;
begin
FIBQuery.SQL.Clear;
FIBQuery.SQL.Add('select * from rdb$relation_fields db');
FIBQuery.SQL.Add('where db.rdb$field_name =:PRM_FIELD');
FIBQuery.SQL.Add('and db.rdb$relation_name =:PRM_TABLENAME');
FIBQuery.Params[0].AsString :=aFieldName;
FIBQuery.Params[1].AsString :=aTableName;
FIBQuery.Open;
Result := FIBQuery.Fields[0].IsNull=False;
end;
{*
Fieldin tipinin belirtilen tipte olup olmadigini kontrol eder.
@param aTableName fieldin yer aldigi tablo adidir.
@param aFieldName tipi kontrol edilecek fieldin adidir
@param aNewFieldType fieldin olmasi gereken yeni tip degeridir.
@return Fieldin tipi eski ise true belirtilen tipi sahipse false donderir.
@author Sadettin POLAT
@version 1.1
}
function TFirebirdUtils.isFieldTypeOld(aTableName, aFieldName,
aNewFieldType: string): Boolean;
begin
FIBQuery.Close;
FIBQuery.SQL.Clear;
FIBQuery.SQL.Add('select RDB$FIELD_SOURCE from rdb$relation_fields db');
FIBQuery.SQL.Add('where db.rdb$field_name = :PRM_FIELDNAME');
FIBQuery.SQL.Add('and db.rdb$relation_name =:PRM_TABLENAME');
FIBQuery.Params[0].AsString :=aFieldName;
FIBQuery.Params[1].AsString :=aTableName;
FIBQuery.Open;
Result := not (Trim(FIBQuery.Fields[0].AsString) = aNewFieldType);
end;
function TFirebirdUtils.isIndexUnique(aTableName:string;aIndexName:string):Boolean;
begin
{
SELECT RDB$INDEX_NAME
FROM RDB$INDICES
WHERE RDB$RELATION_NAME='TABLO'
AND RDB$INDEX_NAME = 'TABLO_IDX1'
AND RDB$UNIQUE_FLAG = 1;
}
FIBQuery.Close;
FIBQuery.SQL.Clear;
FIBQuery.SQL.Add('SELECT RDB$INDEX_NAME');
FIBQuery.SQL.Add('FROM RDB$INDICES');
FIBQuery.SQL.Add('WHERE RDB$RELATION_NAME=:PRM_TABLENAME');
FIBQuery.SQL.Add('AND RDB$INDEX_NAME = :PRM_INDEXNAME');
FIBQuery.SQL.Add('AND RDB$UNIQUE_FLAG = 1');
FIBQuery.Params[0].AsString := aTableName;
FIBQuery.Params[1].AsString := aIndexName;
FIBQuery.Open;
Result := FIBQuery.Fields[0].IsNull=False;
end;
function TFirebirdUtils.isIndexAlready(aTableName:string;aIndexName:string):Boolean;
begin
FIBQuery.Close;
FIBQuery.SQL.Clear;
FIBQuery.SQL.Add('SELECT RDB$INDEX_NAME');
FIBQuery.SQL.Add('FROM RDB$INDICES');
FIBQuery.SQL.Add('WHERE RDB$RELATION_NAME=:PRM_TABLENAME');
FIBQuery.SQL.Add('AND RDB$INDEX_NAME = :PRM_INDEXNAME');
FIBQuery.Params[0].AsString := aTableName;
FIBQuery.Params[1].AsString := aIndexName;
FIBQuery.Open;
Result := FIBQuery.Fields[0].IsNull=False;
end;
{*
Belirtilen indexin varolup olmadigini kontrol eder.
@param aIndexName Kontrol edilecek indexin adi
@return Belirtilen index var ise true yoksa false donderilir.
@author Sadettin POLAT
@version 1.1
}
function TFirebirdUtils.isIndexExist(aIndexName: String): Boolean;
begin
{
select count(*) from RDB$INDICES r
where r.rdb$index_name ='TABLO_IDX1'
}
FIBQuery.SQL.Clear;
FIBQuery.SQL.Add('select count(*) from RDB$INDICES r');
FIBQuery.SQL.Add('where r.rdb$index_name =:PRM_INDEXNAME');
FIBQuery.Params[0].AsString :=aIndexName;
FIBQuery.Open;
Result := FIBQuery.Fields[0].AsInteger=1;
end;
{*
fibscript bileseninden sonra artik TableDDL ozelligine gerek
kalmadigindan siniftan ihrac edilecek ozelliklerden birisi...
@param Value ddl kodlari
@author Sadettin POLAT
@version 1.1
}
procedure TFirebirdUtils.SetTableDDL(const Value: TStrings);
begin
FTableDDL := Value;
end;
{*
Script Execute sirasinda meydana gelen hatalari kullaniciya gosteren metod
@param aCustomErrorMessage Kullaniciya verilmek istenen herhangi bir mesaj
@param aException olusan istisnanin ShowError tarafindan islenebilmesi icin kullanilan degisken
@param aNewFieldType fieldin olmasi gereken yeni tip degeridir.
@author Sadettin POLAT
@version 1.1
}
procedure TFirebirdUtils.ShowError(aCustomErrorMessage: String;
aException: Exception);
begin
if aException.ClassNameIs('EIBInterbaseError') then
begin
MessageDlg(Format('Mesaj: %s ' + #13+#13+
'IBErrorCode: %d - SQLErrorCode: %d',
[aCustomErrorMessage,
EIBInterbaseError(aException).IBErrorCode,
EIBInterbaseError(aException).SQLCode])+#13+
'Message: '+aException.Message,mterror,[mbok],0);
end
else
begin
MessageDlg('Yapılan İşlem Sırasında Hata Oluştu!' +aCustomErrorMessage+ #13 + #13+
'Hata : ' + aException.Message + #13 +
'Hata Kodu : ' + aException.ClassName,mterror,[mbok],0);
end;
end;
{*
Tablonun veritabaninda varolup olmadigini kontrol eder.
@param aTableName kontrol edilecek tablonun adi
@return tablo varsa true yoksa false donderir
@author Sadettin POLAT
@version 1.1
}
function TFirebirdUtils.isTableExist(aTableName: string): Boolean;
begin
FIBQuery.Close;
FIBQuery.SQL.Clear;
FIBQuery.SQL.Add('SELECT COUNT(RDB$RELATION_NAME)');
FIBQuery.SQL.Add('FROM RDB$RELATIONS');
FIBQuery.SQL.Add('WHERE RDB$RELATION_NAME = :PRM_TABLOADI');
FIBQuery.SQL.Add('AND RDB$VIEW_SOURCE IS NULL');
FIBQuery.Params[0].AsString :=aTableName;
FIBQuery.Open;
Result := FIBQuery.Fields[0].AsInteger > 0;
end;
end.
Kod: Tümünü seç
procedure TForm3.Button1Click(Sender: TObject);
var
FBUtils:TFirebirdUtils;
begin
FBUtils :=TFirebirdUtils.Create(IBDatabase1);
//belirtilen tablo yoksa tabloyu olusturmak icin gerekli
//olan sql kodlarini dosyadan calistirir.
if FBUtils.isTableExist('TabloAdi') = false then
FBUtils.ExecuteScript('TabloDDLininYerAldigiDosya.sql');
//belirtilen tabloda belirtilen alan yoksa ilgili alani
// olusturmak icin gerekli olan sql kodlarini
//dosyadan calistirir.
if FBUtils.isFieldExist('TabloAdi','FieldAdi') = False then
FBUtils.ExecuteScript('FieldDDLininYerAldigiDosya.sql');
FreeAndNil(FBUtils);
end;