11 Aralık 2009 Cuma

Redolog dosyalarımın boyutunu nasıl değiştirebilirim?

Boyutu değiştirilmek istenen her redo log dosyasını içeren group ,
önce silinir sonra yeniden oluşturulur. Bu yöntemle redo log
dosyalarının yerleri ve isimleri de değiştirilebilir.
Bir log grubunu silebilmek için silmek istediğimiz grup statusu
INACTIVE olmalıdır. Redo log grubuna
ait her dosya birbirinin aynısı olacağı için büyüklükleri de aynı olmak zorundadır.
Farklı redo log gruplardaki dosyalar farklı büyüklükte olabilir.
Aşağıda örnek bir silme ve yeniden oluşturma işlemi gerçekleştirdim.

1. select * from v$log;

Bu sorguyla hangi log grubunun inactive olduğunu öğrenip
o log grubunu drop edeceğim.

2. alter database drop logfile group 1;

INACTIVE durumdaki redo log grubumu sildim.

3. alter database add logfile group 1 ('/u01/app/oracle/oradata/orcl/redo01a.log','/u01/app/oracle/oradata/orcl/redo01b.log') size 150m;

Burada yeni oluşturduğum redo log dosyasının boyutunu 150 mb olarak ayarladım.

Bu noktada 1 numaralı redo grubumuz için işlem tamam.
Şimdi log grobumuzu switch ederek diğer grupları da aynı şekilde
önce silip sonra yeniden oluşturarak işlemi tamamlayabiliriz.
Aşağıdaki sql leri çalıştırıp bir sonraki log file e geçebiliriz.

alter system switch logfile;

alter system checkpoint;

Redo log konusunda daha fazla bilgi
*************************************
Bir transaction, commit edildiğinde ; redo log file üzerinde bir fiziksel yazma gerçekleşir.
Commit istemi kontrolü kullanıcıya geri vermeden önce yazma işlemi tamamlanmak zorundadır.
Yazma işleminin çeşitli nedenlerle uzaması beklemeye neden olur. Redo log dosyalarının
boyutu bu beklemeyi etkileyen bileşenlerden birisidir.

Redo log I/O işlemleri eğer log dosyaları ayrı ve redo log dosyalarından başka veri içermeyen
bir fiziksel sürücüde ise optimize edilmiş olur. Eğer bu başarılabilirse,
yazma anında disk kafası zaten doğru konumda olduğundan
hareket ihtiyacı duymayacaktır ve yazma zamanı minimize edilmiş olur.
Çünkü log yazma işlemi bir sıralı yazma işlemidir ve sadece logwriter process i ile gerçekleştirilir.

Her hangibir veri kaybına karşı redo log dosyaları mirror edilebilir.
Bu Oracle tarafından yazılım tabanlı olarak yapılabileceği gibi (redo log multiplexing),
donanım temelli de olabilir. (RAID 1)

Redo log ların switch olması sonucu database checkpoint meydana gelir.
Checkpoint işlemi tamamlanmadan ilgili redo log grubu yeniden
kullanılabilir duruma (INACTIVE) gelmeyecektir. Bu nedenle büyük ve çok sayıda
redo log grubu olması daha iyi sonuç verebilir.Çok sayıda redo log grubu
oluşturulursa; redo log grubunun kendisinin içerdiği data aktif olarak
checkpointte kullanılırken, aynı redo log grubuna yeni redo log larının yazılması
ihtiyacının ortaya çıkma dolayısıyla wait oluşma ihtimali düşecektir.
Redo log dosyalarının büyütülmesi ise checkpoint oluşma sıklığını azaltacaktır.

Redo log dosyalarının uygun büyüklüğü transaction miktarına göre değişiklik gösterir.
Redo log dosyalarının boyutu sık sık log switch olayı meydana gelmeyecek kadar büyük olmalıdır.
64-256 mb aralığında 10-20 farklı redo log group olması alışılmadık bir durum değildir.

Genel tavsiye log switch sıklığının
15-20 dk. olması yönündedir. Redo log dosyasının boyutu konusundaki hesaplama
yoğun zamana göre yapılmalıdır.
v$log_history tablosunu kullanarak yoğun zamanlardaki log
değiştirme sıklığı kolayca incelenebilir.

select * from v$log_history
order by sequence# desc

Örneğin yoğun zamanda 7 dk aralıkla değişen 50 mb boyutunda log file lerimiz olsun.
Yeni log file buyukluğümüz yaklaşık 15-20 dk bir log switch
olmasını istediğimiz için 150 mb. civarinda olabilir.

Aşağıdaki sorgudan yola çıkarak, mevcut redo log gruplarını, member dosyaların yerlerini,
redo log dosyalarının boyutlarını ve son zamanlardaki log file değitirme sıklığını görebiliriz.

select l.sequence#,l.group#,l.bytes,lf.type,lf.member,l.first_time from v$log l, v$logfile lf
where l.group# = lf.group#
order by l.sequence#

Ayrıca "v$log" tablosundaki "status" alanı aşağıdaki değerleri alabilir.

UNUSED
*******************
Oracle daha once bu gruba hiç yazmamış.
Yeni yaratılan redo log grup için status.

CURRENT
*******************
Aktif olarak yazılan redo log grubu bu grup.
Log group drop edilemez.

ACTIVE
*******************
Oracle daha once bu gruba yazmış; yazılanlar instance recovery için gerekli.
Log group drop edilemez.

INACTIVE
*******************
Oracle daha once bu gruba yazmış; yazılanlar instance recovery için gerekli.
Log group drop edilebilir.

Konuyla ilgili aşağıdaki linkler de incelenebilir.

Ingilizce
****************
http://download.oracle.com/docs/cd/E11882_01/server.112/e10595/onlineredo002.htm

http://download.oracle.com/docs/cd/B10500_01/server.920/a96521/onlineredo.htm

Türkçe
****************
www.cagataycebi.com/oracle/oracle_redologs.pdf

http://www.gokhanatil.com/redo-log-dosyalarinin-boyutu-ne-kadar-olmali/

http://www.mysqlsupport.net/oracle-redo-log.html

9 Kasım 2009 Pazartesi

IFS-Centura Debug Videosu (Rapidshare Link)

http://rapidshare.com/files/304386557/centura-debug.rar

Ulaşılamayan linkler ile ilgili mail atarsanız
yenilerini burada yayınlayacağım.
Ayrıca sorularınız ile ilgili
cevapları da burada bulabilirsiniz.

8 Ekim 2009 Perşembe

IFS/Centura The End.

Merhaba,
IFS üzerine çalışmakta olduğum Uzmar Gemi İnşaa AŞ. den
"2009 Mayıs" tarihinde ayrıldım. Dolayısıyla artık IFS framework ve Centura ile
ilgili çalışmıyorum. Centura ve IFS hakkındaki muhtemelen son
yazılarımı, eski notlarımdan hareketle,
"2009 Ekim" ayında hazırlamış bulunuyorum. Faydalı olmasını umarım.

Bu nokta yeni IFS geliştiricilere tavsiyem bloğumdaki
centura ile ilgili pdf ve videoları , konuyla ilgili yazılarımı
ve zaten ellerindeki hazır örnek IFS exe sinin
centura kodlarını iyi incelemeleri olacaktır.

Akılda tutulması gereken bir diğer nokta,
esas itibariyle centura ile de örneğin delphi ile yapılan her uygulama
gerçekleştirilebilir ve gerçekleştirilmektedir. Centura ile şu yapılamaz,
bu yapılamazları çok dinleyen biri olarak aynı tepkilerin sizi yıldırmasına
izin vermemenizi tavsiye ediyorum. Ayrıca Centura, IFS tekelindeki bir ide değildir.
Bu ideyi Win32 Development için turkiyede kullanmakta olan,
görüştüğüm firmalar da vardır.
Centura IDE sini Team Developer ismiyle geliştirmekte olan
Unify firmasının web sitesini, daha fazla bilgi için inceleyebilirsiniz.

http://www.unify.com/Products/TeamDeveloper/default.aspx

http://www.unify.com/products/teamdeveloper/videos/ide/td_5.2_themed_ide.html

Gelecekte IFS Applications .net te çalışacak gibi görünüyor.
Centura kodlarını .net ortamına geçimekle ilgili çözümler sunan
IceTeaGroup firmasının, IFS uygulamasını örnek uygulama olarak göstermekte olduğu
aşağıdaki sayfayı ziyaret edebilirsiniz.

http://www.iceteagroup.com/Porting/CaseStudies.aspx

Bundan sonraki yazılarım genellikle yeni işim olan Oracle Database Yönetimi
ve linux üzerine olacak sanırım.

İyi çalışmalar.

Centura - Kaydetme öncesi kontrol

Kaydet butonuna basıldığında önce bir kontrol gerçekleştirmek istiyorum. Duruma göre kaydedilecek veya bir mesaj gösterilecek ve kaydetme iptal edilecek. Nasıl yaparım ?
Önce ihtiyacımız olan değişkenleri forma ekleyelim.
Number: nDegerListesindeKacTaneVar
Boolean: bBasariliMi

İlgili cTableWindow veya cFormWindow 'a ait "action" tabına eğer önceden eklenmediyse On PM_DataSourceSave olayı eklenilir. Önceden bu olaya kod yazılmış ise değişiklik yapılır.Şimdi de bu gereklilikleri gerçekleştirelim.
On PM_DataSourceSave
! kod buradan basladi
Select Case wParam
Case METHOD_Execute
Set bBasariliMi = DbPLSQLBlock(c_hSql,"
BEGIN
SELECT count(*)
INTO :frmShopOrd.nDegerListesindeKacTaneVar
FROM &AO.UZMAR_OPER_TANIM_LOV
WHERE tanim =:tbwShopOrderOperation.colOperationDescription;
END;")
If bBasariliMi
If nDegerListesindeKacTaneVar < 1
Call SalSendClassMessage (PM_DataSourceSave, wParam, lParam )
! kod burada bitti

Centura - Tablomda veri var mı?

Aşağıdaki örnekteki fonksiyonu kullanarak,
herhangibir cTableWindow veya cChildWindow
içinde satır olup olmadığı test edebilirsiniz.

If SalTblAnyRows( mytablename, 0 , 0 )
..çeşitli işler..

SalTblAnyRows( mytablename, 0 , 0 ) : bu satır eğer data varsa TRUE döndürecektir.

Centura - TableWindow Refresh

Table window

refresh
*****************************
!!CB!! 174
Call tbwEngPartStructureConsistOf.DataSourceRefresh( METHOD_Execute )

IFS - Kısa Yoldan Ekrana Yetki Verme

Oracle daki IFS application owner schema da (Orneğin IFSAPP ), aşağıdakine benzer
plsql kodu uygulanarak istenilen ekrana kolayca yetki verilebilir.
Bu iş admin.exe arayüzünden bazen çok zor yapılabiliyor.

BEGIN
ifsapp.Security_SYS.Grant_Pres_Object( 'frmWorkOrderReportInTab', 'UZM_BAKIM', 'TRUE', 'TRUE' );
commit;
EXCEPTION
WHEN OTHERS THEN
rollback;
raise;
END;

Kullanım Detayları
******************************
ifsapp.Security_SYS.Grant_Pres_Object('yetkiverilecekekranismi','Rol_ismi','TRUE','TRUE')

CENTURA - TableWindow a süzerek data getirme

On SAM_Click
Set sOlusturulanSql = "doc_class = 'EYS' "
! ---------------------------------------------------------------------
! ---------------------------------------------------------------------
Call SalSendMsg( tbwUzmarDocIssues, PM_DataSourceUserWhere, METHOD_Execute, SalHStringToNumber( sOlusturulanSql ) )
Call SalSendMsg( tbwUzmarDocIssues, PM_DataSourcePopulate, METHOD_Execute, 0 )

Centura - Tablomda veri var mı?

Aşağıdaki örnekteki fonksiyonu kullanarak,
herhangibir cTableWindow veya cChildWindow dan
miras alınarak yapılmış object içinde
satır olup olmadığı test edebilirsiniz.


If SalTblAnyRows( mytablename, 0 , 0 )
..çeşitli işler..


SalTblAnyRows( mytablename, 0 , 0 ) : bu satır eğer data varsa TRUE döndürecektir.

Centura - TableWindow un kaçıncı satırındayım?

TableWindow.RecNo
------------------------
nContext = SalTblQueryContext ( hWndTbl )

Centura - Tarih

Örnek
******************************************
!!CB!! 173
On SAM_Click
If SalIsValidDateTime(df1)
Set df1 = SalFmtFormatDateTime ( (SalStrToDate(df1) + 1), 'dd.MM.yyyy' )
Else
Call SalMessageBox('Girilen tarih gg.aa.yyyy formatında olmalıdır. (Örn.

01.11.2010)','HATA!',MB_Ok)
Call SalSetFocus ( df1 )


Bir sonraki günü nasıl bulurum?
*******************************
Set dDateDegisken = dDateDegisken + 1

Yukarıdaki komut satırı,
dDateDegisken içerisindeki tarihe bir gun
eklenmesini sağlayacaktır.




Bir string değerin valid bir tarih olup
olmadığını nasıl test edebilirim ?
*****************************************
If SalIsValidDateTime(df1)
.......gecerli bir tarih degeriyse yapilacak cesitli isler
Else
.......gecerli bir tarih degeriyse yapilacak cesitli isler




Bir tarih değerini istenen formatta
nasıl yazdırabilirim?
********************************************
Set df1 = SalFmtFormatDateTime ( dBirDate ), 'dd.MM.yyyy' )




KULLANILABİLECEK FORMAT AÇIKLAMALARI
**************************************************************

Valid date/time picture format values:

Value Item Appearance
M month 1-12
MM month 01-12
MMM month Jan-Dec
MMMM month January-December
d day 1-31
dd day 01-31
ddd day Mon-Sun
dddd day Monday-Sunday
yy year 00-99
yyyy year 0000-9999
hh hour 1-12
hhhh hour 0-24
mm minutes 0-59
ss seconds 0-59
mmmmmm microseconds 000000-999999
AMPM AM/PM The AM/PM indicator
Examples of date/time picture format mappings:

Date/Time Picture Meaning
d MMMM, yyyy 9 January, 1992
dddd, MMMM d, yyyy Friday, February 7, 1992
M/d/yy 3/18/92
dd-MM-yyyy 18-03-1992
d “of” MMMM, yyyy 9 of January, 1992
M/d/yy-hh.mm.ss AMPM 2/3/92-12.23.15 AM

Centura - Form açılışında label a tarih yazmak

On SAM_Create
...Set df1 = SalFmtFormatDateTime ( SalDateCurrent() , 'dd.MM.yyyy' )
...Call SalSendClassMessage ( SAM_Create, wParam, lParam )

Centura - Veri tipi dönüşümleri

String ten sayıya dönüşüm (SalStrToNumber)
******************************************

SalStrToNumber komutunu stringten sayıya dönüşüm
gerekli olduğunda kullanın. Foksiyon otomatik
yuvarlama yapmaktadır.

strString : Sayıya dönüştürmek istene string deger
nNumber : dönüşüm sonucu .

Örn :
Set nNumber = SalStrToNumber ( '100,22' ) !nNumber=100
Set nNumber = SalStrToNumber ( '100,51' ) !nNumber=101
Set nNumber = SalStrToNumber ( '100.51' )
!nNumber=0 çevirme esnasında hata oluşursa 0 dönecektir.

Sayıdan string e dönüşüm
************************
nLength = SalNumberToStr ( nNumber, nDecimalPlaces, strString )
veya
strString = SalNumberToStrX ( nNumber, nDecimalPlaces )

Bir sayıyı string e çevirmek için kullanın


nNumber Number. Dönüştürülecek sayı.
nDecimalPlaces Number. strString e eklenecek virgülden sonraki basamak sayısı.
0 verirseniz sadece tam sayı kısmı dönüştürülecektir.

strString Number tipine dönüştürülen string değer.

nLength , ondalık basamaklar ile beraber strString uzunluğudur.

strString ,nNumber değerinin string e çevirilmiş halidir.


String ten date e dönüşüm
************************

dtDateTime = SalStrToDate ( strString )

String bir değeri date/time değerine dönüştürmek için kullanın.
SalStrToDate fonksiyonu sistem tarih formatını kullanır.
Format sorunu durumlarında SalDateConstruct fonksiyonu
işinize yarayacaktır. Aşağıdaki örneklerde bu fonksiyonda
kullanılmıştır.

Örnek
! Set dDeneme = SalDateConstruct ( nYear, nMonth, nDay, nHour, nMinute, nSecond )
! Aşağıdaki iki satırda dDeneme isimli Date/Time değişkene atama yapılmaktadır.
Set dDeneme = SalDateConstruct ( 2009, 01, 26, 11, 10, 05 )
Set dDeneme = SalStrToDate ( '2009-01-26-10.43.43.480000' )
Call SalDateToStr(dDeneme, df2)

Date ten string e dönüşüm
*************************
nLength = SalDateToStr ( dtDateTime, strDate )

Bir date/time değerini string değerine dönüştürür.
Eğer parametre olarak DATETIME_Null gönderilmiş ise
-1 döndürür.

Parametreler

dtDateTime Date/Time. String e dönüştürülecek değer.

strDate . Dönüştürülmüş string değer.

nLength, dönüştürülen string uzunluğudur.

Örnek:
Call SalDateToStr ( SalDateCurrent ( ), df2 )
!df2 edit box unda şu anki tarih görüntülenir.


Aşağıdaki fonksiyonlar da incelenebilir.
SalFmtFormatDateTime
SalFmtFormatNumber
SalFmtIsValidPicture
SalFmtGetPicture
SalFmtSetPicture

PlSql içerisinde bekleme

Bazen PlSql kodu içerisinde bekleme yaratmak gerekebilir. Bu tür durumlarda
aşağıdaki yöntem kullanılmalıdır.

Örnek
**********************
/* 60 sn. bekleme */

execute dbms_lock.sleep(60);


/* 1 saat bekleme */

execute dbms_lock.sleep(3600);


SLEEP Procedure
***********************
Bu procedure kullanıcı session ını, verilen süre kadar askıya alır.

Syntax

DBMS_LOCK.SLEEP (
seconds IN NUMBER);

Parametre açıklaması
****************************
seconds
Askıya alınmanın kaç saniye süreceğini belirtir.

En küçük bekleme miktarı saniyenin yüzde biri kadar olabilir.
Örneğin, 1.95 geçerli bir zaman değeridir.

Verilen string için MD5 değerini döndüren oracle func.

CREATE OR REPLACE FUNCTION get_md5_val (p_in VARCHAR2)
RETURN VARCHAR2
IS
--bu fonksiyon verilen string icin md5 degeri hesaplar
l_hash VARCHAR2 (2000);
BEGIN
l_hash :=RAWTOHEX(UTL_RAW.cast_to_raw(DBMS_OBFUSCATION_TOOLKIT.md5 (input_string=> p_in)));
RETURN l_hash;
END;


Örnek
**********************

select get_md5_val ('abc') from dual

1 Temmuz 2009 Çarşamba

Developing with SQLWindows

"Developing with SQLWindows"
dökümanını aşağıdaki linki kullanarak indirebilirsiniz.

You can download "Developing with SQLWindows" document
via following link.


http://rapidshare.com/files/250572193/dev.pdf.html

Introducing Centura Team Developer

"Introducing Centura Team Developer"
dökümanını aşağıdaki linki kullanarak indirebilirsiniz.

You can download "Introducing Centura Team Developer" document
via following link.

http://rapidshare.com/files/250571312/intro.pdf.html

Centura SQLWindows Function Reference

"Centura SQLWindows Function Reference"
dökümanını aşağıdaki linkten indirebilirsiniz.

You can download "Centura SQLWindows Function Reference" document
via following link.

http://rapidshare.com/files/250570109/Funcref.pdf.html

26 Mayıs 2009 Salı

PLSQL kullanarak merkez bankası doviz kurlarını internetten alabilir miyim? (PART III)

Aşağıdaki prosedürü bir job içerisine yerleştirerek kullanıyorum.
Bu procedure ile birlikte döviz alma işlemini tamamlamış bulunuyoruz.
Burada ben dolar,sterlin ve euro ve çapraz kurları tabloya insert ediyorum.
Kodu değiştirerek istediğiniz kurları ekleyebilirsiniz.
Aşağıdaki kodu toad a yapıştırıp FormatCode(Shift+Ctrl+F)
tuşlarına basarsanız daha anlaşılır olacaktır.

----------------------------------------------------------
---Purpose : This procedure creates currency rates into PAR_CURRENCY_RATES table
--- via http://www.tcmb.gov.tr/kurlar/today.xml
--- This procedure runs in a job.
---Date : 28.05.2009
---Responsible :BAkverdi
----------------------------------------------------------
PROCEDURE Set_Daily_Currencies IS
gelen_data_ UTL_HTTP.html_pieces;
alinan_sayfa_ NUMBER;
gelen_data_textclob_ CLOB;
--xml parse ile ilgili degiskenler
l_parser DBMS_XMLPARSER.parser;
l_doc DBMS_XMLDOM.domdocument;
l_nl DBMS_XMLDOM.domnodelist;
l_n DBMS_XMLDOM.domnode;
l_temp VARCHAR2 (1000);

TYPE tab_type IS TABLE OF par_currency_rates%ROWTYPE;

t_tab tab_type := tab_type ();
l_nodemap DBMS_XMLDOM.domnamednodemap;
l_attr_node DBMS_XMLDOM.domnode;
--xml parse ile ilgili degiskenler
valid_date_ DATE;
para_birimi_ VARCHAR2 (50);
para_birimi_alis_ VARCHAR2 (100);
para_birimi_satis_ VARCHAR2 (100);
para_birimi_ortalama_deger_ NUMBER;
ortalama_usd_deger_ NUMBER;
ortalama_euro_deger_ NUMBER;
ortalama_gbp_deger_ NUMBER;
BEGIN
--http://www.tcmb.gov.tr/kurlar/today.xml den gunluk doviz kurlari aliniyor
--http://www.tcmb.gov.tr/kurlar/today.xml den gunluk doviz kurlari aliniyor
gelen_data_ :=
UTL_HTTP.request_pieces ('http://www.tcmb.gov.tr/kurlar/today.xml',
100);

--dbms_output.put_line(gelen_data_.count || ' pieces were retrieved.');
--dbms_output.put_line('with total length ');
IF gelen_data_.COUNT < 1
THEN
DBMS_OUTPUT.put_line ('0');
ELSE
DBMS_OUTPUT.put_line ( (2000 * (gelen_data_.COUNT - 1))
+ LENGTH (gelen_data_ (gelen_data_.COUNT))
);
END IF;

--dbms_output.put_line(gelen_data_(1));
alinan_sayfa_ := 1;
gelen_data_textclob_ := NULL;

IF gelen_data_.COUNT > 0
THEN
LOOP
gelen_data_textclob_ :=
gelen_data_textclob_ || gelen_data_ (alinan_sayfa_);
alinan_sayfa_ := alinan_sayfa_ + 1;

--dbms_output.put_line('sayfa : '||alinan_sayfa_);
IF alinan_sayfa_ = gelen_data_.COUNT + 1
THEN
EXIT;
END IF;
END LOOP;
END IF;

--dbms_output.put_line(gelen_data_textClob_);
--http://www.tcmb.gov.tr/kurlar/today.xml den gunluk doviz kurlari aliniyor
--http://www.tcmb.gov.tr/kurlar/today.xml den gunluk doviz kurlari aliniyor


--Merkez bankasi XML inden doviz kurlarinin gecerlilik tarihi aliniyor..(valid_date_)
--Merkez bankasi XML inden doviz kurlarinin gecerlilik tarihi aliniyor..
-- Create a parser.
l_parser := DBMS_XMLPARSER.newparser;
-- Parse the document and create a new DOM document.
DBMS_XMLPARSER.parseclob (l_parser, gelen_data_textclob_);
l_doc := DBMS_XMLPARSER.getdocument (l_parser);
-- Free resources associated with the CLOB and Parser now they are no longer needed.
DBMS_LOB.freetemporary (gelen_data_textclob_);
DBMS_XMLPARSER.freeparser (l_parser);
-- Get a list of all the Tarih_Date nodes in the document using the XPATH syntax.
l_nl :=
DBMS_XSLPROCESSOR.selectnodes (DBMS_XMLDOM.makenode (l_doc),
'/Tarih_Date'
);
DBMS_OUTPUT.put_line (DBMS_XMLDOM.getlength (l_nl));
l_n := DBMS_XMLDOM.item (l_nl, 0);
--dbms_xslprocessor.valueOf(l_n,'Tarih/text()',gecici,null);
l_nodemap := DBMS_XMLDOM.getattributes (l_n);
l_attr_node := DBMS_XMLDOM.getnameditem (l_nodemap, 'Tarih');
valid_date_ :=
TO_DATE (DBMS_XMLDOM.getnodevalue (l_attr_node), 'DD.MM.YYYY');
DBMS_OUTPUT.put_line (valid_date_);
--Merkez bankasi XML inden doviz kurlarinin gecerlilik tarihi aliniyor..
--Merkez bankasi XML inden doviz kurlarinin gecerlilik tarihi aliniyor..


--Merkez bankasindan sadece usd,eur ve sterlin degerlerini aliyorum...
--Merkez bankasindan sadece usd,eur ve sterlin degerlerini aliyorum...
-- Get a list of all the Tarih_Date nodes in the document using the XPATH syntax.
l_nl :=
DBMS_XSLPROCESSOR.selectnodes (DBMS_XMLDOM.makenode (l_doc),
'/Tarih_Date/Currency'
);
DBMS_OUTPUT.put_line (DBMS_XMLDOM.getlength (l_nl));

-- Loop through the list and create a new record in a tble collection
-- for each EMP record.
FOR cur_dvz IN 0 .. DBMS_XMLDOM.getlength (l_nl) - 1
LOOP
l_n := DBMS_XMLDOM.item (l_nl, cur_dvz);
DBMS_XSLPROCESSOR.valueof (l_n, 'CurrencyName/text()', para_birimi_);

--dbms_output.put_line('para_birimi : '||para_birimi_); --tum para birimleri yaziyor
IF para_birimi_ IN ('US DOLLAR', 'EURO', 'POUND STERLING')
THEN
-- Use XPATH syntax to assign values to he elements of the collection.
-- 1 (TL) 2 (GBP) 3 (EURO) 4 (USD)
IF para_birimi_ = 'US DOLLAR'
THEN
t_tab.EXTEND;
t_tab (t_tab.LAST).currency_from := '4';
t_tab (t_tab.LAST).currency_to := '1';
END IF;

IF para_birimi_ = 'EURO'
THEN
t_tab.EXTEND;
t_tab (t_tab.LAST).currency_from := '3';
t_tab (t_tab.LAST).currency_to := '1';
END IF;

IF para_birimi_ = 'POUND STERLING'
THEN
t_tab.EXTEND;
t_tab (t_tab.LAST).currency_from := '2';
t_tab (t_tab.LAST).currency_to := '1';
END IF;

DBMS_XSLPROCESSOR.valueof (l_n,
'ForexBuying/text()',
para_birimi_alis_
);
DBMS_XSLPROCESSOR.valueof (l_n,
'ForexSelling/text()',
para_birimi_satis_
);
para_birimi_ortalama_deger_ :=
( TO_NUMBER (para_birimi_alis_, '999999999.9999')
+ TO_NUMBER (para_birimi_satis_, '999999999.9999')
)
/ 2;
t_tab (t_tab.LAST).VALUE := para_birimi_ortalama_deger_;
t_tab (t_tab.LAST).valid_date := valid_date_;

--BU DEGISKENLER CAPRAZ KURLAR ICIN KULLANILACAK
--HER DEGER TL KARSILIGINI IFADE EDIYOR
IF para_birimi_ = 'US DOLLAR'
THEN
ortalama_usd_deger_ := para_birimi_ortalama_deger_;
END IF;

IF para_birimi_ = 'EURO'
THEN
ortalama_euro_deger_ := para_birimi_ortalama_deger_;
END IF;

IF para_birimi_ = 'POUND STERLING'
THEN
ortalama_gbp_deger_ := para_birimi_ortalama_deger_;
END IF;
--BU DEGISKENLER CAPRAZ KURLAR ICIN KULLANILACAK
--HER DEGER TL KARSILIGINI IFADE EDIYOR
END IF;
END LOOP;

--Merkez bankasindan sadece usd,eur ve sterlin degerlerini aliyorum...
--Merkez bankasindan sadece usd,eur ve sterlin degerlerini aliyorum...


--Capraz kurlar gecici t_tab dizi tablosuna ekleniyor
--Capraz kurlar gecici t_tab dizi tablosuna ekleniyor
-- 1 (TL) 2 (GBP) 3 (EURO) 4 (USD)
--TL to GBP
t_tab.EXTEND;
t_tab (t_tab.LAST).currency_from := '1';
t_tab (t_tab.LAST).currency_to := '2';
t_tab (t_tab.LAST).VALUE := 1 / ortalama_gbp_deger_;
t_tab (t_tab.LAST).valid_date := valid_date_;
--TL to GBP
--TL to EUR
t_tab.EXTEND;
t_tab (t_tab.LAST).currency_from := '1';
t_tab (t_tab.LAST).currency_to := '3';
t_tab (t_tab.LAST).VALUE := 1 / ortalama_euro_deger_;
t_tab (t_tab.LAST).valid_date := valid_date_;
--TL to EUR
--TL to USD
t_tab.EXTEND;
t_tab (t_tab.LAST).currency_from := '1';
t_tab (t_tab.LAST).currency_to := '4';
t_tab (t_tab.LAST).VALUE := 1 / ortalama_usd_deger_;
t_tab (t_tab.LAST).valid_date := valid_date_;
--TL to USD
-- 1 (TL) 2 (GBP) 3 (EURO) 4 (USD)
--GBP to EURO
t_tab.EXTEND;
t_tab (t_tab.LAST).currency_from := '2';
t_tab (t_tab.LAST).currency_to := '3';
t_tab (t_tab.LAST).VALUE := ortalama_gbp_deger_ / ortalama_euro_deger_;
t_tab (t_tab.LAST).valid_date := valid_date_;
--GBP to EURO
--GBP to USD
t_tab.EXTEND;
t_tab (t_tab.LAST).currency_from := '2';
t_tab (t_tab.LAST).currency_to := '4';
t_tab (t_tab.LAST).VALUE := ortalama_gbp_deger_ / ortalama_usd_deger_;
t_tab (t_tab.LAST).valid_date := valid_date_;
--GBP to USD
-- 1 (TL) 2 (GBP) 3 (EURO) 4 (USD)
--EURO to GBP
t_tab.EXTEND;
t_tab (t_tab.LAST).currency_from := '3';
t_tab (t_tab.LAST).currency_to := '2';
t_tab (t_tab.LAST).VALUE := ortalama_euro_deger_ / ortalama_gbp_deger_;
t_tab (t_tab.LAST).valid_date := valid_date_;
--EURO to GBP
--EURO to USD
t_tab.EXTEND;
t_tab (t_tab.LAST).currency_from := '3';
t_tab (t_tab.LAST).currency_to := '4';
t_tab (t_tab.LAST).VALUE := ortalama_euro_deger_ / ortalama_usd_deger_;
t_tab (t_tab.LAST).valid_date := valid_date_;
--EURO to USD
-- 1 (TL) 2 (GBP) 3 (EURO) 4 (USD)
--USD to GBP
t_tab.EXTEND;
t_tab (t_tab.LAST).currency_from := '4';
t_tab (t_tab.LAST).currency_to := '2';
t_tab (t_tab.LAST).VALUE := ortalama_usd_deger_ / ortalama_gbp_deger_;
t_tab (t_tab.LAST).valid_date := valid_date_;
--USD to GBP
--USD to EURO
t_tab.EXTEND;
t_tab (t_tab.LAST).currency_from := '4';
t_tab (t_tab.LAST).currency_to := '3';
t_tab (t_tab.LAST).VALUE := ortalama_usd_deger_ / ortalama_euro_deger_;
t_tab (t_tab.LAST).valid_date := valid_date_;

--USD to EURO
--Capraz kurlar gecici t_tab dizi tablosuna ekleniyor
--Capraz kurlar gecici t_tab dizi tablosuna ekleniyor


--Hazirlanan DATA , PAR_CURRENCY_RATES tablosuna insert ediliyor
--Hazirlanan DATA , PAR_CURRENCY_RATES tablosuna insert ediliyor
--Eger valid date i ayni gun olan kayit varsa temizleniyor...
DELETE FROM par_currency_rates
WHERE valid_date = valid_date_;
--Eger valid date i ayni gun olan kayit varsa temizleniyor...
--Guncel data insert inden Insert ten once eski valid kayitlar invalid ediliyor.
UPDATE par_currency_rates set is_valid = 0 where is_valid = 1;

FOR cur_row IN t_tab.FIRST .. t_tab.LAST
LOOP
INSERT INTO par_currency_rates
(currency_from,
currency_to, VALUE,
valid_date,
is_valid
)
VALUES (t_tab (cur_row).currency_from,
t_tab (cur_row).currency_to, t_tab (cur_row).VALUE,
t_tab (cur_row).valid_date,
1
);
END LOOP;
--Hazirlanan DATA , PAR_CURRENCY_RATES tablosuna insert ediliyor
--Hazirlanan DATA , PAR_CURRENCY_RATES tablosuna insert ediliyor
COMMIT;
EXCEPTION
WHEN OTHERS
THEN
--err_num := SQLCODE;
--err_msg := SUBSTR(SQLERRM, 1, 100);
DBMS_OUTPUT.put_line ( 'Error Number: '
|| SQLCODE
|| 'Error Message:'
|| SUBSTR (SQLERRM, 1, 100)
);
DBMS_LOB.freetemporary (gelen_data_textclob_);
DBMS_XMLPARSER.freeparser (l_parser);
DBMS_XMLDOM.freedocument (l_doc);
ROLLBACK;
END Set_Daily_Currencies;

23 Mayıs 2009 Cumartesi

PLSQL kullanarak merkez bankası doviz kurlarını internetten alabilir miyim? (PART II)

İçerisinde döviz kurlarını tutacağım tablo scripti aşağıdaki gibi.

CREATE TABLE DEVELOPER.PAR_CURRENCY_RATES
(
PAR_CURRENCY_RATES_ID NUMBER(10),
CURRENCY_FROM NUMBER(2),
CURRENCY_TO NUMBER(2),
VALUE NUMBER(10,3),
CREATE_DATE DATE,
VALID_DATE DATE,
IS_VALID NUMBER(1) DEFAULT 0
)

Burada;

PAR_CURRENCY_RATES_ID : primary key
CURRENCY_FROM : hangi currency
CURRENCY_TO : hangi currency ye dönüşecek
VALUE : dönüşüm çarpanı ne
CREATE_DATE : oluşturma trh.
VALID_DATE : Geçerlilik tarihi
IS_VALID : 1 ise en son geçerli olan kayıt. 0 ise valid değil

Bu tabloya hergün çalışan bir job içinden yazacağımız procedure miz
yoluyla kayıt ekleyeceğiz.

Sonraki yazıda bu procedure yi inceleyeceğiz.

18 Mayıs 2009 Pazartesi

PLSQL kullanarak merkez bankası doviz kurlarını internetten alabilir miyim?

Bu makalede belirli bir URL üzerinden
plsql kullanarakdosya transferini
anlatıyorum. Sonraki yazımda merkez bankası döviz
kurlarını bir tabloya insert etme örneğini
gerçekleştireceğiz.

PLSQL ile web uzerinden bir url iceriğinin alınması
için UTL_HTTP paketi kullanılabilir.
Aşağıdaki örnekte merkez bankası günlük döviz
kurları internet üzerinden alınmaktadır.
Bu şekilde herhangibir html,xml vb. tür dosya
alınabilir.

DECLARE
gelen_data_ utl_http.html_pieces;
alinan_sayfa_ NUMBER;
gelen_data_textClob_ CLOB;
--xml parse ile ilgili degiskenler
l_parser dbms_xmlparser.Parser;
l_doc dbms_xmldom.DOMDocument;
l_nl dbms_xmldom.DOMNodeList;
l_n dbms_xmldom.DOMNode;
l_temp VARCHAR2(1000);
TYPE tab_type IS TABLE OF PAR_CURRENCY_RATES%ROWTYPE;
t_tab tab_type := tab_type();
l_nodemap DBMS_XMLDOM.domnamednodemap;
l_attr_node DBMS_XMLDOM.domnode;
--xml parse ile ilgili degiskenler
BEGIN
--http://www.tcmb.gov.tr/kurlar/today.xml den gunluk doviz kurlari aliniyor
--http://www.tcmb.gov.tr/kurlar/today.xml den gunluk doviz kurlari aliniyor
gelen_data_ := utl_http.request_pieces('http://www.tcmb.gov.tr/kurlar/today.xml', 100);
dbms_output.put_line(gelen_data_.count || ' pieces were retrieved.');
dbms_output.put_line('with total length ');
IF gelen_data_.count < 1
THEN dbms_output.put_line('0');
ELSE dbms_output.put_line
((2000 * (gelen_data_.count - 1)) + length(gelen_data_(gelen_data_.count)));
END IF;
--dbms_output.put_line(gelen_data_(1));
alinan_sayfa_ := 1;
gelen_data_textClob_ := NULL;
IF gelen_data_.count > 0 THEN
LOOP
gelen_data_textClob_ := gelen_data_textClob_ || gelen_data_(alinan_sayfa_);
alinan_sayfa_ := alinan_sayfa_ + 1;
--dbms_output.put_line('sayfa : '||alinan_sayfa_);
IF alinan_sayfa_ = gelen_data_.count + 1 THEN
EXIT;
END IF;
END LOOP;
END IF;
dbms_output.put_line(gelen_data_textClob_);
--http://www.tcmb.gov.tr/kurlar/today.xml den gunluk doviz kurlari aliniyor
--http://www.tcmb.gov.tr/kurlar/today.xml den gunluk doviz kurlari aliniyor
END;

Oracle 11g kullanıyorsanız yukarıdaki blok hata verecektir.
ORA-24247: network access denied by access control list (ACL)

Oracle 11g ile gelen ek güvenlik dolayısıyla eğer
11g kullanıyorsanız aşağıdaki kodları çalıştırarak
almak istediğiniz dosya ve url yi ACL içerisine
eklemelisiniz.Burada "DEVELOPER", yetki verilmek
istenilen oracle user dır.

begin
dbms_network_acl_admin.create_acl (
acl => 'today.xml',
description => 'merkez bankasi gunluk doviz kurlari',
principal => 'DEVELOPER',
is_grant => true,
privilege => 'connect',
start_date => null,
end_date => null
);
end;

begin
DBMS_NETWORK_ACL_ADMIN.ADD_PRIVILEGE(acl => 'today.xml',
principal => 'DEVELOPER',
is_grant => true,
privilege => 'resolve');
end;

begin
DBMS_NETWORK_ACL_ADMIN.ASSIGN_ACL(acl => 'today.xml',
host => 'www.tcmb.gov.tr');
end;

Bu güvenlik sistemi ile ilgili ayrıntılı bilgi için aşağıdaki
linki inceleyebilirsiniz.

http://johanlouwers.blogspot.com/2009/01/ora-24247-network-access-denied-by.html

Eğer başarıyla yetki verdiyseniz aşağıdaki SQL
çalıştığında sonuçlar arasında today.xml yer alacaktır.

select * from dba_network_acl_privileges

30 Nisan 2009 Perşembe

Nasıl TableWindow kolonunun arka plan rengi değiştirilir?

TableWindow kolonuna ait arkaplan rengini değiştirmek için XSalTblSetColumnBackColor
fonksiyonu kullanılabilir. Bu fonksiyon xsal2_32.dll içerisindeki tablewindow
external fonksiyonlarından birisidir. External fonksiyonlar arasında olmaması durumunda aşağıdaki kod ile kolayca ekleyebilirsiniz.

!!CB!! 145
Function: XSalTblSetColumnBackColor
Description: BOOL XSalTblSetColumnBackColor(
HWND p_hwndCol,
COLORREF p_cBackColor );
Export Ordinal: 0
Returns
Boolean: BOOL
Parameters
Window Handle: HWND
Number: LONG



Bu fonksiyon kullanılarak aşağıda verilen kod orneğini değiştirerek kendi istediğiniz sütunların rengini değiştirebilirsiniz.

!!CB!! 173
On SAM_CreateComplete
Call SalSendClassMessage ( SAM_CreateComplete, wParam, lParam )
Call XSalTblSetColumnBackColor( tbwUzmarGunYmk.colnMiktar1, COLOR_LightGreen )
Call XSalTblSetColumnBackColor( tbwUzmarGunYmk.colnMiktar2, COLOR_LightGreen )
Call XSalTblSetColumnBackColor( tbwUzmarGunYmk.colnMiktar3, COLOR_LightGreen )
Call XSalTblSetColumnBackColor( tbwUzmarGunYmk.colnMiktar4, COLOR_LightGreen )
Call XSalTblSetColumnBackColor( tbwUzmarGunYmk.colnMiktar5, COLOR_LightGreen )
Call XSalTblSetColumnBackColor( tbwUzmarGunYmk.colsAciklama, COLOR_LightGreen )
On PM_DataSourcePopulate
Call SalSendClassMessage ( PM_DataSourcePopulate, wParam, lParam )
Call XSalTblSetColumnBackColor( tbwUzmarGunYmk.colnMiktar1, COLOR_LightGreen )
Call XSalTblSetColumnBackColor( tbwUzmarGunYmk.colnMiktar2, COLOR_LightGreen )
Call XSalTblSetColumnBackColor( tbwUzmarGunYmk.colnMiktar3, COLOR_LightGreen )
Call XSalTblSetColumnBackColor( tbwUzmarGunYmk.colnMiktar4, COLOR_LightGreen )
Call XSalTblSetColumnBackColor( tbwUzmarGunYmk.colnMiktar5, COLOR_LightGreen )
Call XSalTblSetColumnBackColor( tbwUzmarGunYmk.colsAciklama, COLOR_LightGreen )

27 Nisan 2009 Pazartesi

Centura ekranlarımıza makyaj yapalım.

Pekçok yazılımda kullanılan GUI tekniklerinden, grid sutun/satırlarının renklendirilmesi ve TAB yerine ENTER kullanımı, hem kullanıcı eğitimleri hem de kullanım açısından avantajlar yaratmaktadır. Sonraki makalede TAB yerine ENTER tuşunun kullanılması ve centura tablewindow sutununun renklendirmesi konularını anlatacağım. Bu teknikler kullanılarak hazırlanmış form örneği aşağıdadır.

17 Nisan 2009 Cuma

LOV icin filtreleme örneği

cColumn altındaki action alanına aşağıdakine benzer
kod yazılarak lov un filtrelenmesi sağlanabilir.

On PM_DataItemLovUserWhere
...Return SalHStringToNumber("ALANADINEYSEO='biseybisey'")

'biseybisey' yerine :i_hWndFrame.frmTRHAKTEVZI.tblDetail.coldDated
gibi bir referans ile örneğin bir table veya
formdan data alarak lov u filtrelemek te mümkündür.

burada ALANADINEYSEO, LOV a temel olan view deki
fieldname i temsil etmektedir.

Bir Centura penceresini, başka bir pencereden belirli bir kaydı seçerek açma

Bir ekrandan diğerine, parametre
aktararak geçiş, kullanıcıya hız kazandıran bir opsiyondur.
Bu makalede centurada bunun nasıl yapıldığına
ilişkin bir örnek uygulama inceleyeceğiz.

Örneğimiz nasıl çalışır?
---------------------
Parametre göndererek açmak istediğimiz formun adı X olsun.

Önce global bir değişken tanımlıyoruz.
Sonra X formunu açan window, belirli bir durumda
(Örn. içindeki bir buton tıklanılınca) bu global
değişkeni set ediyor ve X formunu açıyor.
X formu kendi açılış olayında da bu parametre dolu mu acaba diye
kontrol ediyor. Eğer doluysa kayıtlarımızı bu
parametreye göre filtreliyoruz.

Adım adım anlatmak gerekirse...


*******1************************
Formların üzerindeki bölgede gerekli global değişken tanımlanır.

variables
------------
!!CB!! 223
String: __g_sGecici



*******1************************


*******2************************


Açılacak forma aşağıdaki koda benzer kod eklenir. Bu forma X formu diyelim.

variables
------------
!!CB!! 118
String: sGeciciSql


Actions
------------
!!CB!! 173
On SAM_CreateComplete
If __g_sGecici != STRING_Null
Set sGeciciSql = "dagitim_no = '" || __g_sGecici || "'"
Call SalSendMsg(
hWndForm,
PM_DataSourceUserWhere, METHOD_Execute,
SalHStringToNumber( sGeciciSql )
)
Call SalSendMsg( hWndForm, PM_DataSourcePopulate, METHOD_Execute, 0 )
Call SalSendClassMessage ( SAM_CreateComplete, wParam, lParam )
On SAM_Close
Set __g_sGecici = STRING_Null
Call SalSendClassMessage ( SAM_Close, wParam, lParam )

*******2************************

*******3************************
X formunu açacak forma aşağıdaki kod eklenir.

Actions
------------
!!CB!! 139
Set __g_sGecici = tbwUzmarDokDagitim.colsDagitimNo
Call SalCreateWindow( 'frmUzmarDokDagitim', hWndMDI )


*******3************************

8 Nisan 2009 Çarşamba

Table window-kayıtlar arasında dolaşma ve bir kolona focus örneği

Sonraki kayıt ve belirli bir sütuna focus örneği.
*************************************************
If tbwUzmarGunYmk.DataContextNext( METHOD_Inquire )
...Call tbwUzmarGunYmk.DataContextNext( METHOD_Execute )
...Set nGecici = SalTblQueryContext ( tbwUzmarGunYmk )
...Call SalTblSetFocusCell ( tbwUzmarGunYmk, nGecici, colnMiktar1, 0, 1 )

tbwUzmarGunYmk : table window ismi
nGecici : number türündeki değişken. tbwUzmarGunYmk a ait "Variable" tabında
tanımlanmış olmalıdır.
colnMiktar1 : focus olunacak kolon.

SalTblQueryContext ( tbwUzmarGunYmk ) bize üzerinde bulunduğumuz
satır/row numarasını döndürmektedir.

Burada eğer varsa sonraki satıra hareket ediliyor ve oradaki
colnMiktar1 isimli kolon seçiliyor. ileri, geri,sonkayıt,ilkkayıt
a gitme işlemleri için kullanılabilecek fonksiyon listesi aşağıdadır.

DataContextFirst --ilk kayıt
DataContextLast --son kayıt
DataContextNext --sonraki kayıt
DataContextPrevious --önceki kayıt

ENTER tuşu da TAB gibi davransın istiyorum. Nasıl yaparım?

Bu iş için aşağıdakine benzeyen bir kod, tablewindow kolonunun action una yazılarak kullanılabilir. Burada yapılan kısaca, ENTER e basıldığı anda forma
"TAB a basıldı" mesajının gönderilmesinden ibarettir.

On WM_CHAR
...If (( wParam = VK_Tab ) OR (wParam = VK_Enter))
......Call SalSendMsg ( colnMiktar1, WM_KEYDOWN, VK_Tab, 0 )

Form açılırken bir edit box içine bir değer nasıl girilir?

On SAM_Create
...Set df1 = SalFmtFormatDateTime ( SalDateCurrent() , 'dd.MM.yyyy' )
...Call SalSendClassMessage ( SAM_Create, wParam, lParam )

Bu örnek kod ile, form açılışında, "df1" isimli edit box(cDataField) içerisine çalışılan bilgisayardaki tarih bilgisi kopyalanmaktadır. Buradaki
SalFmtFormatDateTime fonksiyonu, parametre olarak verilen date değerini verilen
kriterlere göre formatlamaktadır.
Sonuçta df1 in içerdiği değer "07.04.2009" gibi string bir değer olacaktır.

"Call SalSendClassMessage ( SAM_Create, wParam, lParam )" satırı
inheritance ile ilgilidir. cDataField classında da On SAM_Create
olayında yapılacak işler belirlidir. Eğer bu satırı yazmaz isek
ata sınıfa ait On SAM_Create olay kodları çalışmayacaktır.

2 Nisan 2009 Perşembe

Centura ile tarih işlemleri nasıl yapılır?

Örnek
******************************************
!!CB!! 173
On SAM_Click
..If SalIsValidDateTime(df1)
......Set df1 = SalFmtFormatDateTime ( (SalStrToDate(df1) + 1), 'dd.MM.yyyy' )
..Else
......Call SalMessageBox('Girilen tarih gg.aa.yyyy
............formatında olmalıdır. (Örn.01.11.2010)','HATA!',MB_Ok)
......Call SalSetFocus ( df1 )


Bir sonraki günü nasıl bulurum?
*******************************
Set dDateDegisken = dDateDegisken + 1

Yukarıdaki komut satırı,
dDateDegisken içerisindeki tarihe bir gun
eklenmesini sağlayacaktır.




Bir string değerin valid bir tarih olup
olmadığını nasıl test edebilirim ?
*****************************************
If SalIsValidDateTime(df1)
.......gecerli bir tarih degeriyse yapilacak cesitli isler
Else
.......gecerli bir tarih degeriyse yapilacak cesitli isler



String ten date e dönüşüm
************************
dtDateTime = SalStrToDate ( strString )

String bir değeri date/time değerine dönüştürmek için kullanın.
SalStrToDate fonksiyonu sistem tarih formatını kullanır.
Format sorunu durumlarında SalDateConstruct fonksiyonu
işinize yarayacaktır. Aşağıdaki örneklerde bu fonksiyonda
kullanılmıştır.

Örnek
! Set dDeneme = SalDateConstruct ( nYear, nMonth, nDay, nHour, nMinute, nSecond )
! Aşağıdaki iki satırda dDeneme isimli Date/Time değişkene atama yapılmaktadır.
Set dDeneme = SalDateConstruct ( 2009, 01, 26, 11, 10, 05 )
Set dDeneme = SalStrToDate ( '2009-01-26-10.43.43.480000' )
Call SalDateToStr(dDeneme, df2)

Date ten string e dönüşüm
*************************
nLength = SalDateToStr ( dtDateTime, strDate )

srtDate değeri, dtDateTime değişkeninin string e dönüşmüş halidir.



Bir tarih değerini istenen formatta
nasıl yazdırabilirim?
********************************************
Set df1 = SalFmtFormatDateTime ( dBirDate ), 'dd.MM.yyyy' )

Yukarıdaki fonksiyon aynı zamanda date i string e çevirmenizide sağlamış olur.
Ek olarak tip dönüşümleri ile ilgili yukarıdaki fonksiyonlar da kullanılabilir.

KULLANILABİLECEK FORMAT AÇIKLAMALARI
**************************************************************

Valid date/time picture format values:

Value Item Appearance
M month 1-12
MM month 01-12
MMM month Jan-Dec
MMMM month January-December
d day 1-31
dd day 01-31
ddd day Mon-Sun
dddd day Monday-Sunday
yy year 00-99
yyyy year 0000-9999
hh hour 1-12
hhhh hour 0-24
mm minutes 0-59
ss seconds 0-59
mmmmmm microseconds 000000-999999
AMPM AM/PM The AM/PM indicator
Examples of date/time picture format mappings:

Date/Time Picture Meaning
d MMMM, yyyy 9 January, 1992
dddd, MMMM d, yyyy Friday, February 7, 1992
M/d/yy 3/18/92
dd-MM-yyyy 18-03-1992
d “of” MMMM, yyyy 9 of January, 1992
M/d/yy-hh.mm.ss AMPM 2/3/92-12.23.15 AM

31 Mart 2009 Salı

TableWindow - Üzerinde bulunduğum satır numarası ne ?

nContext = SalTblQueryContext ( hWndTbl )

26 Mart 2009 Perşembe

Tablomda veri var mı?

Aşağıdaki örnekteki fonksiyonu kullanarak,
herhangibir cTableWindow veya cChildWindow
içinde satır olup olmadığı test edebilirsiniz.

If SalTblAnyRows( mytablename, 0 , 0 )
..çeşitli işler..

aşağıdaki satır eğer tabloda data varsa TRUE döndürecektir.
SalTblAnyRows( mytablename, 0 , 0 )

23 Mart 2009 Pazartesi

Bir IFS/Centura TableWindow a filtrelenmiş kayıt kümesini nasıl getirebilirim?

Aşağıdaki örnek kodu değiştirerek kullanabilirsiniz. İstediğiniz forma bir buton koyduktan sonra Sam_Click (butona tıklama) olayında filtreleme yaparak veri getirebilirsiniz.
Burada sOlusturulanSql değişkeni tanımlanmış olmalıdır. Değişken tanımlama ile ilgili de bir yazım mevcut. İhtiyaç durumunda inceleyebilirsiniz.

On SAM_Click
Set sOlusturulanSql = "doc_class = 'EYS' "
! ---------------------------------------------------------------------
! ---------------------------------------------------------------------
Call SalSendMsg( tbwUzmarDocIssues, PM_DataSourceUserWhere, METHOD_Execute, SalHStringToNumber( sOlusturulanSql ) )
Call SalSendMsg( tbwUzmarDocIssues, PM_DataSourcePopulate, METHOD_Execute, 0 )

Çalışma anında db den getirilecek veri kümesi aşağıdaki gibi olacaktır.

*****************************
select * from formdaki_tablo where sOlusturulanSql
*****************************

Herhangibir IFS Ekranına Nasıl Yetki Veririm?

Ekran tasarlama ile ilgili anlatımlarımızın son ayağını yeni ekrana
yetki verme işlemi oluşturuyor. IFS yazılımı üzerinde ekranların
yetkilendirilmesi çok ayrıntılı ve akılcı olarak ele alınmıştır.
Her ekran için hangi kullanıcı grubunun neler yapabileceği
belirlenebilir. Örneğin "Satınalma" kullanıcı grubu yeni sipariş ekleyebilir
fakat "Stok" kullanıcı grubu sadece görüntüleyebilir gibi.
Ekranda kullanılan her oracle prosedürüne ayrı ayrı yetki verilmesi veya
yetki iptali de mümkündür.

IFS Yetki işleri Admin.Exe kullanılarak gerçekleştirilir.
Ben bu aşamada Admin.exe ile bu işlerin nasıl halledileceğine değinmek yerine
alternatif bir yöntemden bahsetmek istiyorum. İleride Admin.Exe 'den de
bahsedebiliriz.

Pek çok durumda Admin.Exe içerisinde yetki vermek istediğimiz ekranı bulmanın da
problem olduğunu göz önüne alarak bu yöntemin çok işinize yarayacağını düşünüyorum.
Aşağıdaki kodu değiştirerek Toad veya SqlDeveloper vs. programlardan birinde çalıştırabilirsiniz. Aşağıdaki kodu çalıştırmanızın ardından ilgili rol verilmiş olan tüm kullanıcılar belirttiğiniz ekranı tam yetkili olarak kullanabilecektir.
Form adları küçük-büyük harf duyarlıdır. Bu konuya dikkat etmelisiniz.
Bu tür bir yanlışlık yapmanız veya olmayan bir formu parametre olarak vermeniz durumunda hata oluşacaktır.

BEGIN
ifsapp.Security_SYS.Grant_Pres_Object( 'frmWorkOrderReportInTab', 'UZM_BAKIM', 'TRUE', 'TRUE' );
commit;
EXCEPTION
WHEN OTHERS THEN
rollback;
raise;
END;

Kullanım Detayları
******************************
ifsapp.Security_SYS.Grant_Pres_Object('yetkiverilecekekranismi','Rol_ismi','TRUE','TRUE')

17 Mart 2009 Salı

Yeni IFS Ekranı Tasarlama (4)

Evet şimdi elimizde bir IFS ekranı var fakat sadece
ifsapp kullanıcısı veya başka bir değişle sadece application owner ı
tarafından bu ekrana ulaşılabiliyor. Bu noktada bizim
diğer kullanıcılara da bu ekrana erişim izni vermemiz gerekir.
Öncelikle yeni eklenan ekranın ifs ekran yetkilerinin verildiği admin.exe de
görüntülenmesi için yapılması gereken işlemden başlayayım.
Aşağıda bu işlem hakkında adım adım bilgiler verilmektedir.

1) DEVTOOLS.exe çalıştırılır.



2) “Scan Tool” üzerinde çift tıklanır ve ilgili component seçilir.



3) “Add Files” butonu kullanılarak ilgili app uzantılı dosya seçilir.



4) Aşağıda işaretli olan “Scan” butonuna basılır ve yetki nesneleri ile program kodu arasındaki farklar otomatik tespit edilir.



5) Aşağıda gösterilen “Transfer” butonuna basılarak eksikliği belirlenmiş olan nesneler yetki sistemine eklenilir ve işlem tamamlanmış olur. Bu noktadan sonra admin.exe kullanılarak yeni yaptığımız ekrana yetki verebiliriz.

3 Mart 2009 Salı

Yeni IFS Ekranı Tasarlama ( 3 )

Centura ile ekran tasarımı videosu için aşağıdaki linki kullanabilirsiniz.
Bu videoda oluşturduğumuz API ve APY dosyasını kullanarak yeni veri giriş
ekranını IFS içerisine ekliyoruz.

Video için buraya tıklayın...

2 Mart 2009 Pazartesi

Yeni IFS Ekranı Tasarlama (2)

Bu adımda, ihtiyacımız olan tablo tasarımını Rationa Rose ile yaptıktan sonra Design.exe yi kullanarak tablo oluşturma DDL kodunu db ye göndereceğiz. Son aşamada da ekran tasarımında kullanmak üzere API ve APY (oracle package spec. ve body) dosyalarını otomatik text dosya olarak oluşturduktan sonra Admin.exe ile compile ederek database e göndereceğiz.

Aşağıdaki linkte RationalRose ile yaptığım tablo tasarımının ve sonrasında design.exe kullanımı videosu bulunuyor.

Video için buraya tıklayın...

Adım adım anlatacak olursak;

1. Kullanılacak Rose model dosyası (.mdl) açılır.





2. Table eklenilmek istenilen component e ait içerik sayfası açılır.



3. Buraya, eklemek istediğimiz table ın field ve fonksiyonlarını içerecek olan class (table için mantıksal altyapı diyebiliriz.) oluşturulur.



4. Yeni table ımıza ait alanları oluştururuz.



5. Yeni eklediğimiz alanları “Public” konumuna getiririz.



6. Rose model dosyasını kaydederiz. Rational Rose programını kullanarak yapılacak işlerimiz tamamlanmış olur.



7. Design.exe yi çalıştırıp projemizi açarız.



8. Yeni tablomuza ilişkin son ayarlamalar yapılır.



9. Şimdi yeni eklediğimiz deneme4 tablosunu cre dosyamıza ekleyelim.



10. Yeni deneme4 table ımızın yaratılması için gerekli DDL ler zaten oluşturulmuş durumdadır. Bunları cre dosyamıza ekliyoruz.





11. Projemizi ve cre dosyamızı kaydettikten sonra “Deploy CRE” yani DDL leri db ye gönderme işlemine başlıyoruz.





12. Sadece yeni tablomuz için gerekli DDL leri çalıştıralım.



13. Bu aşamada yeni tablomuza ait DDL cümleleri database imize gönderilmiştir. Şimdi gerekli oracle package leri (IFS API ve APY dosyaları) oluşturalım ve database e göndermek kaldı. Önce API ve APY dosyalarımızı export edelim.







14. Admin.exe yi kullanarak API ve APY dosya sını database imize gönderdiğimizde işlem tamamlanmış olur.



26 Şubat 2009 Perşembe

TRUNC() Performansı

Bazen select cümlesi yazarken "between" koşulunu kullanırız.
Eğer "between" ifadesi ile beraber tarih türünde field kullanıyorsak
genellikle TRUNC() fonksiyonu kullanmayı tercih ederiz.

IFS ekranlarını incelediğimizde bu konuyla ilgili, performans noktasında
önemli fark yaratan bir çözüm vardır.

Aşağıda aynı query inin 2 versiyonu gözükmektedir. İlki trunc() fonksiyonunu
kullanır ve 20 dk. kadar sürer. 2. versiyona cevap süresi 1 dk. ya iner.
Tabi bu süreler kayıt sayınıza bağlı değişecektir.

--- 1 ------- 20 dakika ---------------------
trunc(f.promised_delivery_date) BETWEEN xbegin_ AND xend_
--- 1 ------- 20 dakika---------------------

--- 2 ------- < 1 dakika ---------------------
f.promised_delivery_date BETWEEN xbegin_ AND xend_ + ( 1 - 1/ ( 60*60*24 ) )
--- 2 ------- < 1 dakika ---------------------

Bir başka değişle, TRUNC() eşitliğin solunda kullanılırsa
indeks kullanımını iptal eder.

..Önerilmez
****************************************
WHERE TRUNC(trans_date) = TRUNC(sysdate)

..Önerilir
****************************************
WHERE trans_date BETWEEN TRUNC(sysdate) AND
TRUNC(sysdate) + 0.99999

23 Şubat 2009 Pazartesi

Yeni IFS Ekranı Tasarlama (1)

IFS win32 ekranlarının geliştirmesi genellikle iki seviyede gerçekleştirilmektedir.
1) Oracle da gerekli API ve APY dosyalarının iş kuralları çerçevesinde hazırlanması.
API ve APY dosyaları admin.exe kullanılarak çalıştırıldığında oracle üzerinde
bu ekranın çalışması için ihtiyaç duyulan view ler ve package oluşturulmuş olur.
2) Centura da IFS Framework unu kullanarak ekranların oluşturulması.

Biz konumuza API ve APY geliştirme noktasından başlayalım. IFS geliştirmelerinde, gerekli olan oracle package lere esas API ve APY dosyalarının oluşturulması için Rational Rose ve Design.exe kullanılır. Önce gerekli field leri içeren ilişkisel tablolar Rational Rose da tasarlanır ve bir model olarak kaydedilir. Ardından design.exe kullanılarak Rational Rose modelinden elde edilen DDL scripleri database e gönderilir.(Böylece mesela table larımız oluşmuş olur) Yine design.exe kullanılarak API ve APY dosyaları daha sonra üzerinde değişiklik yapmak veya yeniden kullanılmak üzere istenilen klasöre alınır ve database e gönderilir.

APY dosyalar genellikle; package spec, package body ve gerekli view leri içerirler.
Admin.exe bu dosyaları yorumlayarak database e gönderir. Başka bir değişle API ve APY
dosyalar third party tool lar ile DB ye gönderilemezler.
(Örneğin toad,plsql developer)

Bu makalenin bundan sonraki bölümlerini video lar kullanarak desteklemeyi düşünüyorum. Vakit buldukça bloğa ekleyeceğim. Yorumlarınızı bekliyorum.

cRecSelExtComboBox Hakkında

IFS ekranlarında cRecSelExtComboBox combobox’lar, yeni pencere açmadan çoktan seçmeli menü açmak ve bir kayıt seçmek için kullanılırlar. Üzerlerine tıklanıldığında yeni bir küçük pencerede seçim listesi görüntülenir ve burada en soldaki sütuna tıklayarak istediğimiz kaydı seçebiliriz.



cRecSelExtComboBox nesnesi örneklerine ait açılan kutuda kendisine bağlı child nesneler görüntülenir. Görüntülenmesi istenen child a ait foundation1 dialogbox ta “Logical Parent” olarak cRecSelExtComboBox nesnesinin seçilmesi gerekir.
Aşağıdaki örnekte vendorno, ccAgrementNo nesnesine tıklanıldığında açılan pencerede görüntülenir.



cRecSelExtComboBox a tıklanıldığında açılan pencerede alanların üzerindeki başlık bilgisi text itemlardan alınmaktadır.Bu açılan pencedeki sıralama da outline daki sıralamadır. Outline da ata/Parent her zaman mirasçısından/Child yukarıda olmalıdır.



17 Şubat 2009 Salı

Centura kullanarak istenen bir quickreport nasıl açılır?

Burada gösterilen yöntemi kullanarak örneğin herhangibir ekrandan sağ Mouse ile istediğiniz
quickreport u istediğiniz parametrelerle başlatabilirsiniz. İlk yapmamız gereken quickreport umuzun “quick_report_id” değerini öğrenmektir. “select * from quick_report” sorgusu ile öğrenilebilir.



İhtiyacımız olan cMessage class ından bir değişken tanımlıyalım.



İstenilen bölgeye aşağıdaki kod yerleştirilir. Bu kod 1016 quick_report_id li raporu, belirtilen “referansno” parametresi ile başlatacaktır.

!!CB!! 160
Call msg.Construct()
Call msg.SetName( '1016' ) ! 1016 quick_report_id li raporu açacağız.
Call msg.AddAttribute( 'referansno', tbwUzmarOdemeTalimatlari.colsReferansNo ) !referansno param set ediliyor
Call InfoService.QuickReportStart( msg.Pack() ) ! quickreport u aç

16 Şubat 2009 Pazartesi

Verilen iki tarih grubunun kesişimi kaç gün ?

Bu fonsiyon başlangıç ve bitiş tarihi verilen iki
zaman aralığının kesişiminin kaç gün olduğunu döndürür.
Fonksiyonun düzgün çalışabilmesi için
başlama tarihleri, bitiş tarihlerinden küçük olmalıdır.

FUNCTION kesisen_kac_gun_var (
tarih1_bas_ DATE,
tarih1_bit_ DATE,
tarih2_bas_ DATE,
tarih2_bit_ DATE
)
RETURN NUMBER
IS
TYPE sayiarray IS TABLE OF NUMBER
INDEX BY BINARY_INTEGER;

gecici sayiarray;
top_gun NUMBER := 0;
min_ NUMBER;
max_ NUMBER;
BEGIN
IF (tarih1_bas_ IS NULL)
OR (tarih1_bit_ IS NULL)
OR (tarih2_bas_ IS NULL)
OR (tarih2_bit_ IS NULL)
THEN
RETURN 0;
END IF;

min_ :=
LEAST (tarih1_bas_, tarih2_bas_)
- TO_DATE ('01.01.2000', 'dd.mm.yyyy')
- 10; -- +-10 araligi tedbir icic genis tuttum
max_ :=
GREATEST (tarih1_bit_, tarih2_bit_)
- TO_DATE ('01.01.2000', 'dd.mm.yyyy')
+ 10;

--array ın kullanilacak kismi 0 ile set ediliyor
--dbms_output.put_line('min_: ' || min_ || ' max_ : '||max_ );
FOR i IN min_ .. max_
LOOP
gecici (i) := 0; --deger null olursa hata oluşuyor
END LOOP;

--ilk tarih araligi her gun icin -1 ile set ediliyor
FOR i IN 1 .. (tarih1_bit_ - tarih1_bas_)
LOOP
gecici ( TO_DATE (tarih1_bas_, 'dd.mm.yyyy')
- TO_DATE ('01.01.2000', 'dd.mm.yyyy')
+ i
) := -1;
END LOOP;

--bazi -1 ler 1 olarak set ediliyor
FOR i IN 1 .. (tarih2_bit_ - tarih2_bas_)
LOOP
IF gecici ( TO_DATE (tarih2_bas_, 'dd.mm.yyyy')
- TO_DATE ('01.01.2000', 'dd.mm.yyyy')
+ i
) = -1
THEN
gecici ( TO_DATE (tarih2_bas_, 'dd.mm.yyyy')
- TO_DATE ('01.01.2000', 'dd.mm.yyyy')
+ i
) := 1;
END IF;
END LOOP;

--sonuc 1 lerin toplami
FOR i IN LEAST (tarih1_bas_, tarih2_bas_)
- TO_DATE ('01.01.2000', 'dd.mm.yyyy')
- 10 .. GREATEST (tarih1_bit_, tarih2_bit_)
- TO_DATE ('01.01.2000', 'dd.mm.yyyy')
+ 10
LOOP
IF gecici (i) = 1
THEN
top_gun := top_gun + gecici (i);
END IF;
END LOOP;

RETURN top_gun;
END;

Rakamı yazıya dönüştüren oracle foksiyonu

Fonsiyon virgulden sonraki iki basamağı dikkate alır ve yuvarlama yapmaz.

Kullanımı
**************
select rakam2yazi(153922.69, 'YTL') from dual

Sonuç
**************
YÜZELLİÜÇBİNDOKUZYÜZYİRMİİKİ YTL ALTMIŞDOKUZ KURUS

create or replace FUNCTION rakam2yazi (MY_RAKAM NUMBER, PARABIRIMI VARCHAR2) RETURN VARCHAR2
AS
MY_ARTIS NUMBER(18):=0;
MY_ARA NUMBER(18):=0;
MY_UZUNLUK NUMBER(18):=0;
MY_UZUN NUMBER(18):= NVL(LENGTH(TO_CHAR(TRUNC(MY_RAKAM))), 0) + 1;
MY_DEGER NUMBER(18):= NVL(LENGTH(TO_CHAR(TRUNC(MY_RAKAM))), 0);
MY_BIRLER VARCHAR2(54):='bir iki üç dört beş altı yedi sekiz dokuz ';
MY_ONLAR VARCHAR2(54):='on yirmi otuz kırk elli altmışyetmişseksendoksan';
MY_BINLER VARCHAR2(50):='bin milyon milyar trilyon kattrilyon';
MY_YAZIL VARCHAR2(54) :=NULL;
MY_YAZIM VARCHAR2(300):=NULL;
MY_SAYI VARCHAR2(3) :=NULL;
VAR VARCHAR2(1);
MY_YAZI VARCHAR2(2000);
HATA VARCHAR2(2000);
VIRGULDEN_SONRAKI_KISIM VARCHAR2(500);
BEGIN
IF (TRUNC(MY_RAKAM) - MY_RAKAM < 0) AND (PARABIRIMI <> 'GECXXYY') THEN --eger ondalik kisim var ise
IF (PARABIRIMI = 'YTL') OR (PARABIRIMI = 'TL') THEN
VIRGULDEN_SONRAKI_KISIM := substr( trunc(MY_RAKAM * 100),length(trunc(MY_RAKAM * 100))-1, 2 );
VIRGULDEN_SONRAKI_KISIM := rakam2yazi(to_number(VIRGULDEN_SONRAKI_KISIM),'GECXXYY');
VIRGULDEN_SONRAKI_KISIM := VIRGULDEN_SONRAKI_KISIM || ' KURUS';
ELSE
VIRGULDEN_SONRAKI_KISIM := substr( trunc(MY_RAKAM * 100),length(trunc(MY_RAKAM * 100))-1, 2 );
VIRGULDEN_SONRAKI_KISIM := &PKG..rakam2yazi(VIRGULDEN_SONRAKI_KISIM,'GECXXYY');
VIRGULDEN_SONRAKI_KISIM := VIRGULDEN_SONRAKI_KISIM || ' CENT';
END IF;
END IF;
MY_YAZI := NULL;
LOOP
MY_ARTIS := MY_ARTIS + 1;
MY_ARA := 1;
MY_YAZIM := NULL;
IF MY_UZUN >= 4 THEN
MY_UZUNLUK := 3;
MY_UZUN := MY_UZUN - 3;
ELSE MY_UZUNLUK := MY_UZUN - 1;
MY_UZUN :=1;
END IF;
MY_SAYI := SUBSTR(to_char(MY_RAKAM),MY_UZUN,MY_UZUNLUK);
FOR VAR IN 1 .. MY_UZUNLUK LOOP
IF SUBSTR(MY_SAYI,MY_ARA,1) = 1 AND MY_UZUNLUK = 3 THEN
MY_YAZIM := MY_YAZIM || 'yüz';
GOTO DONGU_SONU;
END IF;
IF MY_ARTIS = 2 AND MY_SAYI = 1 THEN
GOTO DONGU_SONU;
END IF;
IF SUBSTR(MY_SAYI,MY_ARA,1) > 0 THEN
IF MY_UZUNLUK = 2 THEN MY_YAZIL := MY_ONLAR;
ELSE MY_YAZIL := MY_BIRLER;
END IF;
MY_YAZIM := MY_YAZIM || SUBSTR(MY_YAZIL,
(to_number(SUBSTR(MY_SAYI,MY_ARA,1))-1)*6+1,6);
IF MY_UZUNLUK = 3 THEN
MY_YAZIM := MY_YAZIM || 'yüz';
END IF;
END IF;
<>
MY_ARA := MY_ARA + 1;
MY_UZUNLUK := MY_UZUNLUK - 1;
END LOOP;
IF MY_DEGER >= 4 AND MY_ARTIS != 1 AND MY_SAYI != 0 THEN
MY_YAZIM:= MY_YAZIM || SUBSTR(MY_BINLER,(MY_ARTIS-1)*10+1-10,10);
END IF;
MY_YAZI := REPLACE(MY_YAZIM,' ','') || MY_YAZI;
EXIT WHEN MY_UZUN = 1;
END LOOP;
HATA:= 0;
IF PARABIRIMI = 'GECXXYY' THEN
RETURN MY_YAZI ;
ELSE
RETURN MY_YAZI || ' ' || PARABIRIMI || ' ' ||VIRGULDEN_SONRAKI_KISIM;
END IF;
EXCEPTION
WHEN OTHERS THEN RETURN MY_YAZI; --HATA := ' ';
END;

Centura Debug Kullanımı

Centura kodları içerisinde debug edilmek istenilen satır uzerinde sağ mouse a basılarak "Toggle Breakpoint" seçeneği seçilir. Seçilen satır kırmızı olacaktır. Program akışı bu kırmızı satırlara denk geldiğinde durur ve satır satır işletmenize olanak tanınır.

Debug anında Tools/Expression menusünü seçtiğinizde gelen küçük pencerede, yazdığınız değişkenlerin çalışma anında içerdikleri değerleri veya bir fonksiyonun geri dönüş değerini yine çalışma anında inceleyebiliriz.

Unutulmaması gereken bir nokta isimlendirmede centura küçük büyük harf duyarlı davranır. Yani "benimdegisken" isimli değişken ve 'Benimdegisken' isimli değişken farklı değişkenleri ifade eder.

Konu ile ilgili, aşağıdaki linkten hazırladığım videoyu izleyebilirsiniz.

http://rapidshare.com/files/198804673/centura_debug.rar.html

11 Şubat 2009 Çarşamba

Gerçekleştirilen değişiklikler üzerine

Zaman içerisinde,herhangibir geliştirme(Oracle,Delphi,Java,IFS,Centura vs)
ortamında iş ihtiyaçları paralelinde pek çok
değişiklik gerçekleştiriyoruz. Yoğunluğa bağlı olarakta,
bir süre sonra bu değişiklikleri kolay hatırlayamaz
olmamız kaçınılmaz bir durumdur.
Bu sorunun çözümü ile ilgili benim yontemim
her değişikliğe unique bir kod verme ve bu değişiklikleri
bu kodlar vasıtasıyla izlemeye dayanıyor.
Pek çok durumda, pek çok programcının karşılaştığını düşündüğüm,
şu durumla karşılaştım.
Bir hata mesajı ile karşılaşıyorum. Bu hata mesajını verdiren
ben olduğum halde hata mesajı ile ilgili çok az şey hatırlıyorum.
Yeniden o kodları yazarken neler düşündüğümü hatırlamaya
çalışmaya dalıyorum:) Bu durum gerçekten de çok vakit kaybettirici
olabiliyor.

Çözüm ayrıntılarına gelince;
benim hazırladığım her hata mesajı, hataya ait unique
bir kod ile başlıyor ve bu kod ile aynı isimde, açıklamalar içeren,
bir text dosya hazırlıyorum.
Text dosyada geliştirme zamanında almış olduğum notlar var.
Hata ile ilgili ayrıntıları tuttuğum text dosya formatına ait
template im aşağıdaki gibi.

--DOSYA BAŞLANGICI--
Amaç : xx
Tarih : xx
Değişikli yapılan DOSYA : \\dbs\ifs\dev2007\new\original\xx.apy
Değişikli yapılan API : SHOP_ORDER_OPERATION_API
Değişikli yapılan bölge : PROCEDURE Unpack_Check_Insert___
REV No : 0
REV Açıklama : xx
REV TArih : xx

NOT : Ek klasöründe yapılan uygulama ile ilgili bir resim daha var.
Arama Yardımcı Kelimeleri : ChangeOrder, Değişim Talebi

HATA Mesajları
----------------------------------------------------------------------------
UZM0023 : xxxx

UZM0023.3 : xxxx


PROCEDURE Unpack_Check_Insert___ (
attr_ IN OUT VARCHAR2,
newrec_ IN OUT &TABLE%ROWTYPE )
IS
BEGIN
.......................................
.......................................
--çeşitli plsql kodları
.......................................
.......................................
end;
--DOSYA SONU--



Bu sorunu halletmetmeye yardımcı olacak adımlardan biri de
kaynak kod aralarına eklenen comment/açıklama satırlarıdır.
Yazdığınız her turlu koda comment eklemek çok
faydalı olacaktır.

9 Şubat 2009 Pazartesi

Oracle kullanarak hata mesajı göstermek

Error_SYS.Record_General
************************

Bu procedure; APY dosyası yani oracle package body içerisinde
geçerli kayıtla ilgili belirlenen bir durumda
hata mesajı görüntülemek ve akışı durdurmak için
kullanılabilir. Çağırıldığı noktada
geçerli işlem durdurulur ve -20110 istisnası oluşur.
Örneğin; insert veya update işleminin belirli bir durumda
gerçekleşmemesi ve oluşan durumla ilgili istenen hata mesajının
görüntülenmesi için kullanılabilir.


Record_General (lu_name_ IN VARCHAR2,
err_text_ IN VARCHAR2,
p1_ IN VARCHAR2 DEFAULT NULL,
p2_ IN VARCHAR2 DEFAULT NULL,
p3_ IN VARCHAR2 DEFAULT NULL)


Parametreler
**************
lu_name_ : Çağıran konumdaki Logical unit
err_text_ : Error text tercüme edilebilir error string .
Runtime error meydana geldiğinde translate mümkündür.
p1_ : err_text_ ile belirtilen parametre içerinde ':P1' yerine gelecek text
p2_ : err_text_ ile belirtilen parametre içerinde ':P2' yerine gelecek text
p3_ : err_text_ ile belirtilen parametre içerinde ':P3' yerine gelecek text

Örnek
****************
Error_SYS.Record_General('Benim LU',
'Bu bir :P1 .',
'denemedir', NULL, NULL);


hata mesajı "Benim LU.Bu bir denemedir ." olacaktır.

Benzer sonuç "raise application error" oracle plsql komutu
kullanılarakta alınabilir fakat Error_SYS.Record_General
prosedürün kullanımı, hem kodu daha
anlaşılır kılmakta hem de mesajın değişik dillere
çevrilmesi ve başka faydalara imkan tanımaktadır.

Oracle Nasıl Nereden Başlamalı ?

Tonguç Bey bence, Oracle a nasıl nereden başlamalı ve kendimizi nasıl geliştiririz konusunda, benim söyleyebileceklerimden fazlasını
çok başarılı bir biçimde aktarmış.
Okunması gereken makaleler diye düşünüyorum.

Oracle'a nasıl başlamalı?
**************************
http://www.ceturk.com/makaleoku.asp?id=200

Oracle'a nasıl başlamalı?(devam)
********************************
http://www.ceturk.com/makaleoku.asp?id=262

3 Şubat 2009 Salı

Centura - Bir table kolonunun null olup olmadığını nasıl test ederim?

If NOT SalIsNull( colsDocClass )

Centura - İmleç bir editbox a gitsin istiyorum. Nasıl yaparım?

--setfocus
Call SalSetFocus ( dfsBenimEditBox )

Centura - Editbox a nasıl değer atarım ?

--editbox a yada item a deger atamak
Set dfsUzmTalepNo = 'bi değer'

--editbox ta bulunan değeri değişkene almak
Set sBirStringDegisken = dfsUzmTalepNo

Centura - Herhangibir nesneyi enable disable nasıl ederim?

--bir item ı enable,disable etmek, örnekteki item editbox
Call SalDisableWindow( dfsUzmTalepNo )
Call SalEnableWindow( dfsUzmTalepNo )

API ile oluşturulan viewlerdeki "comment" ler hakkında

Örnek Comment 'ler
..............................
COMMENT ON COLUMN &VIEW..TALEPNO
IS 'FLAGS=A-IU-^DATATYPE=STRING^PROMPT=TalepNo^';
COMMENT ON COLUMN &VIEW..ISEMRINO
IS 'FLAGS=A-IU-^DATATYPE=STRING^PROMPT=IsemriNo^';
COMMENT ON COLUMN &VIEW..COTYPE
IS 'FLAGS=A-IU-^DATATYPE=STRING^PROMPT=COType^';
..............................

FLAG
****************
Field lerin çalışma zamanındaki davranışları etkiler.
Örneğin LOV(List of Value) flag ı "L" ise F8 ile listeden
seçilmeye çalışıldığında bu alan görüntülenir. "-" ise
görüntülenmez.

FLAGS=

Flag diziliminde sıralama önemlidir.
Örneğin alanı 3. karakter olmalı ve
değeri "-" veya "I" olmalıdır. Her durumda toplam
karakter sayısı 5 olmak zorundadır. Bu kurallara
uymayan girişler ihmal edilir.



Primary yani unique bir key i ifade eder
Flag için olası değerler
P = Parent key
K = Key
A = Attribute


M = Zorunlu
- = Zorunlu Değil


I = Insert e izin verilir
- = Insert e izin verilmez


U = Update e izin verilir
N = Eğer NULL ise Update e izin verilir
- = Update e izin verilmez


L = LOV da görünür
- = LOV da görünmez

Flaglari gereği gibi set ettikten sonra debug consolu
açılarak sırasıyala once Database Library Cache
sonrada Client Cache refresh edilmelidir. Değişiklikler
bu işlemler ardından aktif olur.

Instance Variables/Örnek Değişkenleri

cDataField ata sınıfından türetilmiş bir nesnenin
içerisindeki değeri bir değişkene aktarmak için

Set sBirDegisken = dfBenimcDatafield

satırına benzer bir satır yazılabilir. Ancak
bu yöntem cComboBox, cRecSelExtComboBox, cListBox
ata sınıflarından türetilmiş olan nesnelerin
gözüken(seçili) değerleri okunmaya çalışıldığında
tip uyuşmazlığı hatasına yol açacaktır.

! Tip uyuşmazlığı hatası alınır.
Set sBirDegisken = cmbBenimCombo

! İşlem sonucu başarılıdır.
Set sBirDegisken = cmbBenimCombo.i_sMyValue

Burada kullanılan "i_sMyValue" özelliği
bir instance variable' dır.IFS framework
içerisindeki bazı classlar çeşitli instance
variable lara sahiptir.

Diğer instance variable' lar ve tanımlı
oldukları class listesi aşağıdadır.


Variable Name Defined in class Description
************* ****************** **************************
i_sMyValue cComboBox,
cRecSelExtComboBox,
cListBox Nesnenin içerdiği değer
i_nMyValue cPictureDataItem Nesnenin içerdiği değer
i_hWndSelf cSessionManager Nesneye ait Window handle
i_hWndParent cSessionManager Nesneye ait logical parent Window handle
i_hWndFrame cSessionManager Nesneyi içeren table window veya
dialog box için Window handle

i_sFileName, cPictureDataItem Resim ile ilgili detaylar
i_sFilePath,
i_sDisplayText,
i_bExternalStorage