Latvijas Universitāte
Fizikas un matemātikas fakultāte
Datorikas nodaļa
Oracle
Forms koda optimizācija un
lietotāja-datora
interfeisa uzlabošana
Maģistra darbs
Autors : Ivo Ālmanis
st. apl. Nr. DatZ M 96007
Darba
vadītājs : Dr. dat. Andrejs Auziņš
Rīga, 1999
Anotācija
Šajā
darbā ir aprakstīta Oracle Forms 4.5
koda optimizācija un lietotāja-datora interfeisa uzlabošana. Darbs sastāv no 2
daļām. Pirmajā no tām liela uzmanība tiek pievērsta tieši rīka izejas koda un
objektu atribūtu vērtību optimizācijai, kam ir liela nozīme, ja šai vidē
veidotās sistēmas strādā ar lieliem datu apjomiem un ir nepieciešama ātra darbu
veikšana un reakcija uz datu kļūdām. Darbā minētie optimizācijas risinājumi
paskaidroti ar piemēriem no reālām sistēmām. Otrā daļā tiek aplūkots kā veidot
vienotu, vienkāršu un intuitīvi saprotamu lietotāja-datora interfeisu,
strādājot ar Oracle Forms 4.5,
produktu, kura vājākā vieta, salīdzinot ar citām 4 paaudzes valodām (4GL), ir
tieši lietotāja-datora interfeiss. Darba beigās doti programmu kodu piemēri
visiem darbā minētajiem problēmu risinājumiem.
Abstract
This Master Thesis is devoted to the
optimisation of Oracle Forms 4.5 code
and user interface improvement. The Thesis consists of two parts. The first
part deals with optimisation of tool’s source code and object attribute values.
Both issues are very important because Oracle
Forms 4.5 environment systems are managing large volumes of data.
Therefore, fast operations and prompt reaction to data errors is essential. The
proposed solutions of optimisation are described using real examples of live
systems. The second part of the Thesis deals with creating of unified, simple
and intuitively understandable user interface for Oracle Forms 4.5. If compare with other 4th generation
languages (4GL), the user interface is the main weakness of Oracle Forms 4.5. In the final part of the Thesis the
author provides with the program code examples for all solutions described in
this paper.
Аннотация
В данной работе
дается описание оптимизации кода Oracle
Forms 4.5 и усовершенствования интерфейса пользователя. Работа состоит из
двух частей. В первой части большое внимание уделено вопросам оптимизации
выходного кода инструментальных программных средств и значений атрибутов
объектов. Эти параметры имеют важное значение, если системы, созданные в данной
среде, работают с большими объемами данных, где требуется быстродействие и
немедленная реакция на ошибочные данные. Решения оптимизации пояснены примерами
из реальных систем. Во второй части рассмотрено формирование единого,
несложного и интуитивно понятного интерфейса пользователя для работы с Oracle Forms 4.5, где наиболее слабым
местом по сравнению с другими языками 4-го поколения (4GL), является интерфейс
пользователя. В конце работы приведены примеры программных кодов с решениями
вышеупомянутых проблем.
Autoreferāts
Darba autors strādā
SIA Tieto Konts Financial Systems nu jau vairāk par četriem gadiem. Pēdējos trīs
ar pusi gadus autors piedalījies daudzu sistēmu, kas balstītas uz Oracle RDBMS,
izstrādē, strādājot gan kā programmētājs, gan kā sistēmu analītiķis. Pašlaik
autors strādā par produktu grupas vadītāju un galvenokārt nodarbojas ar sistēmu
izstrādi un analīzi, taču ļoti bieži arī ievieš izmaiņas pirms gadiem
rakstītajās programmās. Bieži vien šīs izmaiņas ir saistītas tieši ar
programmas koda optimizāciju.
Maģistra darba
pirmajā nodaļā aprakstīta Oracle Forms
4.5 koda optimizācija. Galvenais akcents darbā nav likts tieši uz PL/SQL
koda optimizāciju formās, bet gan uz formas objektu atribūtu vērtību
optimizāciju kā arī uz konkrētu uzdevumu optimizāciju, pamatojot tos ar
piemēriem no reālām sistēmām. Tā kā materiāli par Oracle Forms 4.5 koda optimizāciju prakstiski nav atrodami, darbā dotie
risinājumi ir Oracle dokumentācijas apkopojums un autora darba pieredzes
rezultāts.
Vadot
sistēmu izstrādi, pie kuras strādā vismaz 3-4 cilvēki, bieži vien nākas
saskarties ar problēmu, ka katram izstrādātājam ir sava gaumes un stila izjūta,
veidojot formas. Tas parasti noved pie problēmas, ka sistēma izskatās ļoti
raiba. Bez tam lietotājiem nav pārliecības, ka tā izstrādāta vienā
organizācijā, jo tie nespēj intuitīvi strādāt ar sistēmu, kurā gandrīz katra
forma izskatās savādāk. Šīs problēmas neitralizēšanai, autors kā sistēmas
izstrādes vadītājs, apkopoja visu pieejamo informāciju par vienota interfeisa
izstrādi Oracle Forms 4.5, kas sīkāk
aprakstīta darba otrajā nodaļā. Bez tam autors darbā min arī savus risinājumus
dažām lietotāja-datora interfeisa problēmām.
Izstrādājot darbu,
autors balstījies uz personīgo pieredzi patreizējā darba vietā kā arī uz
dažādām publikācijām un grāmatām.
Saturs
Ievads....................................................................................................................................................................... 7
1. Programmas
koda optimizācija............................................................................................. 9
1.1. Formas objektu un to atribūtu vērtību
optimizācija...................................................................... 11
1.1.1. Formas objekti un to atribūti, kas iespaido
ātrdarbību........................................................ 11
1.1.2. Trigeru pareizs pielietojums un izvairīšanās no
atkārtotiem izsaukumiem....................... 15
1.1.3. Ne-tabulas lauku vērtību aktualizēšana................................................................................... 18
1.2. Operāciju ar datnēm optimizēšana................................................................................................... 20
1.2.1. Datņu ielasīšana............................................................................................................................ 21
1.2.2. Datņu veidošana............................................................................................................................ 27
1.2.3. Pakotnes DBMS_PIPE pielietojums.......................................................................................... 33
1.3. Datu ievadformu optimizācija (pieslēgums datu
bāzes serverim, izmantojot modemu)....... 35
1.3.1. Datu atlasīšana pēc maskas un piesaistīto
tabulu raksti...................................................... 36
1.3.2. Fetched Records atribūts formas blokiem................................................................................ 37
1.3.3. Auto Refresh atribūts LOV objektiem........................................................................................ 39
1.3.4. Ne-tabulas lauku vērtību aktualizēšana................................................................................... 40
1.3.5. Update Changed Columns atribūts formas blokiem............................................................... 41
1.3.6. Datnes ielasīšana.......................................................................................................................... 42
2. Lietotāja-datora interfeisa uzlabošana.......................................................................... 45
2.1. Grafiskā lietotāja-datora interfeisa
pamatprincipi......................................................................... 45
2.2. Šablonformu izmantošana formu ģenerācijai................................................................................ 45
2.3. Preferences kā ģeneratora parametri................................................................................................ 50
2.4. Padomi interfeisa uzlabošanai........................................................................................................... 53
2.4.1. Rīku josla........................................................................................................................................ 53
2.4.2. Rīku padomi (Tooltips) - spiedpogu nozīmju
aprakstīšana................................................... 54
2.4.3. Standartizvēlnes............................................................................................................................ 54
2.4.4. Ievadlauku krāsu nozīme.............................................................................................................. 56
2.4.5. Logu virsraksti............................................................................................................................... 56
2.4.6. Resursu pārbaude pirms lietojumprogrammas
palaišanas................................................... 57
2.4.7. Par - ātra informācija par jūsu
lietojumprogrammu.............................................................. 58
2.4.8. Paroles maiņa................................................................................................................................ 59
2.4.9. Progresa rādītājs........................................................................................................................... 60
2.4.10. Lietojumprogrammu palaišana................................................................................................ 60
2.4.11. MS Windows palīdzības logi.................................................................................................... 61
2.4.12. Nodaļlapas (Tabbed pages) - jauns interfeisa
standarts.................................................... 62
2.4.13. Palīdzības teksta (Hint) krāsa................................................................................................... 63
Nobeigums.......................................................................................................................................................... 64
Literatūra........................................................................................................................................................ 65
Pielikums............................................................................................................................................................ 66
Programmu teksti......................................................................................................................................... 66
Formu koda optimizācija........................................................................................................................ 66
Lietotāja interfeisa uzlabošana............................................................................................................. 77
Ievads
Salīdzinot
ar neseno pagātni, tagad ir tendence veidot lielas sistēmas, kur datu apjoms
sasniedz simtus un pat tūkstošus megabaitus. Uz personāliem datoriem bāzētās
datu bāzu vadības sistēmās, kā Fox Pro, Access un citās, palielinoties datu
apjomiem, krasi samazinās darbības ātrums. Drīz tiek sasniegta robeža, kad
palielināt apjomu vairs nav iespējams. Bez tam nav iespējama vienlaicīga datu
lietošana vairākiem lietotājiem, t.i. vienlaicīgi vairāki lietotāji nevar
ievadīt datus, tajā pašā laikā nodrošinot šo datu unikalitāti. Nolasot datus
parasti visus resursus aizņem viens lietotājs, pārējiem tikmēr ir jāgaida. Šādu
ierobežojumu dēļ, ar laiku sistēmas nav funkcionēt spējīgas. Tās jāveido no
jauna un tāpēc ir vajadzīgas DBVS, kurām nav šādu ierobežojumu. Lielās datu
bāzu vadības sistēmās (Oracle, DB2 un citas) visas šīs problēmas ir novērstas,
lielāku uzmanību pievēršot arī datu aizsardzībai un drošumam. Oracle piedāvātā tehnoloģija sistēmu
izstrādei spēj nodrošināt vieglāku un ātrāku sistēmu izstrādi, izmantojot
grafiskos līdzekļus un ģeneratorus, kas aizvieto monotonu programmu rakstīšanu.
Tādēļ aizvien
vairāk lielu datu bāzu vadības sistēmu izstrādātāji sāk izstrādāt savas
sistēmas tieši Oracle, DB2 un citās vidēs, kas spēj nodrošināt labu produktu
izstrādi un kas ir orientētas tieši uz lielām datu bāzēm.
Iztrādājot lielas sistēmas, kas piemēram
balstītas uz Oracle piedāvāto tehnoloģiju, izstrādātāji bieži vien balstās uz
to, ka jaunā tehnoloģija ir daudz spēcīgāka un spēj strādāt ar lieliem datu
apjomiem, tādējādi piemirstot par rakstāmā produkta izejas koda optimizāciju.
Strādājot ar tādiem pašiem datu apjomiem, kādi bija Fox Pro vidē sistēma,
neapšaubāmi strādā ātrāk, veicot nepieciešamos datu pieprasījums un labojumus
pietiekoši ātri, taču papielinoties datu apjomiem izstrādātās sistēmas tāpat
sāk lēni strādāt, kas bieži vien notiek iztrādātāju vainas dēļ, jo tie nav
veikuši nekādus izstrādātās sistēmas optimizācijas pasākumus.
Darba
pirmajā nodaļā autors piedāvā savu skatījumu tieši uz Oracle Forms 4.5 optimizāciju, kas sevī ietver
gan formas objektu un to atribūtu, gan arī pašas formas izejas teksta
optimizāciju. Darbā tiek aplūkoti autora nu jau vairāk kā trīs gadu ilgas darba
pieredzes ar Oracle Forms 4.5
rezultāti, jo vismaz pašlaik autora rīcībā nav nevienas grāmatas vai cita
informācijas avota kā, piemēram, www lapas, kas sniegtu izsmeļošu informāciju
kā optimizēt Oracle Forms 4.5
rakstīto izejas tekstu. Nedaudz informācijas šai sakarā ir atrodama Oracle Forms 4.5 grāmatās (arī on-line Help), bet tā attiecas tikai uz
formas objektu atribūtu vērtībām. Darbā bez teorijas apskata tiek aplūkoti arī
reālu uzdevumu iespējamā optimizācija, pamatojot to ar reāliem piemēriem no
autora rakstītām sistēmām. Ļoti konkrēti tiek apskatītas datņu ielasīšanas un
veidošanas optimizācija kā arī darbs ar sistēmu attālinātā režīmā, t.i. ja
pieslēgums datu bāzei tiek organizēts, izmantojot modemu.
Taču bieži vien ar labu sistēmas
funkcionalitāti un ātru darbību vien ir par maz. Lietotājs galvenokārt īpašu
uzmanību pievērš sistēmas interfeisam, cik viegli ir ar to strādāt un cik
intuitīvi viņš var strādāt. Tas parasti tiek aizmirsts, izstrādājot lielas
sistēmas, kā rezultātā lietotāji nav apmierināti un vienmēr uzskata, ka vecā
sistēmas, kas piemēram bija veidota uz FoxPro bāzes, bija krietni labāka, kaut
arī šad tad pazuda dati, sistēma uz lieliem datu apjomiem strādāja lēni, šad
tad jāgaida uz kādu, kamēr tas pabeigs savu darbību ar datiem, lai tiem vispār
varētu tikt klāt.
Bez tam, ja tirgū ir pieejami vairāki
vienādas kvalitātes produkti produkti, klients vienmēr izvēlēsies to, kas ir
vieglāk saprotams, apgūstams un ar kuru strādājot var gūt lielāku darba
efektivitāti. Citiem vārdiem sakot, klients izvēlēsies to produktu, kam būs
labāks lietotāja-datora interfeiss.
Taču, lai izveidotu labu lietotāja-datora
interfeisu, vienmēr rodas zināmas problēmas. Palielinoties projektu apjomiem,
parasti tos vairs nerisina viens cilvēks kā tas ir FoxPro un citu mazu DBVS
gadījumā, bet gan 2, 3 un pat vairāk cilvēku. Tā kā katram cilvēkam ir sava
gaumes un stila izjūta, katrs programmētājs veido savu lietotāja-datora
interfeisu, tādu, kādu tas uztver par vairāk tīkamu. Bet lietotājs vēlas, lai
projekta ietvaros visas datu ievadformas un citi datu logi būtu vienota stila.
To parasti panāk, izstrādātājiem vienojoties par kopēju lietotāja-datora
interfeisu. Tā kā Oracle CASE rīki atļauj ģenerēt formas no iepriekš
aprakstītiem moduļiem, tad izstrādātāji vēlētos, lai visas ģenerētās formas,
jau saturētu interfeisa standartu, par kuru izstrādes grupa ir vienojusies. To
panāk aprakstot formu šablonus (template),
kas tiek izmantoti ģenerācijas procesā kā arī sistēmas, atsevišķu moduļu un
atsevišķu tabulu preferences (preference),
kas tiek izmantotas ģenerācijas procesā.
Darba otrajā nodaļā tiek aplūkots kā
veidot vienotu lietotāja-datora interfeisu strādājot ar Oracle Forms Designer 4.5, produktu, kura
visvājākā vieta, salīdzinot ar citām 4 paaudzes valodām (4GL), ir tieši
lietotāja-datora interfeiss. Kā vienu no tā iemesliem varu minēt Oracle
produktu pieejamību uz vairākām operētājsistēmu platformām, kā rezultātā visi
Oracle produkti jebkurā operētājsistēmā izskatās vienādi. Tas panākts ieviešot
savus standartus. Tas protams pārāk
daudz neattiecas uz grafisko izpildījumu, bet gan terminoloģiju. Lietotājs
nespēj strādāt intuitīvi, kā ar jebkuru citu jaunu produktu, jo tiek lietots
daudz jaunu terminu. Lietotājs parasti pirmajā brīdī ir samulsis.
Otrās nodaļas beigās tiek apkopoti vairāki raksti žurnālos un Internetā
par tēmu kā labāk veidot savu lietojumprogrammu (application) lietotāja-datora interfeisu, strādājot ar Oracle
formām MS Windows vidē.
Angliskie nosaukumi ir tulkoti izmantojot LZA terminoloģijas komisijas informātikas
apakškomitejas apstiprinātos angļu terminu latviskojumus. Maz pazīstamiem un
nezināmiem terminiem, kuriem iepriekšminētajā vārdnīcā nebija dots tulkojums,
ir doti darba autora tulkojumi, iekavās dodot orģinālnosaukumu angliski.
1. Programmas koda optimizācija
Programmas koda
optimizācijas mērķis ir panākt, lai programmas kods izpildītos pēc iespējas
ātrāk. To var panāk vairākos veidos. Viens no veidiem, ko bieži pielietoja 3
paaudzes valodās ir programmas kodā jau iekļaut kodu, kas rakstīts asamblera
valodā vai pat mašīnkodā. Taču ne visās programmēšanas valodās tas ir iespējams
un tāpēc ir jāķeras klāt pie kodu optimizācijas pamatprincipiem, kas nosaka kā
rakstīt programmas kodu, lai tas izpildītos ātrāk. Šie pamatprincipi nav
stingri kodēšanas likumi, kas būtu jādara, veicot kodēšanu, bet gan elementāras
koda optimizācijas idejas, kuras savā kodā var ietvert jebkurš iesācējs [8].
Kā piemērs var tikt
minēts If nosacījuma izmantošana, kas
iespējama jebkurā programēšanas valodā. Uzmanība šajā gadījumā jāpievērš
loģisko operāciju izvietojumam. Kā zināms and
nosacījumā abām pusēm jābūt patiesām. Pamatā visas programmēšanas valodās,
gadījumā ja nosacījuma pirmā puse ir nepatiesa, otrā puse netiek pārbaudīta jo
tam vairs nav nekādas nozīmes. Tātad optimizētā programmas kodā nosacījuma
pirmā pusē būs nosacījums, kas izpildās ātrāk un atkarībā no kura vērtības jau
ir zināms vai nepieciešams pābaudīt nosacījuma otru pusi. Tāpēc kā pirmā puse
būtu jāliek nosacījums, kas visbiežāk atgriež nepatiesu vērtību. Kā zināms,
operācijas ar skaitļiem izpildās ātrāk nekā ar string mainīgajiem, tāpēc saliktajos nosacījumos, kur tiek
izmantoti abu tipu mainīgie, kā pirmā daļa būtu jāliek skaitļu salīdzinājums.
Tā negatīvas atbildes gadījumā nosacījuma otra puse netiek izpildīta, ietaupot
dažas procesora komandas. Savukārt or
nosacījumiem, vismaz vienai nosacījuma pusei jābūt patiesai, kas nozīmē, ka
izdevīgāk kā nosacījuma pirmo daļu likt to, kas biežāk atgriež patiesu vērtību.
Savukārt if…elsif…else…endif gadījumā jāņem vērā
nosacījumu kārtība. Kā pirmos vēlams likt tos, kas izpildās biežāk, tādējādi
datoram nav jāveic liekas salīdzināšanas operācijas.
Ļoti
bieži novērotā programētāju kļūda ir – nosacījumu ciklos tiek pārbaudītas
mainīgo vērtības, kas nemainās šī cikla laikā, tādējādi katrā ciklā veicot
liekas operācijas. Piemēram:
string1 = "a
string"
string2 =
argument_to_function
for i = 1 to
100
begin
...
if
(string1 equals string2) and …..
...
end
Kā
jau redzams mainīgo salīdzināšana katrā cikla solī ir vienkārši lieka. Tā vietā
labāk būtu lietot šādu programmas kodu:
string1 = "a
string"
string2 =
argument_to_function
are_equal =
string1 equals string2
for i = 1 to 100
begin
...
if
(are_equal) and ……
Do Something
...
end
Šajā
gadījumā nosacījuma rezultāta pirmā puse jau zināma un nav jārēķina katrā cikla
solī. Tas attiecināms uz visiem konstantiem aprēķiniem – jebkurai koda daļai,
kas atgriež konstantu rezultātu, jābūt aprēķinātai jau pirms cikla.
Tas pats attiecināms arī uz programmas
kodu, kur cikls iekļauj sevī citu ciklu. Ja ārējais cikls izpildās 10 reizes un
iekšējais katrā arējā cikla solī arī 10 reizes, tas nozīmē, ka ieksējais cikls
pavisam izpildās jau 100 reizes. Tātad galējais skaits ir šo ciklu skaita
reizinājums un lieki piebilst cik ātri tas pieaug, palielinot vienu no cikla
garumiem. Ļoti svarīgs fakts ir, ka optimizācija iekšējā cikla kodā var strauji
palielināt koda izpildes ātrumu. Šeit jāņem vērā kaut vai pirms tam minētā
salīdzinājuma operācijas pareiza izveidošana.
Vēl
viena ļoti svarīga lieta, kas jāievēro veicot programmu optimizāciju, ir jāzin vai
procedūras izsaukšana cikla ķermenī ir izdevīgāka par procedūras koda
iekļaušanu pašā ciklā. Protams no pārskatāmības viedokļa kods ir vieglāk
lasāms, ja n-rindu vietā ir tikai viens procedūras izsaukums, taču jāatceras,
ka katram procedūras izsaukumam procesoram jādara sekojošais [8]:
1)
Jāsaglabā esošais stāvoklis;
2)
Jāizveido jauna darba vide, t.i.
lokālo mainīgo inicializācija u.t.t.;
3)
Jāizpilda funkcija;
4)
Jāatgriežas izejas stāvoklī;
5)
Jāturpina no vietas, kur tika
izsaukts.
Ja soļa 3 izpilde
neaizņem vairāk par 2/3 laika, tad nav nekādas vajadzības veidot šo funkciju
- tās kods jāraksta pa tiešo tekstā.
Dauzi kompilatori tomēr atļauj rakstīt šādas funkcijas atsevišķi, kas
kompilētajā koda gabalā jau ir iekļautas bez funkcijas izsaukuma pa tiešo paša
tekstā.
Tas viss ir tikai
daļa no pamatprincipiem, kas jāievēro, rakstot optimizētu programmas kodu. Šajā
darbā netiks aprakstīta šāda Oracle Forms
4.5 koda optimizācija, bet gan jau daudz plašākā mērogā un tieši konkrētāk
Oracle Forms 4.5 videi.
Tā kā Oracle Forms 4.5 ir objektorientēta vide, koda
optimizācija varētu nozīmēt ne tikai koda optimizāciju, bet arī formas objektu
un/vai to atribūtu vērtību maiņu, kas varētu dod labākus rezultātus formas
izpildē. Bez tam ar ļoti daudzām formām tiek veiktas ne tikai vienkāršas datu
ievadīšanas un labošanas operācijas, bet arī daudzi citi uzdevumi, t.i. tiek
izsauktas dažādas programvienības gan no bibliotēkām, gan servera pakotnēm. Bez
tam var tikt veikta arī kāda vienkārša datu manipulācija, kas nav redzama
lietotājam. Šajā gadījumā koda optimizācija ir kā vienkāršāk uzrakstīt formas
izejas kodu, lai tas izpildītos pēc iespējas ātrāk un arī retāk, jo kā vēlāk
darbā tiks aplūkots, programmētāji ļoti bieži uzraksta kodu kas strādā korekti
un ātri, taču izpildās pārāk bieži, t.i. tiek pielietoti nepareizie trigeri (trigger) vai tie izvietoti pārāk augstu
objektu hiarhijas kokā, kā rezultātā tiek izpildīti daudz biežāk nekā
nepieciešams.
Šajā darbā
galvenokārt tiks apskatītas formas objektu atribūtu vērtību nozīme formas ātrdarbībā.
Tiks aplūkoti arī daži piemēri kā uzlabot tieši izejas kodu, lai tas izpildītos
ātrāk. Par to sīkāk nākamājās darba nodaļās.
1.1. Formas objektu un to atribūtu vērtību optimizācija
Vispirms darbā teorētiski tiks
aplūkoti visi tie formas objekti un/vai to atribūti, kas zināmā mērā varētu
iespaidot formu ātrdarbību, kā arī tiks pamatots kāpēc. Ar formas ātrdarbību
šeit nav domāts tikai koda izpildes ātrums, bet arī dažādu atribūtu vērtības,
lai novērstu lieku kodu izpildi, kuru dēļ lietotājiem, teiksim, jāveic liekas
darbības kā atkārtota tausiņu nospiešana u.c. Pēc tam nākošajās nodaļās ar
piemēriem tiks pierādīts, cik liela ir šo objektu un/vai atribūtu ietekme uz
formas ātrdarbību.
1.1.1. Formas objekti un to atribūti, kas iespaido ātrdarbību
Vispirms aplūkosim
pašas formas atribūtus. Eksistē tikai viens formas atribūts, kas iespaido tās
ātrdarbību, un tas ir: CURSOR MODE PROPERTY, kas definē formu kursoru (cursor) stāvokli starp tranzakcijām. Šis
atribūts ir ļoti noderīgs strādājot tieši ar ne-Oracle datu bāzi. Atribūtam ir
2 vērtības [6]:
·
OPEN_AT_COMMIT – nosaka, ka
kursoriem jāpaliek atvērtiem starp tranzakcijām;
·
CLOSE_AT_COMMIT – nosaka, ka
kursors ir jāaizver tūlīt pēc COMMIT operācijas.
Kursoru aizvēršana tulīt pēc COMMIT
operācijas un to atkārtota atvēršana var ļoti samazināt formas ātrdarbību pie
šādām operācijām:
·
Veicot COMMIT operāciju;
·
citu SQL pieprasījumu izpildīšanā
uz tiem pašiem ierakstiem;
·
datu pieprasījumu (SELECT…)
izpildīšanā.
Oracle Forms 4.5 ātrdarbība samazinās tādēļ, ka
katru reizi ir jāatver jauns kursors un tajā esošā komanda atkal ir
jāizanalizē.
Tālāk aplūkosim formas objektus un to
atribūtus, kuru vērtības varētu iespaidot ātrdarbību. Vispirms viens no
primārajiem formas objektiem – bloks. Formās var būt gan datu tabulas bloki,
gan kontroles bloki, t.i. bloki, kas neatsaucas uz kādu konkrētu datu bāzes
tabulu. Tie parasti tiek izmantoti dažādu kontroles mainīgo glabāšanai, taču
tie nekādi nevar iespaidot ātrdarbību. Ir virkne bāzes tabulu bloku (bloks, kam
piesaistīta konkrēta bāzes datu tabula) atribūtu, kas iespaido formu
ātrdarbību. Tie ir:
a)
WHERE Clause – standarta SQL
pieprasījuma maskas nosacījums bloka bāzes tabulai. Šis maskas nosacījums
automātiski tiek pievienots SQL pieprasījumam un tiek izpildīts vienmēr, kad
lietotājs pieprasa datus par šim blokam piesaistīto tabulu. Rakstot šo
nosacījumu jāņem vērā, ka maskas nosacījums jāraksta tā, lai tas pēc iespējas
efektīvāk izmantotu tabulas indeksus, jo pretējā gadījumā tas ļoti krasi
samazina formas ātrdarbību. Šī atribūta vērtības optimizācija patiesībā ir
izpildāmā SQL pieprasījuma ātrdarbības optimizācija. Gadījumos, ja maskas
nosacījums neizmanto nevienu tabulas indeksu un veic pilnu tabulas
caurskatīšanu – datu atlasīšana formā var ieilgt līdz pat vairākām minūtēm, kas
izmantojot indeksus var būt dažas sekundes daļas;
b)
ORDER BY Clause – tāpat kā maskas
nosacījums arī kārtošanas nosacījums ir standarta SQL pieprasījuma daļa, kas
automātiski tiek pievienota SQL pieprasījumam, veicot datu atlasīšanu.
Teorētiski kārtošana pēc laukiem, kas ietilpst indeksā noteik ātrāk nekā pēc
tiem, kas tajos nav. Tāpat kā maskas gadījumā – rakstot kārtošanas nosacījumu,
jāņem vērā, ka optimāla ātrdarbība tiks panākta, ja izpildāmais SQL
pieprasījums būs pietiekami labi optimizēts;
c)
OPTIMIZER HINT – tāpat kā divi
augstāk minētie arī šis atribūts raksturo padomu (hint) RDBMS optimizatoram, izpildot SQL pieprasījumus. Pareizi
lietojot šo atribūtu iespējams krasi palielināt formu ātrdarbību darbā ar
lielām datu tabulām. Piebilde: šis atribūts var tikts lietots tikai strādājot
ar Oracle7 datu bāzi. Šo atribūtu var izmantot, lai panāktu ātrāku atbildes
laiku uz pieprasījumiem, piemēram, norādot, ka pieprasījumam vispirms jāatgriež
tikai pirmās rindas ( /*+ FIRST_ROWS */); Sīkāk par šo un augstāk minēto
atribūtu vērtībām var uzzināt Oracle7 grāmatās, nodaļās “Tuning SQL statements”
un “The Optimizer”;
d)
RECORDS BUFERED – atribūts, kas
nosaka cik ierakstu no tabulas tiks buferēti klienta darba vietas atmiņā
izpildot SQL pieprasījumu. Pēc noklusēšanas šī vērtība ir vienāda ar formā
rādāmo bloka ierakstu skaitu plus konstante 3. Tā arī ir minimālā vērtība.
Maksimālā vērtība tiek noteikta Oracle Forms
4.5 izpildes laikā, jo tas atkarīgs no pieejamās atmiņas apjoma uz klienta
darba vietas. Šī atribūta papielināšana var paātrināt formu ātrdarbību, jo
gadījumā, ja lietotājam jāaplūko tabula ar ļoti daudziem ierakstiem, tad
mēģinot aplūkot nākošos tie tiks parādīti uzreiz, jo tie jau būs formas atmiņā.
Pretējā gadījumā tie tiek savākti no datora virtuālās atmiņas. Uz ātrām darba
stacijām ar ātriem diskiem tā nav problēma, jo tas notiek sekundes simtdaļās un
ātrāk, bet ja darba stacijas disku ātrums ir lēns tas var radīt nelielu
aizkavēšanos parādot ierakstus. Oracle formas buferētos rakstus glabā pagaidu
failos uz diska. Tas nozīmē, ka pirms šī atribūta uzstādīšanas ir jārēķinās ar
datora resursiem, ko aptuveni varētu aizņemt šie dati, jo rakstu var būt daudz,
bet ar mazu apjomu (raksta lauku skaits un to izmēri), vai arī maz rakstu, bet
kuru apjoms ir liels (satur laukus ar long
datu tipu vai grafiskiem attēliem);
e)
RECORDS FETCHED – atribūts, kas
nosaka ierakstu skaitu, ko vienā reizē no datu bāzes pieprasa Oracle formas.
Vislielākā ātrdarbība protams ir gadījumā, ja formām ir jāatlasa viens ieraksts
vienā reizē. Lielāks šo ierakstu skaits samazina vispārējo laiku, kas
nepieciešams ierakstu atlasīšanai, veicot mazāku skaitu datu pierasījumu
izsaukumu. Šī atribūta vērtība jāliek atkarībā no blokā rādāmo ierakstu skaita,
vislabāk vienāda ar rādāmo ierakstu skaitu. Strādājot sistēmās, kur pieslēgums
datu bāzes serverim organizēts, izmantojot modemu, šī atribūta ieteicamā
vērtība būtu vismaz 2-3 reizes lielāka, nekā rādāmo ierakstu skaits. Sīkāk par
to tiks aplūkots kādā no nākamajām darba nodaļām;
f)
UPDATE CHANGED COLUMNS – atribūts,
kas nosaka vai izpildot datu modifikācijas komandu (UPDATE table_name SET…) tās
parametros tiks iekļauti visas datu tabulas lauki vai tikai mainīto lauku. Pēc
noklusēšanas šī atribūta vērtība ir False,
kas nozīmē, ka izpildot UPDATE komandu tajā tiks uzrādīti visi datu tabulas
lauki, kas dod iespēju Oracle Forms 4.5,
lietot to pašu SQL teikumu vairākas reizes neveicot tā atkārtotu analizēšanu (re-parse). Uzstādot šā parametra vērtību
uz True, var strauji samazināties
Oracle Forms 4.5 ātrdarbība, jo katru
reizi izpildāmā komanda vispirms ir jāizanalizē. Pamatā šī atribūta vērtība
jāuzstāda uz True tikai gadījumos, ja
lietotājs reti mainīs datus, kas prasa laiku to nosūtīšanai pa tīklu, piemēram,
long tipa mainīgos vai grafiskos
attēlus. To var izmantot arī gadījumos, lai samazinātu datortīkla noslodzi, ja
zināms, ka lietotājs mainīs tikai vienu vai divus ierakstus, kā arī, lai
izvairītos no lielu datu tabulu lauku vairākkārtējas pārsūtīšanas datortīklā.
Gadījumos, ja maināmā tabulā ir tabulas trigeris, kas fiksē tikai mainīto lauku
datus, šī atribūta vērtību arī ieteicams uzstādīt uz True, jo citādi datu modifikācijas komanda mainīs arī laukus, kuru
vērtības patiesībā nav mainījušās, kas radīs liekas darbības tabulas trigerī;
Kā nākošos formas
objektus aplūkosim vērtību sarakstus (LOV
– List Of Values) un ierakstu grupas (Record
group), kas tiek izmantotas, lai atlasītu ierakstus vērtību sarakstiem.
Tāpat kā blokiem arī šiem objektiem ir virkne atribūtu, kuru vērtības var
izmainīt formas ātrdarbību. Vērtību saraksta atribūti ir:
1.1.2. Trigeru pareizs pielietojums un izvairīšanās no atkārtotiem izsaukumiem
Kā jau minējām iepriekš, rakstot
trigeru kodus formās ir jāuzmanās no situācijām, kad kāds trigeris var tikt
izsaukts pārāk bieži vai šad tad arī nevietā. Tas var radīt pārāk lēnu formas
darbību vai arī sliktākajā gadījumā neparedzētus datu labojumus datu tabulās.
Lai izprastu, kur visbiežāk tiek pieļautas kļūdas un kā no tām izvairīties ir
pareizi jāsaprot trigeru izpildes kārtība formās, arī atkarībā no to hiarhiskā
izvietojuma formā. Tālāk tiek aprakstīti formas bloka līmeņa trigeri, kas tiek
izmantoti visbiežāk [3] [6]. Tie ir:
a)
WHEN-NEW-BLOCK-INSTANCE –
trigeris, kas izpildās, kad lietotājs pārvietojas no viena formas bloka uz
otru, neatkarīgi no bloka lauka uz kuru pārvietojas. Izpildās tūlīt pēc tam,
kad formas ir gatavas jaunam datu ievadam blokā. Parasti tiek izmantots
gadījumos, kad nepieciešams veikt kādu darbību, ja lietotājs formās pārvietojas
uz citu bloku, piemēram, aizliegt/atļaut kādas spiedpogas u.c. Ja trigeris ir
formas līmenī, tas izpildās jebkurā gadījumā, kad nomainās bloks. Ja tas ir
bloka līmenī, tad tikai kad lietotājs pārvieto kursoru uz šo kādu no šī bloka
elementiem;
b)
WHEN-NEW-RECORD-INSTANCE –
trigeris, kas izpildās tūlīt pēc kursora pārvietošanas no viena ieraksta (record) uz otru, kad formas ir gatavas
datu ievadam attiecīgajā ierakstā. Parasti tiek izmantots gadījumos, kad,
piemēram, jāveic kādas manupulācijas ar
citiem formas objektiem, atkarībā no kāda ieraksta lauka vērtības. Ja trigeris
ir formas līmenī, tad tas izpildās jebkurā gadījumā, kad lietotājs pārvietojas
no kāda ieraksta uz citu, t.i. arī gadījumos, ja pāreja notiek no viena bloka
kāda ieraksta uz cita bloka kādu ierakstu. Ja trigeris ir bloka līmenī, tas
izpildās vienmēr, kad notiek pārvietošanās no bloka viena ieraksta uz citu;
c)
WHEN-NEW-ITEM-INSTANCE – trigeris,
kas izpildās tūlīt pēc kursora pārvietošanas uz kādu no formas ievadlaukiem,
tūlīt pēc tam kad formas jau gatavas datu ievadam. Parasti, piemēram, tiek
lietotas lai izpildītu formas ierobežotās funkcijas (restricted built-ins). Ja trigeris ir formas līmenī, tas izpildās
vienmēr, kad notiek pārvietošanās no viena ievadlauka uz citu. Ja tas ir bloka
līmenī, tas izpildās tad, kad notiek pārvietošanās no viena ievadlauka uz citu
tajā pašā blokā. Ja tas ir konkrēti jau kāda ievadlauka trigeris, tad tas
izpildās tikai gadījumā ja kursors tiek pārvietots uz šo konkrēto ievadlauku;
d)
WHEN-CREATE-RECORD – trigeris, kas
izpildās vienmēr, kad formās tiek izveidots jauns ieraksts. Parasti tiek
izmantots gadījumos, piemēram, kad jāveic kādas darbības, teiksim noklusēto
vērtību piešķiršana (funkcija no citu lauku vērtībām, kas aprēķināmas tikai
izpildes laikā, un nav nosakāmas izstrādes laikā) jaunajam ierakstam. Ja
trigeris ir formas līmenī, tas izpildās vienmēr, kad formās tiek izveidots jauns
ieraksts. Ja tas atrodas bloka līmenī, tad vienmēr kad jauns ieraksts tiek
izveidots attiecīgajā blokā;
e)
WHEN-VALIDATE-RECORD – trigeris,
kas izpildās ieraksta validācijas procesā, kā pēdējais posms. Parasti tiek
pielietots gadījumos, lai papildinātu formas noklusēto validācijas procesu.
Piezīme, lietojot šo trigeri ir, ka formas atļauj šī trigera kodā manīt arī
esošā ieraksta lauku vērtības atkārtoti neizsaucot šo trigeri, jo citādi tas
var novest pie bezgalīgā cikla. Tāpēc izstrādātājiem jāuzmanās, lai šādi datu
tabulās netiktu ierakstītas nekorektas vērtības, jo formas, trigera izpildes
pozitīvā gadījumā, atzīmē ierakstu kā korektu. Ja trigeris ir formas līmenī,
tas izpildās, ja kaut vienā formas blokā tiek veikta ieraksta validācija. Ja
tas atrodas blokā līmenī, tad tikai, ja validācija notiek bloka ierakstiem;
f)
WHEN-VALIDATE-ITEM – trigeris, kas
līdzīgs WHEN-VALIDATE-RECORD trigerim, tikai izpildās veicot katra ievadlauka
validāciju. Izpildes kārtība tāda pati kā iepriekšējam trigerim, papildus šo trigeri
var izvietot arī paša ievadlauka līmenī;
g)
PRE-BLOCK – trigeris, kas izpildās
navigācijas procesa laikā pārvietojoties no viena bloka uz otru (ienākot
jaunajā blokā). Trigeris izpildās vēl pirms WHEN-NEW-BLOCK-INSTANCE trigera.
Parasti izmanto, lai kontrolētu pieejas tiesības blokam un piešķirtu mainīgo
vērtības. Trigeris neizpildās, ja Oracle Forms
4.5 validācijas vienība ir formas līmenis. Izpildes kārtība atkarībā no
atrašanās objektu kokā tāpat kā iepriekšminētajiem trigeriem;
h)
PRE-TEXT-ITEM – trigeris, kas
izpildās navigācijas procesa laikā pārvietojoties no viena objekta uz citu, pie
kam objektam uz kuru pārvietojas jābūt teksta ievadlaukam. Parasti izmanto, lai
aprēķinātu lauka vērtību atkarībā no citu iepriekšējo ieraksta lauku vērtības
vai arī piefiksētu esošo vērtību turpmākai lietošanai. Izpildes kārtība
atkarībā no atrašanās objektu kokā tāpat kā iepriekšminētajiem trigeriem;
i)
POST-BLOCK – trigeris, kas
atšķirībā no PRE-BLOCK trigera arī izpildās navigācijas laikā, taču atstājot
kādu no formas blokiem. Parasti izmanto, lai pārbaudītu vai lietotājam tiesības
atstāt bloku, balstoties uz kādu nosacījumu. Izpildes kārtība atkarībā no
atrašanās objektu kokā tāpat kā iepriekšminētajiem trigeriem;
j)
POST-TEXT-ITEM – tāpat kā
POST-BLOCK trigeris izpildās navigācijas procesa laikā atstājot kādu no teksta
ievadlaukiem. Izpildes kārtība atkarībā no atrašanās objektu kokā tāpat kā
iepriekšminētajiem trigeriem;
Gandrīz visiem
augstāk minētiem trigeriem, kas sākas ar WHEN-… (izņemot WHEN-RECORD-CREATED,
WHEN-VALIDATE-….) kopīgā (labākā) īpašība ir tā, ka tajos var izpildīt formas
ierobežotās funkcijas (restricted
built-ins), kas nav atļautas citos trigeros. Tas atļauj šajos trigeros
veikt vairāk darbību, kā citos. Visbiežāk minētie jautājumi programmētājiem,
kas sāk strādāt ar Oracle Forms 4.5
ir: ar ko pamatā atšķiras augstāk minētie trigeri un kā zināt kādus trigerus un
kad lietot? Atbildot uz šiem jautājiemiem gribas minēt vienkāršu sakarību. Visi
trigeri, kas sākas ar WHEN-… izpildās, kad jau beidzies navigācijas process,
kursors nostājies uz jaunā ievadlauka un formas gatavas datu
ievadam/labojumiem. Šajos trigeros (ar dažiem izņēmumiem) atļautas formas
ierobežotās funkcijas (restricted
built-ins), kas nav atļautas citos trigeros. Visi trigeri, kas sākas ar
PRE-… izpildās navigācijas procesa laikā pirms kursora novietošanās uz
attiecīgā objektā, bet pirms POST-.. trigeriem, kas izpildās “atstājot” kādu no
formas objektiem. Tā kā šie trigeri izpildās navigācijas procesa laikā, t.i.
pirms formas gatavas jaunam datu ievadam, šajos trigeros nav atļautas formas
ierobežotās funkcijas. Taču arī šo ierobežojumu iespējams apiet, šajos trigeros
izveidojot taimerus (timer), kas
izpildās tūlīt pēc to izveidošanas, kuros savukārt jau var izpildīt visas
formas ierobežotās funkcijas. Šāds “apvedceļš” ir ļoti viegli realizējams [9].
Bet atgriežoties
pie optimizācijas problēmām, biežāk pieļautās optimizācijas kļūdas, ko pieļauj
izstrādātāji, lietojot šos trigerus ir to nepareiza novietošana formas
hierarhiskajā objektu kokā. Tie tiek novietoti pārāk augstu vai arī tiek
pielietoti trigeri, kas izpildās biežāk nekā nepieciešams. Piemēram, pieņemsim,
ka formās ir 3 datu ievades bloki, kas ar relācijās saitēm pakārtoti viens
otram. Atkarībā no katra bloka konkrētā ieraksta vērtības ir
jāatļauj/jāaizliedz kāda konkrēta ievadlauka pieejamība (enabled/disabled), kas atkarīga tikai no konkrēta bloka konkrētā
ieraksta. Bez tā vēl arī no citās datu tabulās esošām vērtībām pēc konkrētas
formulas jāizrēķina un jāparāda kāda vērtība. Visvienkāršāk to protams izdarīt
(kas arī bieži tiek praktizēts) ir formas līmenī izveidojot
WHEN-NEW-RECORD-INSTANCE trigerī, kurā tiek izpildītas šīs
aizliegšanas/atļaušanas darbības un izrēķinātas attiecīgā lauka vērtības no
zināmajām trīs bloku attiecīgo ierakstu vērtībām. Tas viss ir viegli pārskatāms
un ērti lietojams, taču izpildes ātrums krietni samazinās, jo pārvietojoties
par katru ierakstu pašā zemākajā blokā, trigera kodā tiks izpildītas liekas
darbības, kas attiecas uz diviem augstāk esošajiem blokiem. Tas pats attiecas
arī uz pārvietošanos vidējā blokā. Šeit gan jāpiebilst, ka šajā gadījumā
trigeris izpildās pat lieku reizi. Pirmā reize būs izvēloties rakstu vidējā
blokā, pēc tam pakārtotājā. Forma automātiski parādīs piekārtotos rakstus
trešājā blokā, kur atkal būs jāizvēlas vajadzīgais raksts. To darot pašā
“augstākajā” blokā, trigeris jau izpildās lieki 2x uz katru ierakstu. Kā jau
zināms, šāda lieka koda izpilde samazina formas ātrdarbību, it sevišķi, ja
trigeros tiek veikts daudz aprēķinu un datu pieprasījumu no citām datu tabulām.
Savukārt minot
piemēru par nepareiza trigera izvēli, kā rezultātā tā kods tiek izpildīts pārāk
bieži (trigeris novietots hierarhiskajā līmenī pareizi), der minēt šādu
piemēru. Jaunajam ierakstam ir jāpapildina dažas lauku vērtības ar vērtībām no
citu datu tabulu laukiem. Tam tiek izmantots WHEN-NEW-RECORD-INSTANCE trigeris,
WHEN-RECORD-CREATED trigera vietā, katrā tā izsaukumā tiek pārbaudīts vai jaunā
ieraksta atribūts nav New. Lieki
piebilst, ka kods tiks izpildīts katru reizi pārvietojoties no viena ieraksta
uz otru un ja lietotājs jaunus ierakstus pievieno ļoti reti, kods izpildās
prakstiski nevajadzīgi (Parasti jau tā izpilde beidzas tūlīt pēc ieraksta
statusa pārbaudes, bet tomēr lieki tiek izsaukts trigeris). Izstrādātāji
parasti pieļauj šādas kļūdas gadījumos, kad pilnībā nepārzin visus Oracle Forms 4.5 trigerus un lieto tikai tos
kurus pārzin, pielāgojot tos nepieciešamajām situācijām.
1.1.3. Ne-tabulas lauku vērtību aktualizēšana
Ļoti bieži formās datu tabulu blokos
ir nepieciešams ievietot laukus, kas patiesībā nepieder tabulai, be gan tikai
rāda kāda tabulas lauka koda atšifrējumu no citas tabulas. Parasti to izmanto,
lai parādītu klasifikatoru kodu nozīmi. Šādi ne-tabulas lauki tiek iekļauti
bloka definīcijā. Pēc tam tiek rakstīts PL/SQL kods šo vērtību aktualizēšanai.
Tam parasti izmanto 2 trigerus: POST-QUERY, ko izmanto vērtības aktualizēšanai
nolasot ierakstus no datu tabulas un WHEN-VALIDATE-ITEM, ko izmanto gadījumos,
ja tiek mainīta klasifikatora vērtība. Visvienkāršākais risinājums šādas
klasifikatora koda nozīmes atlasīšanai ir standarta SQL datu pieprasījums formā
[6]:
SELECT name
INTO :block.code_name
FROM CODE_TABLE1
WHERE code = :block.code;
Tā kā šad tad
klasifikatoru vērtības var būt arī tukšas papildus tiek apstrādāti tādi
gadījumi (exceptions) kā
NO_DATA_FOUND un OTHERS, attiecīgi ierakstot tekstu, ka koda vērtība tukša vai
nezināma. WHEN-VALIDATE-ITEM trigeris izpildās tikai ievadot jaunu ierakstu vai
arī labojot esoša ieraksta vērtības. Tas izpildās tik reizes cik tiek veiktas
šādas operācijas. Savukārt POST-QUERY trigeris izpildās tik reizes cik bāzes
tabulas ieraksti tiek atlasīti no datu bāzes. Uz katru ierakstu vienu reizi,
katru reizi izpildot vienu un to pašu SQL datu pieprasījumu, no vienas un tās
pašas tabulas. SQL pieprasījumā mainās tikai maskas nosacījums, kas nosaka kurš
ieraksts jāatgriež. Atkārtoti pieprasot datus no vienas un tās pašas tabulas
tie būs servera operatīvajā atmiņā (cache)
un datu pieprasījums izpildīsies ļoti ātri. Bet skaidri redzams ka šāda darbība
ir vienkārši lieka, jo bieži ir daudz ierakstu, kam šī klasifikatoru vērtības
sakrīt. Bez tam visi datu pieprasījumi un atbildes tiek pārsūtītas pa tīklu,
radot lieku noslodzi datortīklā. Jāņem vērā arī fakts, ka parasti vienā blokā
šādu lauku, kuru vērtības ir klasifikatoru kodi ir ne tikai viens, bet gan
vairāki. Tātad uz katru ierakstu, kas tiek atlasīts no datu bāzes, tiek
papildus veikti vēl n datu pieprasījumi, lai parādītu attiecīgo klasifikatoru
kodu vērtības. Ja POST-QUERY trigerī tiek mainītas bloka lauka vērtības Oracle
formas attiecīgo ierakstu atzīmē kā labotu (changed),
kā rezultātā vēl papildus tiek izpildīts WHEN-VALIDATE-ITEM trigeris. To
protams var appiet uzstādot ieraksta atribūtu uz atlastīts (quered) programmātiski, taču tā atkal ir
lieka PL/SQL koda izpilde. Optimizācijas risinājums šai problēmai būtu, ja
visie šie dati tiktu atlasīti tikai vienreiz kādā virtuālajā masīvā vai kādā
citā formas objektā un nepieciešamības gadījumā formas vērstos pie šī objekta
nevis veiktu datu pieprasījumu no datu tabulas.
Kā viens no
labākajiem risinājumiem šai problēmai, autora skatījumā, ir izmantot Oracle Forms 4.5 objektu list item. Tā aktualizēšanai ir jāizveido ierakstu grupa, kas datu
nolasīšanai no datu servera - datu pieprasījumu izpilda tikai vienu reizi,
startējot formu. Šis formas objektam ir divas vērtības: pirmā, kas tiek
ierakstīta datu tabulā un otra, kas tiek parādīta lietotājam. Lai lietotājs
tāpat kā augstāk minētajā gadījumā zinātu, gan laukā ievadītā klasifikatora
kodu, gan tā informatīvo vērtību, ieraksta grupa tiek veidota sekojoši:
SELECT code, code||’-‘||code_name
FROM CODE_TABLE1;
Tādējādi lietotājs
redz abas vērtības, bet datu tabulas laukā ierakstās tikai atbilstošais kods.
Taču ja lietotājam paredzētā datu ievadforma domāta masveida datu ievadam, šāds
risinājums varētu būt arī pārāk neērts, jo šādi lietotāji parasti strādā zinot
šo lauku klasifikatoru kodu vērtības no galvas, un 2 vai 3 ciparu koda ievade
no klaviatūras var tikt veikta daudz ātrāk nekā šāda klasifikatora izvēli no list item. Bez tam šim Oracle Forms 4.5 objektam nav iespējas
nostāties uz attiecīgā raksta, ievadot raksta pirmās vērtības, kā tas ir
iespējams citiem MS Windows vidē
esošiem šādiem pašiem objektiem. Tas strādā tikai uz pirmā simbola vērtību.
Cerams, ka šī mazā kļūda tiks novērsta jaunajā produkta versijā Oracle Forms 5.0.
Arī šādos gadījumos,
autora skatījumā, labāk ir rīkoties šādi – blokā tiek izveidoti 2 objekti.
Viens datu ievadlauks klasifikatora kodam, kura vērtības tiek kontrolētas
izmantojot vērtību sarakstu (LOV) un
klasifikatora informatīvais lauks, objektu kura tips ir jau zināmais list item un kura atribūts List style vienāds ar Poplist vai T-list atkarībā no izstrādātāja gaumes. List item objekta atribūts Mirror
Item tiek uzstādīts vienāds ar ievadlauka objektu vārdu. Abus objektu (LOV un list item) vērtību aktualizēšanai tiek izmantotas divas (2)
ierakstu grupas, kas atlasa vienus un tos pašus datus. Problēma ir tikai faktā,
ka vērtību sarakstam parasti datus atlasa formā code, code_name, bet ierakstu grupai, kas aktualizē list item, tie vajadzīgi citā kārtībā – code_name, code. Protams šeit var
diskutēt, kas strādā ātrāk – n-tie datu pieprasījumi pēc vienas rindas no datu
tabulas, izmantojot indeksu, vai arī viens (vai 2, ja tiek izmantots otrais
variants ar 2 laukiem) visas datu tabulas ierakstu pieprasījums. Ja tabula,
kuru apskatām ir ļoti maz ierakstu, bet klasifikatoru tabula ļoti liela apjoma
– varbūt arī lielāks ieguvums būs no šī risinājuma (POST-QUERY trigera
izmantošana), taču parasti lielās sistēmās ir otrādi – ir ļoti daudz mazu
klasifikatoru tabulu, kuru informācija ir daudzās un lielās datu tabulās. Šādā
gadījumā viens datu pieprasījums pēc visas tabulas datiem izpildīsies daudz
ātrāk nekā n-tie pēc viena ieraksta. Kā tiks aplūkots vēlākā darba gaitā, tas
ir ļoti izdevīgi, ja lietotājs pie datu bāzes ir pieslēdzies izmantojot modemu,
kur pārāk liela datu plūsma tikai samazina formas ātrdarbību.
Protams pastāv arī
iespēja definēt virtuālās tabulas (view), kas atgriež jau atšifrētas
klasifikatoru kodu vērtības, tādējādi viss tiek atrisināts jau servera pusē.
Taču ja tas nav iespējams, tad neatliek nekas cits kā veidot vērtību atlasīšanu
caur trigeriem. (Problēmas parasti ir ja kādas tabulas divi vai vairāki lauki
atsaucas uz vienu un to pašu klasifikatoru, vai arī jāveic datu pieprasījums no
vairākām tabulām, kur katrā jāveic atkal pieprasījums no vienas un tās pašas
klasifikatoru tabulas. Šādi datu pieprasījumi kā rezultātu atgriež šo tabulu
rakstu reizinājumu)
1.2. Operāciju ar datnēm optimizēšana
Ļoti daudzas pakešu
apstrādes sistēmas (šeit runa nav par ON-LINE
sistēmām, kas savstarpēji sazinās, izmantojot kādu tīkla protokolu) veic
“sazināšanos” savā starpā, pārsūtot ASCII datnes ar nepieciešamo informāciju,
kas no vienas sistēmas tiek eksportētas un otrā importētas. Vienkāršāk
izsakoties, notiek datu apmaiņa ar datnēm, abām sistēmām zinot šo datņu
formātus. Pie lieliem datu apjomiem vai pie nosacījuma ka šīs operācijas jāveic
vairākkārt dienā sistēmas ātrdarbība šo operāciju laikā ir ļoti nozīmīga.
Šajā darbā netiks
aplūkotas situācijas, kad datņu ielasīšanu varētu veikt, izmantojot ORACLE
SQL*Loader, kurai sagatavotas datnes konkrētā formātā. Tas izskaidrojams ar to,
ka šajā vidē ļoti sarežģīti ir veikt datu veselumu kontroli, aplūkojot
kontrolvērtības, kas aprakstītas datnes nobeiguma rakstos vai citur. Ļoti bieži
šādas datnes tiek saņemtas jau zināmā formātā, kas nav atkarīgs no mūsu izvēles
(teiksim ielasot citu sistēmu datus, kas tiek sagatavoti viņu esošā formātā),
kas nozīmētu, ka šī datu datne pirms ielasīšanas būtu jāpārveido citā formātā,
lai to varētu ielasīt ar ORACLE SQL*Loader. Protams pastāv arī situācija datus
ielasīt pagaidu tabulās un tad veikt datu veselumu pārbaudi, bet šādus
gadījumus šoreiz neaplūkosim, jo tie prakstiski nedod nekādus labākus
rezultātus, jo laiks, kas patērēts datu ierakstīšanai pagaidu tabulās un
atlasīšanai no tām pēc tam, var tikt izmantots datu ielasīšanai pa tiešo,
nerakstot tās pagaidu tabulās. Parasti arī lietotājiem ir prasība, ka, jau
datnes ielasīšanas laikā, tie vēlas redzēt, ka datne ir ielasīta veiksmīgi vai
datnē ir kāda kļūda.
1.2.1. Datņu ielasīšana
Parasti rakstot
ASCII datņu ielasīšanu Oracle bāzēs pirmais, ko veic programmētāji, izmantojot
pakotnes TEXT_IO palīdzību, ir - tiek ielasīti datnes dati, turpat formas
programmu vienībās (programm units)
tiek pārbaudīts tās datu veselums, kā arī izpildītas nepieciešamās datu
ievadīšanas vai labošanas (INSERT un UPDATE) operācijas datu bāzē. Pie ļoti
maziem datu apjomiem šādu operāciju ātrdarbība ir ļoti laba un lietotāji
parasti par to nesūdzas, taču gadījumos, ja datnes izmēri strauji pieaug, t.i.
datnes apjoms ir 5000 un vairāk rindiņas, tās ielasīšana jau prasa zināmu
pacietību no lietotāju puses. Pamatā sistēmas “bremzēšana” notiek uz ļoti biežo
datu bāzes operāciju INSERT un UPDATE izpildīšanas rēķina, jo visas šīs operācijas,
izmantojot Oracle SQL*Net protokolu, tiek padotas Oracle serverim izpildei. Tad
tiek sagaidīta operācijas rezultāta atbilde. Gadījumos, kad klienta darba
vietas dators ir mazjaudīgs, kā arī pie lielām datortīkla noslodzēm, šo
operāciju izpildes laiks krasi samazinās.
Pirms veicam kādu
analīzi, lai noskaidrotu, ko var uzlabot lai datņu ielasīšana tiktu veikta
ātrāk, ir jānoskaidro cik liels laika patēriņs tiek veikts uz katru mums
nepieciešamo operāciju:
1)
Failu operācijas (atvēršana,
nolasīšana, aizvēršana);
2)
Datu kontrole (datu veseluma
pārbaude);
3)
Datu ievads datu bāzē (INSERT un UPDATE operācijas);
4)
Pārpalikums (f-ju izsaukumi, darba
gaitas parādīšana un informācijas sinhronizācija).
Tātad vispirms tiek izveidota forma,
kas veiks mums nepieciešamo datu ielasīšanu, sadalīšanu pa laukiem un
ievadīšanu datu bāzē (INSERT INTO…). Rakstot šo darbu šādiem testiem tika
izmantota autora vadībā izveidotās sistēmas VISA
Clearing Interface, datņu ielasīšanas forma, kas veic VISA CTF (VISA Center Transactions File) datņu
ielasīšanu sistēmā pirmā versija. Tajā visas datu kontroles un datu
ievadfunkcijas tika realizētas formas programvienībās vai bibliotekās (program units vai Program units from Libraries).
1.1. attēlā ir aplūkojams mēģinājumu
rezultāts, kuru laikā tika veikts sekojošais: ielasītas 2 VISA CTF datu
datnes – viena ar 3 300 rindiņām, otra
ar 56 300 rindiņām. Tika veikti 5 mēģinājumi pie dažādām klienta darba vietas
un datu bāzes servera noslodzēm. Pirmie 3 mēģinājumi veikti, darba dienas vidū,
kad paralēli tiek eskpluatēts arī datu bāzes serveris. Otrajā un trešājā
mēģinājumā uz klienta darba vietas vēl papildus tiek veiktas citas darbības –
strādāts ar citām Windows programmām /MS Word, MS Excel, Oracle Forms
Designer/, kā arī vēl spēlēta mūzika izmantojot MP3 datņu izpildprogrammu
WinAmp, kas kā zināms ļoti daudz patērē datora procesora laiku. /Normālas darba
stacijas noslodzes simulēšana/. Ceturtais un piektais mēģinājums tiek veikti
vēlu vakaros, kad praktiski nav nekādas noslodzes uz datu bāzes servera, kā arī
uz klienta darba vietas tiek darbināta tikai šī programma.
![]() |
1.1. attēls. Datņu ielasīšana no formām.
Kā redzams attēlā, datu ievadīšanai
bāzē (INSERT… operācija) tiek patērēts aptuveni sekojošs laiks: 5m17s – 10m15s
(13,3% – 14% no kopējā laika), kas, kā redzams attēlā, ļoti atkarīgs no klienta
darba vietas noslodzes. Jo tā lielāka, jo šīs operācijas izpilde vairāk
palēninās. Tas pats attiecināms arī uz datu kontroles un datu sadalīšanas
operācijām (vienkārša datu virknes sadalīšana pa laukiem /SubStr, Lpad un citas
operācijas/ un aizpildīšanu pēc konkrētiem algoritmiem /+, - , * u.c. operācijas/ ), kurām tiek patērēts no
15m15s līdz 27m40s (aptuveni 40% no kopējā laika).
Tā kā visas datu ievades operācijas
(INSERT INTO…) un unikālo identifikātoru nolasīšanas operācijas (SELECT
SEQ.nextval …) tik un tā tiek izpildītas uz servera, iespējams, ka tiek lieki
patērēts laiks šo operāciju nodošanai izpildei serverim (izmantojot SQL*Net
protokolu). Viena no idejām, kas varētu dod ātrākus rezultātus, iespējāms būtu
šīs operācijas izpilde uz servera, t.i. servera pakotnēs.
Vienīgā iespēja, kā samazināt virkņu
operācijām patērēto laiku, laikam būtu to izpilde uz jaudīgākas mašīnas, kas
šīs operācijas spētu veikt ātrāk. Iespēja, kas mums pastāv ir šo operāciju
pārnešana uz servera pakotnēm un to izpildīšana tur. Pakotnei tiek nodoti tikai
nepieciešamie parametri. Datu bāžu serveri parasti ir ļoti jaudīgi datori, kas
spēj veikt daudzreiz vairāk operāciju sekundē. Šādu operāciju pārnešana dod
varbūt ne acīmredzami ātrāku izpildi uz ātrākiem klienta darba vietas datoriem,
bet gadījumā, ja klienta darba vietas dators ir 486 tipa dators ir diezgan
ievērojama. Virknes sadalīšana pa
laukiem jau pašā servera pakotnē ir izdevīgāka arī ar to, ka funkcijas izsaukumos
tagad tiek nodots tikai viens parametrs – virkne, nevis visu datu ievades
operācijai nepieciešamos lauku dati, kas atvieglo formas programmas koda
rakstīšanu.
Visbeidzot tas reducējas uz to, ka uz
klienta darba vietas datora jeb konkrētāk Oracle formas, varētu izpildīt tikai
dažas operācijas, kuras nav iespējams izpildīt uz servera - datu nolasīšanu no
datnes, servera pakotņu funkciju vai procedūru izsaukšanu un rezultātu
parādīšanu lietotājam.
Tātad nākošajos
mēģinājumos tiek izmantota jau agrāk minētās formas VISA CTF datņu ielasīšanai
otrā versija, kurā forma tikai nolasa datus no datnes un nodod tos serverim,
gaidot tā atbildi par veiksmīgu vai neveiksmīgu datu ievades operācijas
izpildi. Ciklā, kamēr vien datnē eksistē dati, tiek veiktas sekojošas darbības:
While TEXT_IO.Get_Line(f,
line) LOOP
………….
IF NOT
VISA_READ_CTF.Write_data(line, errtxt) then
Message(‘Error writing data’||errtxt);
END
IF;
………..
END LOOP;

Servera pakotnes funkcijā Write_Data tiek veikta virknes sadalīšana pa laukiem, datu veseluma kontrole un datu ievades operācijas izpilde. Kļūdas gadījumā kļūda tiek atgriezta mainīgajā errtxt.
1.2. attēls. Datņu ielasīšana no formām, ja visas operācijas ar datiem
tiek veiktas servera pakotnēs.
Pirmajā variantā /1.2. attēlā
apzīmēti ar (F)/, Oracle formas programvienībās tiek veiktas visas operācijas,
t.i. datnes lasīšana, datu kontrole un datu ievades operācijas. Otrajā variantā
/attēlā apzīmēti ar (S)/, Oracle formas veic tikai datnes datu nolasīšanu un
servera pakotnes funkcijas izsaukšanu.
Arī šajā gadījumā tāpat kā iepriekš
tiek veikti 5 mēģinājumi - pirmie 3 tiek veikti, darba dienas vidū, kad
paralēli tiek eskpluatēts arī datu bāzes serveris. Otrā un trešā mēģinājuma
laikā uz klienta darba vietas vēl papildus tiek veiktas citas darbības –
strādāts ar citām Windows programmām. Ceturtajā un piektajā mēģinājumā šis
uzdevums ir vienīgais, kas noslogo gan datu bāzes serveri, gan klienta darba
vietas datoru.
Aplūkojot INSERT operācijas izpildes
laiku, datu kontroles laiku kā arī visas datnes ielasīšanas operācijas
koplaiku, jau redzama atšķirība izpildes ātrumā, kopsummā no 1,5 līdz pat 2
reizēm. Kur veidojas šī atšķirība ?
Kā redzams attēlā
abos gadījumos datņu operācijām patērētais laiks prakstiski neatšķiras, kas arī
ir loģiski, jo abos gadījumos to veic Oracle formas un viss atkarīgs tikai no
klienta darba vietas noslodzes – palielinoties klienta darba vietas noslodzei
laiks palielinās un samazinoties - samazinās. Tātad abos gadījumos patērētais
laiks datņu operācijām ir 1m50s – 4m10s, kas atkarīgs no klientu darba vietas
noslodzes. Noslodzes maiņas uz datu bāzes servera nekādi neiespaido datņu
ielasīšanas operācijas, kas tiek izpildītas uz klienta darba vietas datora.
Aplūkojot sīkāk
pārējo operāciju izpildes laikus, konstatējam, ka datu ievades operācijai
(INSERT INTO..), to izpildot servera pakotnē vidēji tiek patērēts 1m50s - 2m05s
(3,9% – 7,8% no kopējā laika), savukārt šo pašu operāciju izpildei formas
programmvienībās (program units vai Program units from Libraries) tika
patērēts 5m17s – 10m15s (13,3% – 14% no kopējā laika). Acīmredzams, ka laika
starpība šo operāciju izpildei formas programmvienībās un servera pakotnēs ir
2,5-5x, kas pie vienkāršu datņu ielasīšanas, kur pamatā tiktu veiktas tikai
datu ielasīšanas, dotu ātrāku operāciju izpildi. Pie kam jebkurā gadījumā, ja
palielinās klienta darba vietas noslodze, tad kopējais izpildes laiks, ja
operācija tiek izpildīta formās palielinās, bet ja uz servera - nemainās. Bet
ja noslodze tiek palielināta uz servera, tad abos gadījumos, neatkarīgi kur
tiek izsaukta datu ievades operācija, tās izpildes laiks palielinās, jo beigās
tik un tā operācija tiek izpildīta uz servera.
Nākošais mūs
interesējošais rādītājs ir datu veseluma kontrole un pārbaude pirms datu
ievades operācijas veikšanas, kas šo konkrēto mēģinājumu gadījumā sevī ietver
datnes rindas sadalīšanu pa laukiem (SubStr,
Decode, Translate un citas funkcijas), datu pārbaudi uz NULL vērtībām
laukiem, kam šādas vērtības nav pieļaujamas. Dažu lauku vērtības tiek
aprēķinātas no zināmām citu lauku vērtībām (sevī var ietvert arī datu
atlasīšanas operācijas no citām tabulām). Aplūkojot 1.2 attēlu varam konstatēt,
ka datu kontrolei servera pakotnē vidēji tiek patērēts no 4m30s līdz 4m40s (10%
– 17% no kopējā laika), savukārt šo pašu operāciju izpildei formas
programvienībās tiek patērēts no 15m15s līdz 27m40s (aptuveni 40% no kopējā
laika). Laika starpība šo operāciju izpildei formas programvienībās un servera
pakotnēs ir 3-6x, kas protams ļoti atkarīgs no veiktajām operācijām, taču
tendence ir skaidri saskatāma, ka operācijas ar virknes tipa (string) mainīgajiem, dažādu mainīgo
vērtību kalkulācija uz klienta darba vietas izpildās lēnāk, kaut vai tāda
iemesla dēļ, ka klienta darba vietas datoru procesori ir ar mazāku jaudu.
Noslodzes maiņas gan uz klienta darba vietas, gan uz datu bāzes servera šajā
gadījumā ir neatkarīgas. Tas nozīmē, ja izpildām operācijas Oracle formās, tad
uz servera palielināta noslodze neiespaido mūsu rezultātus un viss par ko
jārūpējas ir lai klienta darba vieta būtu noslogota pēc iespējas mazāk un
otrādi, ja operācijas tiek izpildītas servera pakotnēs.
Tātad secinājums,
kas tiek iegūts pēc šiem mēģinājumiem ir
- jebkuras operācijas ar datiem datu bāzē, ja tās jāveic lielos apjomos
daudz ātrāk izpildās, ja tās tiek izpildītas uz servera, t.i. servera pakotnēs.
Tas pats attiecināms arī uz virknes sadalīšanu, izmantojot tādas operācijas kā SubStr, Decode, Translate u.c.
Taču neskatoties uz
iegūtajiem labākajiem rezultātiem tik un tā datu ielasīšanas ātrums šķiet ļoti
lēns – vidēji 0.04-0.05 sekundes uz vienu datnes rindu (0.07-0.08, ja
ielasīšana un datu ievades operācijas notika tikai formas programvienībās).
Summējot mums visu zināmo kritisko operāciju laikus - faila nolasīšana + datu
kontrole + datu ievads mēs iegūstam vidēji 20-30% no koplaika. Zinot arī, ka
operācijas rezultātu pierakstam sistēmas žurnāla tabulās un parādīšanai uz
ekrāna tiek vidēji patērēts 10-15% resursu, mums pāri paliek ap 55-70% no
koplaika, kas atkarīgs no sistēmas noslodzes. Vairāk kā puse no laika resursiem
kaut kur tiek patērēta, taču ne mums vajadzīgajās operācijās. Kur tiek patērēts
šis laiks? Kārtīgi izpētot uzrakstīto formas kodu un atceroties pašā sākumā
minēto par koda optimizāciju ciklu ķermenī, iegūstam sekojošo – zinot ka
ielasam datnes, kuru apjoms pārsniedz 59 600 rindas un pie katras rindas tiek
izsaukta servera pakotnes funkcija, kas veic datu ievadoperāciju, forma veic 59
600 servera pakotņu izsaukumus, katru reizi kā parametru nododot vienu rindu.
Ja datortīkls, kurā darbojas sistēma ir noslogots, samazinās funkcijas
izsaukšanas un atbildes laiks. Pirmā ideja, kas šādā situācijā nāk prātā ir –
serverim ir jānodod uzreiz vairākas rindas, teiksim 5-10, tādējādi samazinot šo
izsaukumu skaitu attiecīgi 5-10 reizes. 5960 funkcijas izsaukumu 59 600 vietā,
nododot serverim tikpat daudz informācijas (tās pašas 59 600 rindas ar
informāciju), varētu dod mazliet labākus rezultātus. Taču izmēģinot, iegūtie
rezultāti patiešām pārsteidz, kas norāda tikai uz to, ka patiešām daudz laika
tiek tērēts tieši veicot servera pakotņu funkciju un procedūru izsaukumus no
formām.
Tātad atkal tika
veiti 5 mēģinājumi pie dažādām formu un servera noslodzēm. 1.3. attēlā ir
parādīti šo mēģinājumu rezultāti.

1.3. attēls. Datnes ielasīšana no formām, ja servera pakotņu
izsaukums tiek samazināts 10 reizes.
Kā jau redzams 1.3.
attēlā šāda realizācija, izsaucot servera pakotnes funkciju, kurai tiek nodotas
uzreiz 10 rindas, dod apmēram 2x reizes ātrāku realizāciju, kas panākts
samazinot laiku, kas tiek patērēts procedūru izsaukumiem, jo datnes operācijām,
datu ievadam datu bāzē un datu kontrolei patērētais laiks nav mainījies. Datu
ielasīšanas ātrums tagad ir vidēji 0.01-0.02 sekundes uz vienu datnes rindiņu.
Kas notiktu, ja servera pakotnes funkcijai tiktu padotas 20, 30 vai pat 50
rindas uzreiz? Ātrdarbība palielinātos taču ne vairs tik ļoti, jo pie notiekta
rindu skaita tiktu sasniegta iespēju robeža. Bez tam jāatceras, ka uz servera
ir jārealizē papildus programmas kods kas apstrādā visas padotās rindas, kam
kļūdas gadījumā n-tajā rindā ir jāaptur turpmākā apstrāde. Veicot šos
mēģinājumus, tas tika realizēts ļoti vienkārši, bet gari:
IF str1 IS NOT NULL then
rez := WRITE_DATA(str1, err_txt_tmp);
err_text := err_txt_tmp;
IF rez and str2 IS NOT NULL then
……………………
……………………
Return
rez;
END IF;
ELSE
Return TRUE;
END IF;
END;
Funkcijas izsaukums
formā praktiski paliek nemainīgs, jo izmainās tikai tas, ka uzreiz jānolasa 10
rindas un tās jānodod servera procedūrai, kas atgriež vai nu pozitīvu rezultātu
ar visiem brīdinājuma ziņojumiem vai arī sliktākā gadījumā kļūdas paziņojuma
tekstu.
Lai lietotājs
varētu sekot datnes ielasīšanas procesam, t.i. datnes ielasīšana turpinās un
pašlaik vēl nekādu kļūdu nav bijis, ir jāveic kaut kāda informācijas parādīšana
lietotājam. MS Windows lietotājiem ļoti pieņemams un viegli uztverams ir
progresa rādītājs. (Par tā realizāciju un citiem sīkumiem tiks aprakstīts darba
nākošajā nodaļā par lietotāja-datora interfeisa uzlabošanu). Atceroties
iepriekš minēto par servera pakotņu funkciju izsaukšanu gandrīz 60 000 reizes
varam saprast, ka gadījumā, ja pēc katras rindas tiek mēģināts parādīt paveikto
un vēl aprēķināts cik laika nepieciešams līdz procesa beigām - lieki tiek tērēts
laiks. Tika veikts papildus mazs mēģinājums veicot šo pašu datņu ielasīšanu,
informāciju sinhronizējot tikai pēc katrām 500 rindām /1.3.attēlā redzamie
mēģinājumi tika izpildīti sinronizējot informāciju ik pēc 10 rindām/. Rezultāts
– datnes tiek ielasītas ātrāk, pamatā tiek samazināts kopējais procesa izpildes
laiks. Tātad Oracle Forms 4.5
procedūra informācijas sinhronizēšanai formās Syncronize patērē zināmu laiku. Konkrētu laiku nav iespējams
uzrādīt, jo tas ļoti atkarīgs no darba vietas noslodzes. Tās patērētais laiks
vienā izpildes reizē var būt ļoti mazs, taču kopsummā tas veido sekundes un
minūtes. Tapēc pirms izvēlēties pareizo sinhronizācijas periodu ir jāapsver cik
reāli bieži tas nepieciešams, lai lietotājs saprastu, ka process turpinās, kā arī
lai tas nebūtu pārāk bieži, tādējādi lieki tērējot sistēmas laika resursus.
1.2.2. Datņu veidošana
Kā jau tika minēts
iepriekšējā apakšnodaļā, pirmais programmas kods, ko uzraksta izstrādātāji arī
šajā gadījumā ir formas programmvienībās tiek izveidoti kursori (cursor), kas atlasa nepieciešamos datus
un pēc tam, izmantojot pakotnes TEXT_IO palīdzību tie tiek pārrakstīti datnēs.
Tāpat šajās programmvienībās tiek izpildītas nepieciešamās datu manipulācijas
operācijas (INSERT un UPDATE). Šāda uzdevuma realizācija ir
ļoti viegli un ātri uzrakstāma un pie ļoti maziem datu apjomiem ātrdarbība
vienmēr apmierina klienta prasības. Taču strauji palielinoties datu apjomiem,
kā arī gadījumos, ja tiek izmantoti saliktie datu pieprasījumi no vairākām datu
tabulām (join izmantošana) vai lieli
maskas nosacījumi (where…), šādu
kursoru atvēršanas laiks strauji palielinās. Pamatā sistēmas “bremzēšana”
notiek, veicot atlasīto datu, t.i. kursora rezultātu, pārsūtīšanu no servera uz
formām, izmantojot Oracle SQL*Net protokolu. Gadījumos, kad klienta darba
vietas dators ir mazjaudīgs, kā arī pie lielām datortīkla noslodzēm šīs
operācijas izpildes laiks samazinās vēl straujāk.
Tāpat kā iepriekš,
veicot datņu ielasīšanu, vispirms tiek veikta analīze - cik liels ir laika
patēriņš uz katru mums nepieciešamo operāciju. Tādējādi tiek noskaidrots, ko
iespējams uzlabot, lai datņu veidošanas operācijas būtu ātrākas. Mūs
interesējošie faktori ir:
1)
Datu atlasīšana (datu atlasīšanas
operācijas – SELECT …);
2)
Nepieciešamās informācijas
labošana datu bāzē (INSERT… & UPDATE….);
3)
Datņu operācijas (atvēršana,
ierakstīšana, aizvēršana);
4)
Pārpalikums (f-ju izsaukumi, darba
gaitas parādīšana un informācijas sinhronizācija).
Vispirms tiek izveidota forma, kas
veic mums nepieciešamo datu atlasīšanu, izvadrindas saformēšanu un ierakstīšanu
failā. Rakstot šo darbu, šādiem mērķiem tika izmantota, autora vadībā
izveidotās sistēmas VISA Clearing
Interface forma, kas veic VISA CTF datņu veidošanu sistēmā pirmais variants. Tajā datu atlasīšanas, datu
kontroles un datņu veidošanas funkcijas tika realizētas formas programvienībās
vai bibliotēkās (program units vai Program units from Libraries).
Zemāk, 1.4. attēlā
ir aplūkojams veikto 5 mēģinājumu rezultāts. Katrā no tiem tika izveidotas 2-as
VISA CTF datnes – viena ar 3200
rindiņām, otra - 53 800 rindiņām.

Jau iepriekš jāmin, ka šajā darbā netiek apskatīta Oracle servera datu pieprasījumu (SELECT….) optimizācija, kam bez šaubām arī šajā gadījumā ir liela nozīme. Tā kā mans mēģinājumu mērķis ir tieši Oracle Forms 4.5 koda optimizācija, tika pieņemts, ka izmantoti datu pieprasījumi ir maksimāli optimizēti.
1.4. attēls. Datnes veidošana no formām.
Kā redzams 1.4. attēlā, datu
atlasīšanai no datu bāzes (SELECT…)
tiek patērēts laiks no 10m30s līdz 23m50s (aptuveni 30% no kopējā laika), kas,
ļoti atkarīgs no klienta darba vietas datora noslodzes. Jo lielāka noslodze, jo
vairāk laika tiek patērēts šai operācijas izpildei, kaut gan procentuāli
patērētais laiks paliek tas pats – apmēram 30%. Tas pats attiecināms arī uz datu
maiņas operācijām datu bāzē (INSERT…
& UPDATE…), kurām tiek patērēts
no 3m5s līdz 6m30s (aptuveni 9% no kopējā laika).
Kā jau tika minēts pie datnes
ielasīšanas, arī šeit visas datu manipulācijas operācijas (SELECT, INSERT & UPDATE….) tik un tā tiek izpildītas uz
servera. Tas nozīmē, ka lieki tiek patērēts laiks šo operāciju nodošanai
serverim izpildei. Kā jau zināms no datnes ielasīšanas mēģinājumiem, labākus
rezultātus iespējams iegūt izpildot šīs operācijas uz servera, konkrētāk -
servera pakotnēs.
Virkņu operācijām patērēto laiku
tāpat iespējams samazināt tās izpildot uz jaudīgāka datora, kas šīs operācijas
spētu veikt ātrāk. Tātad tāpat kā datnes ielasīšanas gadījumā šīs operācijas
tiks “pārnestas” uz servera pakotnēm, jo to izpildīšana tur dod vislabākos
rezultātus. Šajā gadījumā, tas nozīmē, ka servera pakotnes funkcija atgriež
nevis tikai atlasītos sistēmas datus no datu tabulām, bet gan jau saformētu
virkni, kuru atliek tikai izvadīt datnē. Optimizējot datnes veidošanu, pirmais
mērķis, tāpat kā veicot datnes ielasīšanu, ir visas operācijas, kas izpildās
lēni un palielinoties klienta darba vietas datora noslodzei vēl lēnāk, izpildīt
citur. Tas nozīmē uz klienta darba vietas datora Oracle formās tiek izpildītas
tikai datnes operācijas un servera pakotņu funkciju vai procedūru izsaukšanu un
rezultātu parādīšana lietotājam.
Atceroties secinājumu, kas tika
iegūts pie datnes ielasīšanas, arī šajā gadījumā uzdevuma optimizācija ir -
operācijas kas tik un tā tiek izpildītas datu bāzes serverī, ir obligāti jāizpilda
datu bāzes servera pakotnēs, jo tādējādi to izpildi nekavē, teiksim, klienta
darba vietas noslodze.
Nākošajos
mēģinājumos tika izmantota, jau agrāk minētās formas VISA CTF datnes veidošanai
nākamais variants, kurā forma tikai saņem rindu no servera pakotnes funkcijas
un ievada to datnē. Šādas funkcionalitātes realizēšana salīdzinājumā ar datnes
ielasīšanu ir daudz sarežģītāka, jo jākontrolē izveidoto kursoru stāvoklis
(atvērts, aizvērts, vai vēl ir rakstu). Vispirms pakotnē ir jāatver visi nepieciešamie
datu kursori, kuros tiks atlasīti dati. Pēc tam ciklā, kamēr vien eksistē dati
kursoros, tie jāatgriež formai, kas tos savukārt ievada datnē. Realizācijas
kods varētu izskatīties apmēram šāds:
IF NOT
VISA_WRITE_CTF.Open_Cursors(errtxt) then
Message(‘Error opening data cursors!’);
END IF;
While
VISA_WRITE_CTF.Get_Data(line, errtxt) LOOP
………….
TEXT_IO.Put_Line(f,
line) then
………..
END LOOP;
IF errtxt IS NOT NULL
then
Message(‘Error reading data -’||errtxt);
END IF;
IF NOT
VISA_WRITE_CTF.Close_Cursors(errtxt) then
Message(‘Error closing data cursors!’);
END IF;

1.5.attēls. Datnes veidošana no formām, ja datu atlasīšanas operācijas
tiek veiktas servera pakotnēs.
Pirmajā variantā /1.5. attēlā
apzīmēti ar (F)/, Oracle formas programvienībās tiek veiktas visas operācijas,
t.i. datu rakstīšana datnē, datu atlasīšana un citas datu labošanas operāciju
izpilde, bet otrajā /attēlā apzīmēti ar (S)/, Oracle formas veic tikai
rakstīšanu datnē un servera pakotnes funkcijas izsaukšanu. Attiecīgā servera
pakotnes funkcija katrā izsaukumā atgriež pa vienai rindai, kas ierakstāma
datnē.
Šie mēģinājumi tāpat kā visi
iepriekšējie veikti pie dažādām gan klienta darba vietas, gan servera
noslodzēm.
Aplūkojot datnes veidošanu, kad visas
programvienības atrodas formās un datnes veidošanu, izmantojot funkcijas
servera pakotnē, redzama atšķirība izpildes ātrumā no 2 līdz pat 2,5 reizēm.
Kuru operāciju uzlabojums veido šo atšķirību ?
Kā jau redzams 1.5.
attēlā abos gadījumos datnes operācijām patērētais laiks prakstiski neatšķiras
(ar minimālām izmaiņām, kuras raksturo klienta darba vietas noslodze attiecīgā
mēģinājuma laikā). Tas ir loģiski, jo abos gadījumos tās tiek veiktas formās uz
klienta darba stacijas. Abos gadījumos patērētais laiks datnes operācijām ir no
1m40s līdz 4m15s, kas ļoti līdzīgs laikam, kas tika patērēts ielasot datnes datus
ar tādu pašu apjomu.
Tāpat kā pie datnes
ielasīšanas arī šoreiz tiek aplūkots katras operācijas izpildes laiks, lai
konstatētu, kuras operācijas “pārnešana” uz servera pakotnēm devusi vislielāko
ieguldījumu datnes veidošanas optimizācijā. Datu atlasīšanas operācijai (INSERT…), to izpildot servera pakotnē,
vidēji tiek patērēts no 1m59s līdz 2m32s (6,2% – 12% no kopējā laika), savukārt
šīs pašas operācijas izpilde formas programvienībās (program units vai Program
units from Libraries) tiek patērēts 10m27s – 23m50s (aptuveni 30% no kopējā
laika). Acīmredzams, ka laika starpība šo operāciju izpildei formas
programvienībās un servera pakotnēs ir 10x, pie kam abos gadījumos tiek
izmantotas tās pašas datu atlasīšanas komandas. Tāpat izmantoti tiek tie paši datu
tabulas indeksi un palīdzības teksti (hints)
SQL teikumos. Ja palielinās klienta darba vietas noslodze, tad kopējais
izpildes laiks arī palielinās. Savukārt, ja datu atlasīšana izpildās servera
pakotnēs, tad izpildes laiks nepieaug tik krasi. Ja savukārt noslodze tiek
palielināta uz servera, tad abos gadījumos, neatkarīgi no tā kur tiek izsaukta
datu atlasīšanas komanda, tās izpildes laiks palielinās, jo tā tik un tā tiek
izpildīta uz datu bāzes servera.
Nākamais apskates objekts ir datu
labošanas komandu (INSERT & UPDATE) salīdzinājums. Aplūkojot 1.5.
atēlu redzams, ka datu izmaiņām no servera pakotnēm tiek patērēts no 35s līdz
40s (2% – 4% no kopējā laika), savukārt šo pašu operāciju izpildei formas
programvienībās tiek patērēts no 3m5s līdz 7m6s (9% – 10% no kopējā laika).
Laika starpība šo operāciju izpildei formas programvienībās un servera pakotnēs
ir 6-13x, kas protams ļoti atkarīgs no veiktajām operācijām, dažos gadījumos
tas varētu būt tikai 2-3x, citos varbūt pat 15x. Kā jau zināms no iepriekš gūtiem
rezultātiem, veicot datnes ielasīšanu, šādu operāciju izpilde servera pakotnēs
dod labākus rezultātus jebkurā gadījumā.
Tāpat kā veicot
datnes ielasīšanu arī datnes veidošanas gadījumā, neskatoties uz iegūtajiem
labākajiem rezultātiem datnes veidošanas ātrums tāpat šķiet ļoti lēns – vidēji
0.02-0.04 sekundes uz vienu datnes rindu atkarībā no datu servera un klienta
darba vietas noslodzes (0.04-0.08, ja datu atlasīšana datnes veidošanai tika
veikta tikai formas programvienībās). Atceroties iegūtos secinājumus, zinām, ka
jāsamazina servera pakotnes funkciju izsaukumu skaits, lai samazinātu izpildes
laiku. Tādējādi serverim tiek pieprasīts atgriezt uzreiz vairākas rindas,
teiksim 10. Tas nozīmē, ka šo izsaukumu skaits tiek samazināts attiecīgi 10
reizes.
Tāpat atkal tika
veikti 5 mēģinājumi pie dažādām klienta darba vietas un datu bāzes servera
noslodzēm. 1.6. attēlā ir parādīts šo mēģinājumu rezultāts.

1.6.attēls. Datnes veidošana no formām, ja servera pakotņu funkciju
izsaukums tiek samazināts 10 reizes.
Kā jau bija
gaidāms, šāda realizācija, kad tiek izsauktas servera pakotnes funkcija, kas
atgriež uzreiz 10 rindas ar datiem dod apmēram 2x reizes ātrāku realizāciju,
kas panākts samazinot laiku, kas tiek patērēts procedūru izsaukumiem, jo datnes
operācijām, datu labojumiem datu bāzē un datu formēšanai patērētais laiks
prakstiski nav mainījies. Datu pārrakstīšanas datnē ātrums tagad vidēji
0.01-0.02 sekundes uz vienu datnes rindu. Iespējams, ka ja servera pakotnes
funkcija atgrieztu uzreiz 20 vai pat 50 rindas uzreiz ātrdarbība palielinātos
vēl mazliet, taču ne tik ļoti krasi. Bez tam jāatceras, ka uz servera papildus
ir jārealizē programmas kods kas apkopo visas rindas izejas parametros, kā arī
jāatgriež visi kļūdu un brīdinājumu ziņojumi, ja tādi bijuši.
Kā jau tika minēts pie datnes
ielasīšanas, lai lietotājs varētu sekot datnes veidošanas procesam ir jāveic
kaut kāda informācijas parādīšana lietotājam. Tāpat arī šajā gadījumā der
atcerēties, ka informācijas sinhronizācija pēc katras rindas ir lieka un tikai
patērē laiku. Optimālais variants ir, ja informācija tiek sinhronizēta vismaz 1
reizi sekundē. Ar to ir pietiekoši, lai lietotājs saprastu, ka process
turpinās. Šajā gadījumā, kad vinai rindai tiek patērēts apmēram 0.01 sekunde –
ir pilnīgi pietiekoši, ja informācija tiek sinhronizēta ik pēc 100 rindām.
1.2.3. Pakotnes DBMS_PIPE pielietojums
Strādājot kādu laiku pie vienas
problēmas risināšanas, vai kā mūsu gadījumā, konkrēti, pie datnes ielasīšanas
optimizācijas, ļoti bieži tiek sasniegti it kā ļoti labi rezultāti un
teorētiski pierādīts, ka tas ir maksimālais, ko iespējams iegūt. Taču parasti
jāatceras ka šis ir pats labākais rezultāts, izmantojot šo tehnoloģiju vai šo
algoritmu vai šos līdzekļus. Arī šoreiz tā tas izrādījās tikai īsu laiku līdz
autora rīcībā nonāca ideja, izmantot pavisam citus līdzekļus datu nosūtīšanai
no servera līdz formām, jo kā jau tika minēts iepriekš, pašu datu atlasīšana,
rakstīšana failā un citas operācijas kopumā aizņem tikai ne vairāk kā 50% no izmantotajiem
laika resursiem. Atlikušie 50% “pazūd” kaut kur formas “iekšienē” un servera
procedūru izsaukumos. Tātad jaunākā ideja, ja tā to drīkst dēvēt, ir citas
Oracle servera pakotnes izmantošana, kas ļauj daudz straujāk atlasītos datus
nosūtīt formām.
DBMS_PIPE – tā ir
Oracle servera pakotne, kas ļauj nosūtīt ziņojumus starp divām sesijām. Tā ir
līdzīga UNIX vidē pazīstamai komandai pipe.
Izmantojot funkciju send_message var
tikt nosūtīts ziņojums, bet izmantojot funkciju receive_message -saņemt. Savukārt, lietojot funkcijas pack_message un unpack_message, ziņojumi var tikt ievietoti vai izņemti attiecīgi
no statiskā bufera. Pakotnes kanāli (pipe)
var strādāt privātā modē, kas nozīmē, ka tikai sesijas, kas izveidotas ar vienu
un to pašu lietotāja identifikatoru (user-id)
var rakstīt un lasīt noteiktajā kanālā (pipe).
Kanāli var tikt atvērti arī publiskai lietošanai, kas ļauj visiem sistēmas
lietotājiem, kam ir tiesības uz servera pakotni DBMS_PIPE, to izmantot. Tas
tiek norādīts veidojot šo pakotnes kanālu (pipe),
kas tiek identificēts ar viennozīmīgu vārdu pipename.
Pati labākā šo pakotņu kanālu īpašība ir ka tie strādā neatkarīgi no
tranzakcijām, t.i. COMMIT un ROLLBACK operācijas neiespaido datus,
kas atrodas pakotnes kanālos. Bez tam ar šiem kanāliem var strādāt asinhronā
modē, tas ir rakstīšanas un lasīšanas kārtība pakotnes kanālā nav definēta. To
var darīt kad vien ir dati, ko rakstīt. Tāpat vairāki lietotāji vienlaicīgi var
rakstīt vienai un tai pašā kanālā un vienlaicīgi arī no tā nolasīt informāciju
[11].
Risinājums
konkrētajai datnes veidošanas (arī ielasīšanas) problēmai varētu būt, ka
neatkarīgs servera process nepārtraukti pakotnes kanālā raksta atlasītos datus
no kursoriem, bet savukārt no klienta darba stacijas Oracle formās cits neatkarīgs
process veic šo datu savākšanu un ievadīšanu datnē. Tā kā šie abi procesi
notiek neatkarīgi, t.i. servera pakotne negaida izsaukumu no formas, lai
nolasītu nākamo rakstu no kursora (fetch
next records), bet lasa tos nepārtraukti, kā arī klienta process negaida uz
servera pakotnes funkciju, kamēr tā atgriezīs rakstu, bet gan nepārtraukti tos
nolasa no pakotnes kanāla (pipe),
failu izveidošana notiek daudz ātrāk, jo ne viens ne otrs process negaida uz
otru.
Šīs pakotnes
ātrdarbības testiem tika izmantota SIA Tieto Konts sistēmas Issuing autorizācijas datnes (Q file) veidošanas forma, kas lieto
augstāk minēto DBMS_PIPE pakotni.

1.7.attēls. Datnes veidošana no formām, lietojot DBMS_PIPE pakotni.
Patiesībā esošais
risinājums ir izveidots ar daļēju darbības sinhronizāciju, izmantojot divus
kanālus. Servera process veido 32 kilobaitu lielu informācijas apjomu, kas 8
reizes pa 4 kilobaitiem (puse no kanāla maksimālā apjoma) tiek iesūtīts kanālā.
Laikā kamēr tiek pārsūtīts pēdējais no 8 gabaliem un tas arī nolasīts, servera
process jau veido nākamos 32 kilobaitus nosūtāmās informācijas. Šai daļējai
sinhronizācijai starp formām un servera pakotni arī tiek izmantots otrais
kanāls. Formas nosūta informāciju, ka jaunā pakete nolasīta, bet servera
process nosūta informāciju, ka kanālā ir ievietots jauns datu sūtījums. Šis
uzdevums pagaidām vēl nav realizēts tā lai abi procesi varētu strādāt pilnīgi
neatkarīgi, t.i. servera pakotne tikai sūta izveidoto informāciju kanālā, bet
formas tikai nolasa informāciju no tā. Tas izskaidrojams ar to, ka vēl līdz
galam nav izpētītas visas DBMS_PIPE pakotnes funkcijas kā arī vēl nav skaidra
pakotnes darbība, ja kanālā nepārtraukti tiks sūtīta informācija. Bez tam nav
skaidrs vai šāda realizācija 100% nenoslogos servera procesorus, jo
nepārtraukti tiks veikta datu rakstīšana kanālā. Pašlaik vēl nav izpētīts arī
kā šādos gadījumos iespējams atšķirt rakstīšanas kļūdu no fakta, ka pakotnes
kanāls reāli jau ir pārpildīts un tajā vairs nav iespējams rakstīt. Šis ir
viens no uzdevumiem, ko autors vēlas izpētīt tuvākajā nākotnē.
Atgriežoties pie
mēģinājumu rezultātiem, tāpat kā visos iepriekšējos gadījumos tika veikti 5
mēģinājumi, pie dažādām servera un klienta darba vietas noslodzēm. Izveidotā
datne satur 221 000 ierakstu un aizņem aptuveni 33 megabaitus informācijas.
Salīdzinājumā ar VISA CTF datnēm, kas tika veidotas iepriekšējos mēģinājumos,
to apjoms bija apmēram 60 000 ierakstu, kas aizņēma aptuveni 13 megabaitus. Šīs
datnes veidošana, kas ir 2-3 reizes lielāka, pat sliktākajā gadījumā tika
patērēts tik pat daudz laika cik iepriekšējās datnes (VISA CTF) veidošanai
labākajā gadījumā. Lieki piebilst, ka jaunais datnes veidošanas risinājums ir
daudz efektīvāks un kā tā maksimums, jau varētu tuvoties tīkla darbības un
servera ātrumam, kas nepieciešams datnes datu pārsūtīšanai pa tīklu un
ierakstīšanai datnē. Vidēji patērētais laiks, veidojot šo datni, ir no 1.66
līdz 2.36 sekundēm uz 1000 datnes rindām jeb 0.0016-0.0024 sekundes uz vienu
datnes rindu.
Kā jau tikai minēts
šis risinājums datnes veidošanai ir pagaidām izstrādes procesā, tāpēc arī
attēlā nav minēti konkrēti laiki, kas patērēti tādām operācijām kā datu
atlasīšana, labošana un ierakstīšana datnē. Autors cer tuvākājā laikā sīkāk
iepazīties ar DBMS_PIPE pakotnes darbību un ja iespējams pilnveidot šo uzdevumu
līdz pilnīgi neatkarīgai procesu darbībai, ja tas iespējams, kas jau tika
minēta kā daļēja nepilnība šim risinājumam.
1.3. Datu ievadformu optimizācija (pieslēgums datu bāzes serverim, izmantojot modemu)
Risinot Oracle Forms 4.5 koda optimizācijas problēmu,
manuprāt, viens no veidiem kā reāli apzināties to formas koda daļu, kas rada
vislielāko datortīkla noslodzi, iespējams, izpētot formu darbību vidē, kad
Oracle Forms 4.5 kā klients ar
serveri sazinās, izmantojot modemu. Tādos gadījumos iespējams viegli vērot
tīkla noslodzes grafiku, vienkārši izpētot modema nosūtītos un saņemtos datus.
Ja strādājošās
sistēmās arī pastāv šāds risinājums, tad tas parasti tiek pielietots situācijās
centrs-filiāle, kad “centrā” jeb organizācijas centrālajā ofisā atrodas Oracle
datu bāzes serveris, bet filālēs, kas var atrasties pat 100 un vairāk kilometru
attālumā serveriem, pieslēdzas, izmantojot modemu, pa telekomunikāciju
kanāliem. Šādos gadījumos pieslēguma ātrums atkarīgs no modemiem. Parasti tas
ir vai nu 14 400, 19 200 vai 33 000
bit/s. Tas ir ļoti maz, ja salīdzina ar datortīkliem, kur ātrums parasti
sasniedz 10 Mbit/s vai pat 100Mbit/s. Bez tam jāņem vērā arī fakts, ka
daudzviet arī tepat Latvijā pat, ja ir ļoti ātri modemi, sliktās
telekomunikāciju līnijas neļauj izveidot ātrus savienojumus. Brīžiem pieslēguma
ātrums varbūt tikai 19 200 vai pat 14 400 bps. Ja izstrādātās formas nav
testētas šādiem darba apstākļiem un tās, piemēram, veic lielus datu
pieprasījumus, darbs šādā vidē var būt ļoti lēns un neefektīvs. Šajā nodaļā
tiks apskatīti jau 1.1. nodaļā minētie formas objekti un to atribūti un kā tie
iespaido formu ātrdarbību un kā to iespējams novērst.
![]() |
![]() |


![]() |
|


1.8. attēls. Mēģinājumos izmantotais servera un klienta darba vietas
savienojums.
Autora piezīme:
Tālāk darba aprakstā uzrādītie datu plūsmas apjomi uzrādīti pirms modema
programmatūras datu kompresijas, t.i., ja uzrādīts, ka nosūtīts 100 000 baitu,
tas nozīme, ka reāli savienojuma fiziskā līmenī nosūtīts tikai 20 000 – 30 000
baitu. 70 – 80% ir vidējā kompresijas pakāpe, strādājot ar Oracle Forms 4.5. Strādājot datortīklā šāda
datu kompresācija nenotiek, tādējādi skaidri var redzēt, cik liela ir datu
plūsma datortīklā. Ļoti iespaidīgi skaitļi būs redzami nodaļas beigās, apskatot
datnes ielasīšanu.
Šajā nodaļā tiks
aplūkoti, autora uztverē, visbiežāk lietoto formas objektu un atribūtu, kā arī
dažādu operāciju iespējamā darbības uzlabošana, pamatojot to ar piemēriem.
Visos attēlos darbā attēlota datu plūsma – ienākošā un izejošā, ka arī kopējā.
Strādājot šādās vidēs, kad savienojums tiek organizēts, izmantojot modemu,
samazinot datu plūsmas apjomu, mēs attiecīgi paātrinam formas darbību, jo
lietotājam nav jāgaida, kamēr dati tiks saņemti vai nosūtīti dati. Bez tam
jāņem vērā, ka 100 Kb saņemšana uzreiz saņemot kā vienu lielu datu veselumu
notiek ātrāk, nekā 10 reizes pa 10Kb, tādējādi veicot 9 liekus datu pieprasījumus.
Šī ideja tiek izmantota, optimizējot datu pieprasījumus no datu bāzes servera.
Jāatceras, ka katra
konkrētā atribūta vērtības maiņa dod ļoti maz. Reizēm tā ir samazināta datu
plūsma, tādējādi palielinot atbildes ātrumu uz kādu pieprasījumu, reizēm vienkārši
palielināts atbildes ātrums uz kādu darbību. Katrs šāds uzlabojums formu
ātrdarbībā dod 2-4 sekundes ātrāku darbību uz katru veicamo operāciju. Taču
visu šo darbību uzlabojums kopumā, dod daudz ietaupīta laika, kas parasti tiek
reāli novērtēta no lietotāja puses.
1.3.1. Datu atlasīšana pēc maskas un piesaistīto tabulu raksti
Viens no
racionālākajiem veidiem kā paātrināt darbu, ja pieslēgums pie datu bāzes
servera izveidots izmantojot modemu, ir vienkārši samazināt datu plūsmu, kas
tiek pārsūtīta pa modemu. Visvienkāršākais veids kā to samazināt, ir piedāvāt
lietotājam ievadīt nepieciešamo datu masku, tādējādi izveidojot atlasāmo datu
masku, kas nosaka kādi raksti tiks rādīti lietotājam. Lietotājam jau pirmajā
pieprasījuma rezultātos būs viņam nepieciešamie dati. Tas neprasīs no
lietotājiem aplūkot daudz rakstus, lai atrastu nepieciešamo. Maskas lietošana
pazemina Oracle servera atbildi uz pieprasījumu, it sevišķi, ja maskas
nosacījumos ir lauki, kas nav iekļauti nevienā no indeksiem, taču salīdzinājumā
ar laiku, kas patērēts datu pārsūtīšanai ar modemu, to var pielīdzināt tuvu
nullei. Izveidot maskas nosacījumu ir ļoti vienkārši, ir jāievēro tikai SQL
pieprasījumu sintakse. Pēc tam šo maskas nosacījumu, izmantojot formas funkciju
Set_Block_Property, uzstāda blokam un
izpilda datu pieprasījumu. Tas izskatās apmēram šādi [4]:
Set_Block_Property(‘Block_name’, DEFAULT_WHERE,
mask);
Go_Block(‘Block_name’);
Execute_Query;
Ļoti daudzās datu
ievades formās vienlaicīgi kopā ar galvenās tabulas rakstiem tiek rādīti arī
tai pakārtoto tabulu raksti (Master-Detail
tables), kas tiek parādīti automātiski. Tas nozīmē, lietotājam
pārvietojoties pa galvenās tabulas rakstiem automātiski tiek rādīti pakārtotās
vai pakārtoto tabulu raksti. Ja pieslēgums serverim ir organizēts, izmantojot
modemu, tas nozīmē, ka katra pārvietošanās pa galvenās tabulas rakstiem veic
jaunu datu pieprasījumu no datu bāzes un sagaida atbildi. Reāli katra šāda
pārvietošanās lietotājam “maksā” kā minimums 1-2 sekundes. Strādājot datortīklā
to prakstiski nejūt, jo tas notiek dažās sekundes daļās. Izvairīties no šādiem
liekiem datu pieprasījumiem var komentējot galvenās formas trigerī
ON-POPULATE-DETAILS Oracle forms automātiski ģenerēto izejas teksta rindu Query_Master_Details(rel_id,
block_name), kas parāda pakārtotās tabulas rakstus. Bez tam formā vēl
izveido vienu spiedpogu, kuras nospiešanas gadījumā izpilda sekojošu tekstu:
Go_Block(‘Block_name’);
Execute_Query;
Tas ir tas pats
izejas teksts, kas tiek izpildīts jau augstāk minētajā rindā, kas tika
komentēta. Tagad pakārtoto tabulu dati tiek rādīti tikai, kad tie nepieciešami
lietotājam un arī pārvietošanās pa galvenās tabulas rakstiem izpildās krietni
ātrāk.
Tā kā šādas datu
ievadformas var tikt izmantotas, gan strādājot datortīklā, gan veicot datu
ievadi attālināti, izmantojot modema pieslēgumu serverim, vislabāk šīs
darbības, pakārtoto rakstu rādīšanai vai nerādīšanai, papildināt tā, lai tas
strādātu atkarībā no kāda sistēmas parametra. Tādējādi gan vieni, gan otri lietotāji varētu
maksimāli efektīvi strādāt.
1.3.2. Fetched Records atribūts formas blokiem
Iesākumā tiks
aplūkota datu ievadforma, kurā jau paredzēta rādāmo datu atlasīšana pēc datu
maskas, tādējādi samazinot no servera pieprasāmo datu apjomu. Taču kā jau tika minēts
1.1. nodaļā formas atribūts Records
Fetched iespaido formas ātrdarbību, norādot cik rakstus forma saņems no
datu bāzes servera uzreiz. Pēc noklusēšanas šī atribūta vērtība vienāda ar
blokā rādāmo ierakstu skaitu, taču tā var būt arī lielāka. Records Fetched atribūts kā zināms nosaka, cik ierakstus forma
atlasīs uzreiz vienā pieprasījumā. Jo vairāk ierakstu, jo vairāk datu tiks
atlasīti. Taču ja esošie datu pieprasījumi bieži vien atgriež daudz ierakstu,
ir izdevīgāk uzreiz atlasīt vairāk ierakstu, kas dod lietotājam iespēju viegli
tos pārskatīt, jo pretējā gadījumā katru reizi, kad lietotājs gribēs redzēt
nākamos ierakstus, kas vēl nav redzami formā, tiks atkal izpildīts datu
pieprasījums nākamajiem ierakstiem un lietotājs gaidīs servera atbildi.
![]() |
Nākamajā attēlā aplūkojami mēģinājumu rezultāti, aplūkojot sistēmas SIS Tieto Konts ISSUING karšu kontu meklēšanas formu. Pirmajā kolonnu grupā redzams datu apjoms, kas tiek nosūtīts un saņemts, ja formā pieprasa tikai 10 rakstus (tik cik vienlaicīgi var redzēt), bet otrajā, ja pieprasa 100 rakstus (10 reizes pa 10). Acīmredzami, ka pieprasot 10 ierakstus datu plūsma ir mazāka, taču jāņem vērā, ka gadījumā ja lietotājs sāks aplūkot nākamos ierakstus, tie tik un tā tiks pieprasīti no datu bāzes servera, kas nozīmēs izejošās datu plūsmas palielināšanos un lietotāja gaidīšanu uz atbildi (2 kolonna). Tas palielina arī kopējo datu plūsmu automātiski, jo ir jāpieprasa jauni dati. Lielākais datu apjoms, manuprāt, tiek nosūtīts pirmajā reizē, kad tiek atvērts un pārbaudīts datu kursors, jo nākamie datu pieprasījumi kopā nedod 10-kārtīgu apjomu. Nākamās komandas satur noteikti tikai komandu - atlasīt nākamos desmit rakstus (fetchs next 10). Izejošo datu plūsma paliek nemainīga pieprasot arī uzreiz 100 rakstus un arī saņemto datu apjoms ir aptuveni tāds pats kā pieprasot 10x10 ierakstus (3 kolonna).
1.9. attēls. Datu apmaiņas apjomi, mainoties pieprasāmo rindu skaitam.
Lai izvairītos no liekiem datu
pieprasījumiem ir reāli jāizprot lietotāja vajadzības un aptuvenais darba
stils, lai noteiktu cik ierakstus parādīt uzreiz un cik ierakstus atlasīt
uzreiz. Kā zināms parasti lietotājs meklējot kādus datus pārskata daudzus
ierakstus, tas nozīmē ka vienā reizē vajadzētu atlasīt 2-4 vairāk ierakstu,
nekā lietotājs redz uzreiz, tādējādi ietaupot lietotāja laiku un datu plūsmu,
kas tiks nosūtīta un saņemta pa modemu. Atlasāmajiem ierakstiem nevajadzētu būt
arī bezgalīgi daudz, jo tad lietotājs ilgi gaidīs kamēr dati tiks saņemti, bet
izmantos viņš varbūt tikai pirmos ierakstus. Ļoti nozīmīgi datu meklēšanas
formās lietotājam piedāvāt izvēlēties datu sakārtojumu kādā saņemt datus, jo
tas var samazināt atlasāmo ierakstu skaitu – lietotājs ātrāk atrod viņam
nepieciešamos datus. Tas protams samazina servera atbildes laiku, bet salīdzinājumā
ar patērēto, saņemot liekus rakstus, ir pielīdzināms nullei.
1.3.3. Auto Refresh atribūts LOV objektiem
![]() |
Kā jau tika minēts 1.1. apakšnodaļā liela nozīme izstrādājot formas ir kādus izvēlēties datu ievades objektus un kādas uzstādīt šo objektu atribūtu vērtības. Manuprāt galvenokārt šeit jāpiemin datu sarakstu (List of Values) un sarakstu (List Item) objekti. Kā zināms List item objektu vērtības tiek aktualizētas tikai startējot formu, bet vērtību saraksta (LOV) vērtības atkarībā no atribūta Auto Refresh vērtības var tikt aktualizētas katru reizi izsaucot šo objektu (formu noklusētā vērtība) vai tikai vienu reizi. Ja tā ir bieži lietojama datu ievades forma un nepieciešamie datu klasifikatori, kas tiek izmantoti datu ievadam, mainās tikai vienu reizi nedēļā vai vēl retāk nav ieteicams šo objektu atribūtu Auto Refresh uzstādīt kā True, bet gan False. Tas nozīmē vērtību saraksta vērtības tiek nolasītas tikai vienu reizi – startējot formas. Nākamajā 1.10. attēlā redzama, cik liela ir datu plūsma aktualizējot vērtību sarakstus, ja tie tiek izsaukti 10 reizes. t.i. tika veikta 10 ierakstu ievade datu ievades formā kurā ir 2 lauki ar piesaistītiem vērtību sarakstiem. Pirmajā kolonnā redzama datu plūsma, ja vērtību saraksta vērtības tiek aktualizētas katru reizi, otrajā, ja tikai pirmo. Šie vērtību saraksti atgriež valūtu un valstu kodu tabulu datus attiecīgi.
1.10. attēls. Datu plūsma formās ar vērtību sarakstu objektiem,
atkarībā no to Auto Refresh atribūta vērtības.
Kā jau redzams
attēlā, veicot šo 10 ierakstu ievadi, ja
Auto Refresh atribūta vērtība ir True, datu plūsma ir vismaz 7 reizes
lielāka. Jāatzīmē ka šājā gadījumā, tas nenozīmē tikai 7 reizes lēnāku darbību,
jo lietotājam pēc katra datu pieprasījuma ir jāgaida arī servera atbilde.
Pirmajā variantā katru reizi lietotājam jāgaida vismaz 2-3 sekundes, kamēr tiks
atjaunoti dati, bet otrajā tie jāgaida tikai pirmajā reizē. Pārējos gadījumos
vērtību saraksts tiek parādīts uzreiz. Tātad -
ja klasifikatoru dati mainās ļoti reti ir daudz izdevīgāk šī atribūta
noklusēto vērtību nomainīt uz pretējo, tādējādi samazinot gan datu plūsmas
apjomu, gan arī laiku, kas lietotājam jāpavada, gaidot klasifikatora datus, kas
iespējams nemaz nav mainījušies.
1.3.4. Ne-tabulas lauku vērtību aktualizēšana
Kā jau zināms, viena
no datu bāžu normālformām prasa, lai dati datu tabulās neatkārtojas. Tas
parasti arī tiek ņemts vērā veidojot datu bāzes, ieviešot virkni klasifikatoru,
taču, ja jāveic datu parādīšana lietotājam, tie parasti vēlas pilnu
informāciju, nevis tikai klasifikatoru kodus. Tādiem nolūkiem visbiežāk formās
datu tabulu blokos tiek izveidoti ne-tabulas objekti, kuros, izmantojot
POST-QUERY trigeri, kas izpildās katrai no datu tabulas atlasītai rindai, tiek
sameklēts attiecīgais ieraksts no tabulas, kas apraksta klasifikatoru (Sīkāk
par to jau tika runāts 1.1.3. nodaļā). Kā jau tika minēts, rakstot
klasifikatoru koda parādīšanu trigeros, tie izpildās katrai tabulas rindai. Tas
nozīmē, ja no tabulas tiks parādīti 100 ieraksti, tad 100 reizes tiks izsaukts
datu pieprasījums, kam jāatgriež viena rinda no klasifikatoru tabulas ar
klasifikatora koda aprakstu. Strādājot datortīklā tas nav manāms, taču, ja
darbs noris attālināti, izmantojot modema pieslēgumu, tad katrs šāds izsaukums
kavē datu parādīšanu uz ekrāna.
Kā jau tika minēts 1.1.3 nodaļā, ļoti effektīvi ir šādus datu pieprasījumus
formās aizstāt ar List Item
objektiem, kam dati nolasīti no datu tabulas tikai vienu reizi. Šo datu apjoms
varbūt ir lielāks nekā n-tās reizes pieprasot pa vienai rindai, taču jāņem vērā
arī laika faktors. Veicot n-tos datu pieprasījums tiek patērēts laiks pārsūtot
datu pieprasījumu pa modemu un saņemot atpakaļ rezultātu. Nākamajā 1.11. attēlā
ir parādīts, kāds ir datu plūsmas apjoms, kopš formas atvēršanas, ja formā daži
datu lauku paskaidrojošie tekti tiek atlasīti no datu tabulas, parādot
paskaidrojošo tekstu, kā arī, ja tie ir atlasīti tikai vienreiz un formas veic
tikai attiecīgā raksta parādīšanu List
Item objektā.
![]() |
1.11. attēls. Datu plūsma, ja klasifikatoru paskaidrojums tiek pieprasīts no datu tabulas vai tā parādīšanai tiek izmantots List Item objekts.
Attēlā redzama klientu meklēšanas
formas datu plūsma apskatot 50 ierakstus. Pirmajā kolonnu grupā kā redzams datu
plūsma ir vismaz 3 reizes lielāka, kas radusies izpildot datu pieprasījumu pēc
klasifikatoru paskaidrojošiem tekstiem. (Formā ir 3 lauki – klasifikatori,
kuriem tiek atlasītas paskaidrojošās vērtības). Tā izpildās katrai atlasītai
rindai tādējādi papildus radot, gan izejošo, gan ienākošo datu plūsmu. Kā
redzams attēlā otrās kolonnu grupas, kas attēlo datu plūsmu, ja izmantoti List Item objekti, kopējā datu plūsma
pat ir mazāk nekā pirmās izejošo datu plūsma. Arī pati datu atlasīšana otrajā
gadījumā ir vismaz reizes 3 ātrāka. Tātad, ja datu apskates forma arī tiek
izmantota vidē, kad pieslēgumam serverim tiek izmantots modems, ļoti iesakāms
šādus klasifikatoru paskaidrojošo tekstu laukus veidot nevis kā parastu teksta
objektus, bet gan kā List Item
objektus, kas ļaus lietotājam strādāt ar formu daudz ātrāk un efektīvāk.
1.3.5. Update Changed Columns atribūts formas blokiem
Formās
datu blokiem eksistē tāds atribūts kā Update
Changed Columns, kas nozīmē, ka veicot datu kolonnu labošanu, komandas
izpildīšanai tiek sūtīti tikai mainītie lauki. Ja blokā ir daži lauki ar lielu
datu apjomu, tas nozīmē, ka tiks ietaupīts datu apjoms, kas tiek pārsūtīts.
Taču jāatceras, ka šādā gadījumā formām katru reizi jāveido sava unikāla datu
labošanas komanda, kura pirms izpildes jaanalizē (reparse). Ja datu
tabulas lauki nav gari un netiek izmantoti long
tipa mainīgie, kā arī modemu savienojuma ātrums ir pietiekoši ātrs, ieteicams
šo parametru uzstādīt kā False, kas
nozīmē sūtīt visu kolonnu datus. Savukārt, ja datu lauki ir lieli un modema
sakari lēni, šādas datu labojumu komandas tiks ātrāk pārsūtītas, sūtot tikai
mainīto kolonnu datus, jo laiks kas tiek patērēts komandas analizēšanai ir
krietni mazāks. Nākamajā 1.12. attēlā
![]() |
tiek parādīts kā izmainās datu plūsma, mainot šī atribūta vērtību.
1.12. attēls. Datu plūsma formā, kad UPDATE komandā ir visi lauki un
kad tikai mainītie lauki.
Kā redzams attēlā
otrajā gadījumā, kad tiek laboti tikai mainītie datu lauki, izejošā datu plūsma
ir prakstiski uz pusi mazāka. Un tas viss tikai labojot 10 ierakstus. Šī
starpība būtu vēl lielāka, ja datu tabulā būtu kādi liela izmēra lauki,
piemēram long tipa mainīgie. Ja
jārunā par operācijas izpildes ātrumu, tad vismaz šajā vidē, kad pielēgumam pie
datu bāzes servera, tiek izmantots modems, šī datu labošanas operācija
izpildījās otrajā gadījumā ātrāk nekā pirmajā. Tas varētu būt izskaidrojams ar
to ka pirmajā gadījuma līdz serverim jāpārsūta lielāks datu apjoms. Savukārt
otrajā datu plūsma ir mazāka, bet laiks kas nepieciešams komandas
pāranalizēšanai ir vēl mazāks nekā, kas nepieciešams, lai pārsūtītu vēl tik pat
datu. Protams, strādājot ātros datortīklos šī atribūta vērtību maiņa var nedot
kādu ievērojami rezultātu.
1.3.6. Datnes ielasīšana
Beigās vēl gribētos
aplūkot datnes ielasīšanu, izmantojot modema pieslēgumu serverim. Iepriekšējā 1.2.
nodaļā jau tika apskatīta
datnes ielasīšanas optimizācija. Reālā sistēmas ekspluatācijā tāpat var
gadīties, ka lietotājam nepieciešams ielasīt datu bāzes serverī datus no datnes
ar zināmu struktūru, kas, piemēram, eksportēta no kādas citas sistēmas. Kā jau
atklājām, iepriekšējās nodaļās, visefektīvāk datnes ielasīšanu var veikt, ja
visas nepieciešamās darbības, kas nepieciešamas datnes datu ierakstīšanai, tiek
veiktas uz Oracle datu bāzes servera un formas nodarbojas tikai ar datnes nolasīšanu un servera pakotņu
funkciju izsaukumiem. Tika arī pierādīts, ka datu manipulāciju operācijas lēnāk
izpildās tās veicot formas programmvienībās. Uz neliela piemēra bāzes atkal
tiks aplūkota datnes ielasīšana no formām, ja visas darbības notiek formās un
ja daļa no tām servera pakotnēs. Mēģinājumam atkal tiek izmantota tā pati VISA
CTF datņu ielasīšanas forma, kas tika izmantota iepriekš. Šoreiz tiek ielasīta
tikai viena datne ar 3300 rindām. (Jo lielāks datnes apjoms, jo reālāku
priekštatu iepējams iegūt par mēģinājuma rezultātu). Strādājot datortīklā šīs
datnes ielasīšana uz šī testa datu bāzes servera prasīja aptuveni 5m30s laika
(Vidēji 0.1 sekunde uz datnes rakstu, kas ir aptuveni 2x lēnāk nekā
mēģinājumos, kas tika veikti iepriekš. Tas izskaidrojams ar lēna datu bāzes
servera izmantošanu tieši šiem nolūkiem). Nākamājā 1.13. attēlā redzama šīs
pašas datnes ielasīšana, ja pieslēgums datu bāzes serverim ir veidots,
izmantojot iepriekšminēto modema pieslēgumu. Pa labi redzama datnes ielasīšana,
ja visas darbības tiek veiktas formās, vidū – ja forma veic tikai datnes
operācijas un pa kreisi – ja viena izsaukuma laikā servera pakotnei tiek
nodotas uzreiz 10 datnes rindas. Patērētais laiks pirmajam variantam ir – 2h46m
(!!!), otrajam 1h31m, bet trešajam – 30m. (Gan klienta darba vieta, gan datu
bāzes serveris noslogots tikai ar šo uzdevumu) Protams, ka reālajā dzīvē
neviens neatļausies tik maza apjoma failu ielasīt, izmantojot šādu attālinātu
pieslēgumu, taču šis mēģinājums parāda cik reāli ātri tiek veiktas šādas operācijas
modema pieslēguma gadījumā. Pirmajā variantā tas ir – aptuveni viens raksts 3
sekundēs, otrajā – viens raksts 1,7 sekundēs, bet trešajā – 0,6 sekundēs. Ņemot
vērā iepriekš minēto par lēna datu bāzes servera izmantošanu, optimistiski
varam cerēt, ka pie normāliem darba apstākļeim, tas varētu būt iespējams 2x
ātrāk. Taču šie rezultāti nebija mēģinājuma mērķis. Mūs interesēja datu plūsmas
apjoms šāda pieslēguma gadījumā. Lai cik tas arī neliktos savādi, šīs nelielās
datnes (600 kb) ielasīšanai datu bāzē bija nepieciešams 7,22Mb liela ienākošā
un 5,37Mb liela izejošo datu plūsma pirmajā variantā. Mazliet mazāk
informācijas bija otrajā, bet vismazāk trešajā variantā, kad tiek izmantota 10
rindu nodošana servera pakotnes funkcijai.
Atliek tikai vienīgi minēt, kas tiek nosūtīts šajos datos, izmantojot
SQL*Net protokolu. Vēl viens liels jautājums ir kāpēc ienākošā datu plūsma,
skatoties no klienta darba vietas puses, ir lielāka nekā izejošā. Jautājums
rodas tāpēc, ka izsaucot pakotnes funkciju tai tiek nodota datu virkne, bet
atpakaļ saņemts tikai operācijas rezultāts – patiess vai nepatiess. Kas vēl bez
šīs informācijas tiek pārsūtīts noteikti atbildēt var tikai Oracle Forms 4.5 izstrādātāji, bet to uzzināt
pagaidām nav bijis iespējams.
![]() |
1.13. attēls. Datnes ielasīšana (pieslēgums datu bāzes serverim, izmantojot modemu).
Tātad kā varam nojaust viens no “bremzējošiem” faktoriem ir tieši
lielā datu plūsma no klienta darba vietas uz serveri un atpakaļ. Kas tiek
pārsūtīts, izmantojot SQL*Net protokolu mēs nezinām, taču cik var noprast no
mēģinājumu rezultātiem, pārāk optimizēta, vismaz šādā veida darbībām, formas
nav. Redzot attēlā parādītos rezultātus varam skaidri pateikt, ka strādājot arī
datortīklā šī lielā datu plūsma ir viens no lielākajiem “bremzējošiem”
faktoriem.
2. Lietotāja-datora interfeisa uzlabošana
2.1. Grafiskā lietotāja-datora interfeisa pamatprincipi
Labu
grafisko lietotāja-datora interfeisu raksturo faktors, cik viegli lietotājs to
apgūst un cik viegli to ir lietot. Runājot par lietošanu, vienmēr būs
domstarpības, jo katrs cilvēks ir individualitāte un katram patīk kaut kas
cits, kas nepatīk citiem. Labu lietotāja-datora interfeisu definē 3
pamatprincipi [10]:
1)
Vienkāršība (Simplicity)
- jo vienkāršāks ir sistēmas interfeiss, jo vieglāk lietotājs var iemācītes
lietot sistēmu;
2)
konsekvence, saskaņa (Consistency) - konsekvence raksturo sistēmas izmaiņas, cik viegli
lietotājs varēs apgūt sistēmas jaunās komponentes. Lietotājs parasti vēlas, lai
sistēmas jaunā komponente darbotos tāpat kā vecā, lai pārāk daudz laika nebūtu
japavada apgūstot jaunās sistēmas interfeisa īpatnības;
3)
efektivitāte (Efficiency)
- jo mazāk soļu jāveic lietotājam, lai izpildītu kādu operāciju, jo lielāka ir
sistēmas efektivitāte šo operāciju izpildei. Lai izveidotu efektīvu
lietotāja-datora interfeisu izstrādātājam ir jāzin, kuras ir visbiežāk lietotās
operācijas un kā tās tiks kombinētas.
Lietotāja-datora interfeiss neraksturo cik krāšņs un elementu bagāts būs
datu ievades logs, bet gan izstrādātāja profesionālismu un radošo potenciālu.
Pirmo divu pamatprincipu izveide prasa izstrādes grupai izveidot interfeisa
standartus. Bez šādiem standartiem sistēmu interfeisa izstrāde būs haotiska
(katra izstrādātāja stilam atbilstoša) un lietotājam grūti apgūstama. Trešā
pamatprincipa izveide ir pati grūtākā. Tas ir atkarīgs no sistēmas biznesa
modeļa. Tas jāveido sadarbībā ar lietotāju, jo sistēma tiek veidota, lai viņam
palīdzētu.
Sīkāk par lietotāja-datora interfeisa uzlabošanu pēc šiem pamatprincipiem
aprakstīts nākošajās trīs nodaļās.
2.2. Šablonformu izmantošana formu ģenerācijai
Kā jau tika minēts, lai nodrošinātu vienota lietotāja-datora interfeisa
izveidi, atbilstoši izstrādājamā projekta vajadzībām, lietojot Oracle formu
ģeneratoru (Oracle Forms Generator), tiek lietotas
šablonformas (templates), kurās tiek
aprakstīti visi kontroles bloki, rīku joslas, vizuālie objekti, to īpašības.
Lai varētu izveidot šādu šablonformu ir jāsaprot, kā savā starpā saistās
objekti šablonformā ar objektiem izstrādājamajā formā.
Designer/2000 lieto šablonformas, kurās ir visa
nepieciešamā informācija ģenerētai formai - vizuālie atribūti, rīku josla,
kontroles bloki un vienības, kas tiks
ievietotas jebkurā ģenerētajā formā. Taču, ievietojot šablonformās daudz
izpildāmo bloku, rodas problēmas, jo šie programmu kodi tiek ierakstīti visās
sistēmas ģenerētajās formās. Ja kādas izmaiņas tiek izdarītas šablonformās, tad
jāveic viens no sekojošiem uzdevumiem:
1) Jāpārģenerē visas iepriekš ģenerētās formas;
2) izmaiņas jāveic ar roku katrā noģenerētajā formā.
Lai izvairītos no šadām problēmām, tiek ieteikts pēc iespējas vairāk
lietot atsauksmju formas (Reference form)
un bibliotēkas (Libraries)
šablonformu izstrādē [9]. Ja šablonformās vizuālie atribūti un datu vienības
tiek veidotas kā atsauksmes uz citā formā aprakstītiem objektiem, un PL/SQL
procedūras, paketes un funkcijas tiek saistītas ar bibliotēkām(tiek apkopotas
bibliotēkās), tad ģenerētā forma pārmantos šīs atsauksmes un saistības. Tas atvieglos sistēmas izstrādi, kad vajadzēs
labot vai papildināt šablonformu kodu, jo nebūs jāpārģenerē visas iepriekš
veidotās formas.

2.1. attēls. Šablonformu, bibliotēku,
atsauksmju formu un noģenerēto formu saistība.
Piemēram, ja visa rīku josla (kanva (canvas),
kontroles bloks un vienības) ir veidota kā atsauksme uz atsauksmju formu, tad
papildus pogas var tikt pieliktas rīku joslai arī vēlāk, pēc formu ģenerācijas,
nepārģenerējot šīs formas no jauna. Šīs papildus pogas tikai jāpievieno
atsauksmu formai un jāpārraksta PL/SQL kods bibliotēkā, lai jaunā poga
strādātu. Tālāk pārkompilējot visas ģenerētās formas, jaunā poga tiek iekļauta
ģenerētajā formā.
Atsauksmju formā būtu
jāiekļauj sekojoši objekti:
1)
Visu lietoto kanvu informācija;
2)
visi vizuālie atribūti;
3)
visi kontroles bloki;
4)
rīku joslas kanva un bloks (ieskaitot visas pogas, uz
kurām atsauksme tiek veidota automātiski).
Sakarā ar to, ka uz formas līmeņa
trigeriem nevar veidot atsauksmes tieši (jo Designer/2000
formu ģenerators pats pārraksta trigerus), visi PL/SQL kodi būtu jāievieto
bibliotēkā, kas saistīta ar šablonformu [4]. Tāpēc formas līmeņa trigeriem
vajadzētu izsaukt procedūras no bibliotēkas. Bez tam gadījumā, ja jāmaina kāda
formas līmeņa trigera kods, to nākas izdarīt tikai vienā vietā - bibliotēkā,
kurā aprakstīts trigera kods. Piemēram, ja šablonformā ir
WHEN-NEW-FORM-INSTANCE trigeris, tam vajadzētu izskatīties šādi:
/*
WHEN-NEW-FORM-INSTANCE */
BEGIN
WHEN_NEW_FORM_INSTANCE;
END;
Kur WHEN_NEW_FORM_INSTANCE ir procedūra no bibliotēkas. Ja ģenerators pārrakstīs kāda trigera kodu,
tad jauno funkciju izsaukums tiks ierakstīts aiz šī koda, nebojājot
izstrādātāja rakstīto kodu.
Šeit jāpiemin, ka
veidojot atsauksmi uz objektu no citas formas, šo divu formu koordinātu
sistēmas nesakrīt Oracle Forms Designer
4.5 neveic automātisku koordi-nātu maiņu. Par to jārūpējas izstrādātājam
pašam.
Lai visās formās panāktu vienādu lietotāja-datora interfeisu, visiem tās
objektiem jābūt vienādiem, t.i. vienādiem vizuāliem atribūtiem (fonts, fonta izmērs,
krāsas, garums, platums u.t.t). Visvieglāk to var panākt veidojot vizuālos
atribūtus (Visual attributes) un
īpašību klases (Property classes)
atsauksmju formā. Vizuālie atribūti ir fonts un tā īpašības (fonta vārds,
izmērs, stils, platums, garums), kā arī objekta krāsas (priekšplāns, fons,
aizkrāsošanas modelis). Piesaistot visiem vienāda tipa objektiem konkrētu
vizuālo atribūtu, ir atvieglota šī tipa objektu vizuālās informācijas maiņa. Tā
jādara tikai vienā vietā - tur kur tiek definēts vizuālais atribūts.
Katram objektam formās tiek piesaistīts vai nu noklusētais vizuālais
atribūts (default), kas ir atkarīgs
no attiecīgās platformas, kurā tiek ekspluatēta forma, vai arī definētais
vizuālais atribūts (named). Ja
objekta vizuālās īpašības tiek mainītas ar roku, tas iegūst lietotāja vizuālā
atribūta (custom) statusu, kas
nozīmē, ka lai izmainītu šāda objekta vizuālos atribūtus, tie jāmaina, katram
konkrētam objektam, jo tie nav saistīti savā starpā ar kādu no definētiem
atribūtiem.
Vizuālā atribūta vārds nosaka objektu, kuram tas tiks pievienots
ģenerācijas procesa laikā. Piemēram, ikvienam teksta objektam tiek piešķirts
CG$ITEM vizuālā atribūta vārds, ja šis atribūts ir definēts šablonformā.
Eksistē liels skaits šādu speciālo vizuālo atribūtu vārdu, kurus aprakstot var
viegli veidot ģenerētās formas izskatu. Piemēram, CG$PUSH_BUTTON vizuālais
atribūts nosaka jebkuras ģenerētās spiedpogas izskatu, CG$MANDATORY_ITEM -
obligātā ievadlauka vizuālos atribūtus utt. Visus šos vizuālo atribūtu vārdus
var atrast Oracle palīdzības failā C:\ORAWIN95\DES2_60\HLP\CGEN45.hlp.
Savukārt īpašību klases ir spēcīgs līdzeklis, kas atļauj veidot vienotu
lietotāja-datora interfeisu un funkcionalitātes standartus. Īpašību klase ir
objekts, kas satur īpašību kopu, kas var tikt veidota pēc izstrādātāja vēlmes,
un to vērtībām. Piemēram, var veidot
atsevišķas īpašību klases ievadāmiem neobligātiem ievadlaukiem,
ievadāmiem obligātiem ievadlaukiem un informācijas laukiem, spiedpogām, izvēles
sarakstiem (LOV) utt.

2.2. attēls. Īpašību klašu un vizuālo atribūtu
definēšana šablonformā.
Šādu īpašības klašu skaits nav ierobežots un vienas klases īpašības var
tikt piešķirtas dažādu tipu objektiem. Tas, pamatojoties uz iepriekš minēto,
dod iespēju mainīt šo objektu definīcijas tikai vienā vietā, tādējādi mainot to
visā izstrādājamajā lietojumprogrammā veicot tikai vienu operāciju - formu
pārkompilāciju. Visi vizuālie atribūti un īpašību klases, kas aprakstīti
šablonformā, tiek iekļauti ģenerētajā formā, neatkarīgi no tā vai eksistē objekts,
kas izmanto šo atribūtu vai īpašību klasi, vai nē. Tas dod iespēju jebkurā
izstrādes procesa laikā veidot jaunus interfeisa objektus, tos aprakstot ar
esošiem vizuāliem atribūtiem vai īpašību klasēm.
Ja darba laikā tiek izveidots jauns vizuālais objekts vai īpašību klase,
tā jāpiesaista šablonformai, lai tā tiktu ieģenerēta visās jaunajās formās. Lai
šie jaunie atribūti būtu arī jau ģenerētajās formās ir jāveido atsauce uz tiem
no katras formas atsevišķi. Taču arī to var automatizēt, veidojot objektu
grupas (Object groups), kurās
pievieno jaunos vizuālos atribūtus. Tālāk veido atsauces jau uz objektu grupām.
Lai vieglāk būtu apkopot objektus, uz kuriem tiks veidotas atsauksmes,
Oracle formās pastāv jēdziens objektu grupas (Object groups). Tas dod iespēju vienkopus apkopot vairāku tipu
objektus (logus, blokus, kanvas, vizuālos attibūtus), kas paredzami kā
atsauksmju objektu avots.

2.3. attēls. Objektu grupas.
Reāli, veidojot objektu grupas, jauni objekti netiek veidoti, tiek veidota
tikai atsauce uz šiem objektiem formas ietvaros. Veidojot objektu grupas
jāievēro :
1)
Ievietojot objektu grupā bloku, automātiski tiek
ievietoti arī visi tā objekti (vienības, trigeri, relācijas), kaut arī tie
objektu grupas kokā netiek rādīti;
2)
programmu vienības (procedūras, funkcijas) nevar tikt
iekļautas objektu grupās;
3)
bloku objekti, vieni paši nevar tikt iekļauti objektu
grupā, jo tie nevar pastāvēt neatkarīgi bez bloka;
4)
objektu grupas objektiem jābūt definētiem tajā pašā
formā, tie nevar būt no citas formas;
5)
objektu grupa nevar saturēt objektu grupu;
6)
dzēšot objektu, tas automātiski tiek dzēsts no objektu
grupas;
7)
dzēšot objektu grupu, no formas moduļa netiek dzēsti
paši objekti.
Tālāk aplūkosim kā apvienot programmu
kodu, kas nepieciešams vairākās formās. Procedūras un funkcijas, kas tiek
lietotas vairākkārt no dažādām formām ieteicams apvienot vienā vietā -
bibliotēkās. Savukārt procedūras un funkcijas, kuru izsaukšana neprasa vizuālās
informācijas parādīšanu, ietiecams izvietot datu bāzē (Stored procedures), tādējādi samazinot formas izmērus. Lai arī
pārējās lietojumprogrammas (application)
formās būtu pieejamas šīs procedūras atliek tikai piesaistīt attiecīgo
bibliotēku.

2.4. attēls. Piesaistītās bibliotēkas.
Lai
visas vajadzīgās bibliotēkas automātiski tiktu piesaistītas jebkurai ģenerētai
formai, šīs bibliotēkas tikai jāpiesaista konkrētai šablonformai, kas tiek
izmantota ģenerācijas procesā. Jebkuras izmaiņas, kas tiek veiktas bibliotēkas
procedurās vai funkcijās formās ir pieejamas uzreiz pēc to atvēršanas un
pārkompilēšanas.
Ja jāpievieno jauna bibliotēka, tā
pirmkārt jāpievieno šablonformai, lai tā tiktu pievienota visām jaunajām
formām. Formai drīkst pievienot neierobežotu skaitu bibliotēkas, pie kam tas
nepalielina formas izmērus, jo bibliotēkas tiek glabātas atsevišķos *.pll
failos, un netiek iekompilētas programmas kodā. Visām jau ģenerētajām formām
bibliotēkas jāpiesaista ar roku, jo nav iespējams bibliotēku aprakstīt objektu
grupās, kā tika minēts iepriekš. Bez tam pastāv iespēja piesaistīt bibliotēku
bibliotēkai, ko varētu izmantot kā risinājumu. Piemēram, kādai no galvenajām
bibliotēkām, kas ir visās formās piesaistam klāt jauno bibliotēku, kas pēc
formu pārkompilēšanas būs visās formās.
Vislielākās problēmas veidojot šablonformas tomēr ir un paliek
dokumentācijas trūkums. Oracle nenodrošina ar labu dokumentāciju (principā tās
nav vispār) šablonformu veidošanai, ja neskaita dažus piemērus, kas doti Oracle
palīdzībā (Help).
2.3. Preferences kā ģeneratora parametri
Ne visu var aprakstīt šablonformās. Izrādās, ka objektu, kas nav iekļauti
kontrolblokos, un citu īpašības un reakcija uz lietotāja darbību, kā arī visi
pārējie ģeneratora parametri, tiek aprakstītas ar preferencēm (preference), izmantojot preferenču
pārlūkprogramu (preference navigator).
Parasti tie ir datu bloki, kas tiek iekļauti formās no moduļa datu diagrammas,
logi, ritjosla (scrollbar) un citi
objekti.
Preferences ir parametri, kas kontrolē ģenerētās formas izskatu un
uzvedību [1]. Preference var būt vai nu obligāta vai neobligāta. Obligātai
preferencei vienmēr jābūt uzdotai vērtībai. Katrai preferencei eksistē
noklusētā vērtība, kas tiek izmantota gadījumos, ja dotās preferences vērtība
nav definēta.
Preferenču pārlūkprogramma ir grafisks rīks, kas atļauj mainīt preferenču
vērtības, kuras izmanto ģeneratori ģenerācijas procesā, kas nosaka ģenerētās
formas izskatu un uzvedību. Preferences var tikt piesaistītas pie konkrēta
objekta (domeins, forma, modulis, lietojumprogrammas sistēma) sistēmā.

2.5. attēls. Preferenču vērtību ievadīšana lietojot
preferenču pārlūkprogrammu.
Ģenerācijas procesa laikā ģenerātors pārbauda, kuras preferences, kas
iespaido ģenerēto lietojumprogrammu (application),
ja vispār kāda ir uzstādīta. Ja vajadzīgā preference nav uzstādīta, ģenerātors
lieto noklusēto.
Katra preferences vērtība var būt mantota (iedzimta), vai uzstādīta tikai
konkrētam lietojumprogrammas līmenim. Preferenču pārlūkprogramma nosaka šo
preferences īpašību, to apzīmējot ar dažādām ikonām preferenču kokā, vai
dažādām krāsām kopējā preferenču izvēlnē. Šī iespēja ļauj viegli kontrolēt,
piemēram, konkrēta datu bloka vai moduļa uzvedību, vai tas būs tāds pats kā
pārējos moduļos vai atsevišķs, konkrēts tikai šim modelim.
Kad tiek ģenerētas formas,
attiecīgajam ģeneratoram ir jāzin, kuras preferenču vērtības ir uzstādītas.
Ģenerācijas procesa laikā ģenerators pārlūko visu preferenču hierarhiju katrai
preferencei, kas nepieciešama ģenerācijas procesā. Meklēšana notiek no zemākā
lietojumprogrammas (application)
līmeņa virzienā uz augstāko.
1. tabulā doti, pēc autora domām, svarīgāko preferenču (preference) apkopojums, kas nosaka
ģenerētās formas izskatu un reakciju uz lietotāja darbību.
1. tabula. Svarīgākie
formu ģeneratora parametri.
Kategorija
|
Parametra
nosaukums
|
Apraksts
|
Iespējamās vērtības
|
END USER LEVEL
|
AUTOHP
|
Vai parādīt HINT lauka
vērtību, kad lietotājs aktivizē ievadlauku
|
Y, N
|
|
DELWRN
|
Vai brīdināt lietotāju, ka dzēšot rakstu tiek dzēsti arī raksti no citām
tabulām (formas ietvaros)
|
Y, N
|
LAYOUT-BLOCK
|
BLKSBP
|
Bloka scrolbara atrašanās
vieta
|
LEFT, RIGHT
|
|
BLKVSB
|
Vai tiek ģenerēts bloka vertikālais scrolbars
|
Y, N
|
LAYOUT-TEXT ITEM
|
TXTBEV
|
Teksta vienību slīpums
|
None, Raised,
Lowered
|
|
TXTDDF
|
Teksta lauku noklusētais datuma formāta tips
|
Datuma formāts
|
|
TXTDHT
|
Teksta lauku noklusētais augstums
|
1-9
|
|
TXTDNF
|
Teksta lauku noklusētais skaitļu
formāts
|
Skaitļu formāts
|
LAYOUT
|
WIN???
|
Visi šie parametri nosaka logu noklusētās īpašības
|
|
LIST OF VALUES
|
LOVBUT
|
Vai laukam, kam iespējams LOV blakus rādīt LOV pogu
|
Y, N
|
|
LOVVAL
|
Vai pārbaudīt lauka vērtību LOV’ā
|
Y, N
|
TEMPLATE
|
STFFMB
|
Šablonformas vārds
|
|
GENERATE OPTIONS
|
VLDTFK
|
Kad pārbaudīt ārējās atslēgas korektumu
|
B, C, F, N
|
|
VLDTPK
|
Kad pābaudīt primārās atslēgas
korektumu
|
B, C. F, N
|
Vislielākās problēmas, aprakstot preferences, ir to apjoms, izmantotie
saīsinājumi un ļoti mazais dokumentācijas apjoms. Lai saprastu katras
preferences būtību no tās saīsinājuma, vai arī, lai atrastu kura preference
apraksta konkrēto īpašību, vajadzīgs laiks. Visa palīdzības informācija
pieejama tikai izmantojot Oracle palīdzību (Online
Documentation) [2].
2.4. Padomi interfeisa uzlabošanai
Oracle Developer/2000 ir
attīstījies daudzu gadu laikā, no simbolu bāzētas vides uz grafisko vidi, tomēr
vēl joprojām patērējams daudz laika, lai izveidotu Oracle lietojumprogrammu ar labu
lietotāja-datora interfeisu.
Kā piemēru aplūkosim izvēlni. Oracle izvēlne pēc noklusēšanas satur:
darbība (Action), bloks (Block), lauks (Field) u.t.t., bet MS
Windows vidē noklusētā izvēlne ir fails (File),
labot (Edit), skats (View).
Veidojot lietojumprogrammas Oracle vidē, to galvenā priekšrocība ir tā, ka tās
var izpildīt arī citās platformās, tādās kā Macintosh, Motif u.c. Šis varētu
būt iemesls kāpēc aizkavējās labu lietotāja-datora applikāciju izstrāde
speciāli MS Windows videi, kurā strādā lielākā daļa datoru.
Lasot vairākus literatūras izdevumus un informācijas lappuses Internetā
tika apkopoti un izanalizēti vajadzīgākie un labākie 12 padomi, kā labāk veidot
profesionālākas, vieglāk lietojamas un intuitīvi saprotamas Oracle
lietojumprogrammas MS Windows videi,
tādā veido laužot Oracle standarta lietojumprogrammu iezīmi [7], [9]. Kā rāda
pieredze, lietotājiem, kas strādā MS
Windows vidē ir ļoti grūti pārslēgties uz Oracle piedāvāto stilu un
terminoloģiju.
2.4.1. Rīku josla
Šodien jebkura grafikās vides
lietojumprogramma liekas nepilnīga, ja tajā nav rīku joslas. Parasti uz rīku
joslas krāsainu spiedpogu veidā tiek attēloti visbiežāk lietoto funkciju
izsaukumi. Bieži lietojamās funkcijas tiek attēlotas grafiski vieglākai
informācijas uztverei un izpildei.
![]() |
Visbiežāk lietojamās funkcijas Oracle formās, kuras vajadzētu ievietot rīku joslā ir - saglabāt (Commit or Save), nākošais ieraksts (Next record), iepriekšējais ieraksts (Previous record), attīrīt formu (Clear form), attīrīt rakstu (Clear record), beigt (Exit), meklēt (Enter Query), atlasīt rakstus (Execute Query) un citas atkarībā no uzdevuma.
2.6. attēls. Rīku josla.
Funkcijas, kuras var apvienot
grupās arī rīku joslā vajadzētu attēlot grupās, tādējādi atdalot funkcijas pēc
to nozīmes. Piemēram, vienā grupā likt funkcijas nākošais ieraksts (Next record), iepriekšējais ieraksts (Previous record), un otrā izveidot
ierakstu (Create record), dzēst
ierakstu (Delete record), attīrīt
ierakstu (Clear record). Vienas
grupas spiedpogas ir jānovieto blakus viena otrai, bet grupas savstarpēji
jāatdala ar 6-10 punktu tukšu joslu.
Bez tam daudz lietotāju vēlas rīku joslu atvērt atsevišķā logā, kuru var
novietot jebkurā vietā pēc izvēles. Arī to iespējams izveidot, nedaudz mainot
programmas kodu, tikai ar vienu piebildi, ka rīku josla būs vai nu atsevišķā
logā, vai pamatlogā zem izvēlnes. Lietotājs to nevar pārnest no viena stāvokļa
uz otru kā tas iespējams MS Word
vidē.
2.4.2. Rīku padomi (Tooltips) - spiedpogu nozīmju aprakstīšana
![]() |
Rīku padomi (Tooltips) ir palīdzības teksts, kas apraksta spiedpogas nozīmi un parādās, kad pele kādu laiku nekustīgi tiek novietota virs spiedpogas. Kā zināms lielākā daļa MS Windows lietojumprogrammu satur šos rīku padomus. Tas palīdz saprast spiedpogas nozīmi, ja tās ideju nevar uztvert pēc grafiskās interpretācijas.
2.7. attēls. Oracle standarta rīka padoms.
![]() |
Oracle noklusētais rīka padoms tāpat kā visi citi interfeisa objekti, atšķiras no MS Windows standarta rīka padoma, skatīt 2.7. attēlu. Tam ir standarta izmērs, un tas vienmēr parādās blakus spiedpogai, tādējādi aizsedzot pārējās. Nedaudz pielabojot esošo programmkodu, vai arī izmantojot no Oracle corp. saņemto hint.dll failu, rīku padomu var pārveidot par MS Windows standartam līdzīgu kā parādīts 2.8. attēlā, kas neaizsedz citas spiedpogas un kuras izmērs ir atkarīgs no teksta garuma.
2.8. attēls. Rīka padoms, kas līdzīgs MS Windows standartam.
2.4.3. Standartizvēlnes
Izvēlne ir viena no galvenajām
komponentēm lietojumprogramas interfeisā [5]. Diemžēl noklusētā Oracle Forms 4.5 izvēlne krasi atšķiras no
pieņemtās MS Windows standarta
izvēlnes. Tajā ietverti tādi termini kā darbība (Action), labot (Edit),
bloks (Block), lauks (Field), ieraksts (Record), pieprasījums (Query).
Tie ir datu bāzu vadības sistēmu pamatjēdzieni, taču to lietošana izvēlnēs
samulsina lietotājus, jo tie ir pieraduši pie izvēlņu standartjēdzieniem -
fails (File), labot (Edit) u.t.t. Bez tam diez vai lietotāju
interesē programmas skaņošanas režīms (Debug).

2.9. attēls. Oracle standarta izvēlne.
Lai nerastos problēmas ar to lietošanu, vairāki autori neiesaka to lietot.
Tā vietā izstrādātājam pašam vajadzētu izveidot izvēlni, kas līdzinātos
standarta MS Windows izvēlnei. Tad
arī lietotājiem neradīsies problēmas
atrast to ko viņi meklē, jo tie intuitīvi zinās, zem kuras izvēlnes punkta
atrodas viņu meklējamā funkcija.
Vispirms izvēlnei ir jādod iespēja
piekļūt visiem sistēmas moduļiem. Var pastāvēt arī citi veidi un ceļi kā
izsaukt kādu citu modeli, taču izvēlnei jābūt vispilnīgākajai. Izstrādājot
izvēlni kā piemēru var aplūkot jebkuru MS
Windows produkta izvēlni. Pirmajiem diviem izvēlnes punktiem no kreisās
puses jābūt fails (File) un labot (Edit). Pēdējiem diviem jābūt logi (Windows), kam seko palīdzība (Help). Palīdzības izvēlnes parasti
satur šādas standarta iespējas kā palīdzības izsaukšana, informāciju par
lietojumprogrammu un citas, skatīt 2.10. attēlu. Tas protams labi noder, kad
runa iet par konkrētu datu ievades formu. Bet kā veidot izvēlnes galvenajai
formai, kas izsauc citus moduļus, no kuriem tālāk tiek izsauktas datu ievades
un redigēšanas formas? Tā laikam ir katra izstrādātāja un pasūtītāja gaumes un
norunas lieta.

2.10. attēls. Sistēmas izvēlne, kas līdzīga MS Windows izvēlnei.
Izvēlnes var tikt veidotas, kā nemainīgas
visas lietojumprogrammas darbības gaitā, kā arī tādas, kas mainās atkarībā no
konteksta. Iecienītākā pieeja šajā gadījumā ir lietot standarta nemainīgas
izvēlnes, ar papildus iespēju aizliegt izvēlnes punktus, kad tie nav vajadzīgi,
atkarībā no konteksta. Tādējādi lietotājs vienmēr zinās izvēlnes izkārtojumu,
neatkarīgi no konteksta, kas otrajā gadījumā būtu daudz grūtāk, ja izvēlne
mainās atkarībā no konteksta.
2.4.4. Ievadlauku krāsu nozīme
Strādājot ar datu bāžu vadības sistēmām,
datu ievades formās ievadāmie raksti parasti satur obligātos laukus (not null, mandatory), laukus, kas var
būt arī tukši (optional) un laukus,
kas tiek izmantoti tikai informācijas rādīšanai (kur informāciju nedrīkst
ievadīt vai mainīt). Tas palīdz
lietotājam vizuāli ātrāk atšķirt informatīvos laukus no laukiem, kuros dati ir
jāievada. Daži autori iesaka katram no šiem trim tipiem lietot savu krāsu, taču
kā rāda pieredze, pārāk krāsainas datu formas biedē lietotājus, jo tie apjūk
šajā krāsu gammā. Bet ir lietas, ko vajadzētu izšķirt vienmēr - laukus datu
ievadei un laukus informācijas pasniegšanai. Tāpat kā standarta MS Windows lietojumprogrammās, arī
Oracle formās būtu ieteicams informācijas laukus rādīt vienkārši kā tekstu vai
kā pelēku ievadlauku, kurā nav iespējama informācijas maiņa.
![]() |
2.11. attēls. Ievadlauku attēlošana, atkarībā no
informācijas.
Taču neatšķirot obligātos (mandatory) laukus no neobligātiem (optional), lietotājs bieži vien,
saglabājot datus, saņem kļūdas paziņojumu, ka laukā obligāti jāievada informācija
(“field must be entered !”) vai lauks
nevar tikt mainīts (“field is protect to
update against !”). Vai šos laukus veidot atšķirīgus vai nē pilnā mērā
atkarīgs no izstrādātāja un lietotāja vienošanās.
2.4.5. Logu virsraksti
Strādājot ar Oracle Forms 4.5, to izpildāmais modulis (Oracle Forms Runtime) kā logu virsrakstu vienmēr lieto tekstu
“Developer/2000 Forms Runtime for Windows 95/NT - [module]“.

2.12.attēls. Oracle
Forms Runtime noklusētais logu virsraksts.
Jebkura profesionāli izstrādāta lietojumprogramma vienmēr satur savu
nosaukumu, kas papildināts ar tekošā moduļa nosaukumu. Pamatlogs, kurā tiek
startēta lietojumprogramma, tiek saukts par FORMS_MDI_WINDOW.
Šī loga parametri nevar tikt mainīti izstrādes laikā, tāpēc tie jāmaina
programmātiski. Galvenās formas WHEN-NEW-FORM-INSTANCE
trigerī ir jānomaina šī loga virsraksts lietojot komandu:
Set_Window_Property(Forms_MDI_Window,
Title, “Mana
applikācija”);
![]() |
2.13. attēls. Lietotāja definēts logu virsraksts.
Katrai formai sistēmā, tās galvenā moduļa
logam ir jāievada tā virsraksts, aprakstot to loga “Title” īpašībā. Tādējādi visas lietojumprogrammas darbības laikā
jūsu lietojumprogrammas virsraksts būs -
“Mana lietojumprogramma [modulis]”.
Ja lietojumprogramma satur vairākus
moduļus (formas), tad katra moduļa nosaukums jāpievieno cieši klāt visas
lietojumprogrammas nosaukumam, izmantojot to pašu funkciju.
Šad tad ir ļoti vajadzīgi loga virsrakstā
ievietot informāciju par aktīvo rakstu, bloku, piemēram, tāpat kā MS Word attēlo tekošā dokumenta
nosaukumu. To, tāpat kā iepriekš tika aprakstīts var mainīt tikai
programmātiski lietojumprogrammas darbības laikā.
Bez loga virsraksta maiņas vēl var mainīt
katra loga ikonu, tādējādi arī grafiski raksturojot moduli, kuram pieder
konkrētā forma. To var izdarīt jebkuram formas logam, gan formu dizainerī, gan
programmātiski formas darbības laikā, izņemot pašu galveno logu - FORMS_MDI_WINDOW. Kāpēc Oracle nav
devusi iespēju labot arī šo loga ikonu, nav saprotams, taču paliek cerība, ka
tas būs realizēts nākošajā Oracle Forms 5.0.
2.4.6. Resursu pārbaude pirms lietojumprogrammas palaišanas
Developer/2000
vide savai darbībai prasa ļoti daudz resursu, it sevišķi, ja formā tiek lietots
daudz spiedpogu, izvēles sarakstu, izvēles rūtiņas (check box) un citi [3]. Iztērējot visus sistēmas resursus,
Windows 3.1 vidē tika izraisīta atmiņas kļūda (GPF - General Protection Fault or “insufficient memory to run this application”). Šāda tipa kļūdas ir
raksturīgas arī Windows95/NT vidē. Ja tiek izstrādātas ļoti liela apjoma
lietojumprogrammas, tad šāda tipa kļūdas var būt ļoti biežas, it sevišķi, ja
lietotāja datoram ir maz resursu.
Viens no veidiem kā izvairīties no šāda
tipa kļūdām, ielasot kārtējo formu, ir resursu pārbaude pirms formas ielādes.
Ja tas ir zem minimālās robežas, tad izdod brīdinājuma signālu. Viena no Oracle
Forms 4.5 demostrācijām dod piemēru
kā noteikt brīvos resursus MS Windows 3.1 vidē. Lai to pašu
veiktu MS Windows95 vidē, var izmantot to pašu algoritmu, tikai
jāpārraksta *.DLL fails, lai varētu nolasīt sistēmas un atmiņas resursus MS Windows95 vidē.
Experimentāli tika pārbaudīts, ka uz datora ar pastāvīgu virtuālās atmiņas
apgabalu, gadījumā ja atmiņas resursi ir zem 10% no iespējamā (runa ir tikai
par atmiņu - brīvās atmiņas attiecība pret visu atmiņas apjomu), Oracle Forms Runtime 4.5 nestartējas, paziņot
par atmiņas trūkumu dažādu bibliotēku ielādei. Tādējādi var uzskatīt, ka
kritiskā robeža formas ielādei ir šie 10%.
Kā kritiskā robeža jaunas formas ielādei eksperimentāli tika noteiks - 1%
no atmiņas resursiem.
Programmas koda piemēru, lietojumprogrammas atvēršanai ar atmiņas resursu
pārbaudi MS Windows95 videi, var
aplūkot pielikumā, darba beigās.
2.4.7. Par - ātra informācija par jūsu lietojumprogrammu
Kā viens no MS Windows lietojumprogrammu
interfeisa standartiem ir parādīt galveno informāciju par lietojumprogrammu
atsevišķā logā (About box).
Šādā logā attēlo vajadzīgo un nepieciešamo informāciju par jūsu
lietojumprogrammu. Piemēram, šādā logā var attēlot šādu informāciju par jūsu
lietojumprogrammu kā: lietojumprogrammas nosaukums, tekošās versijas numurs,
izlaišanas datums, kā arī lietotāja “login” vārds, tekošās formas nosaukums,
Oracle datubāzes nosaukumu un pat sistēmas brīvo resursu apjoms. Tas var
lieliski palīdzēt lietotājam aprakstīt sistēmas tekošo stāvokli, ziņojot par
sistēmas kļūdām.
![]() |
Kā arī, ja gribas izteikt atzinību projekta komandai, šeit ir īstā vieta kur ievietot viņu vārdus.
2.14. attēls. Par - ātra informācija par jūsu
lietojumprogrammu.
Lai izveidotu šādu formu Developer/2000
vidē, atliek tikai izveidot parastu formu, kurā pirms datu parādīšanas no
datubāzes vai teksta faila, tiek nolasīta informācija par sistēmas versiju,
izstrādes datumu utt. Pārējo informāciju, kā lietotāju, sistēmas resursus un
citus, var iegūt no sistēmas mainīgajiem, vai izmanojot ORA_FFI funkcijas kā tika minēts iepriekš.
2.4.8. Paroles maiņa
Laiku pa laikam sistēmas drošības nolūkos
lietotājam ir jāmaina sava parole un visdraudzīgākais veids kā to veikt ir
veidot savu formu ar labu interfeisu, jo Oracle Forms 4.5 to nepiedāvā kā standarta iespēju. Visparastākais un
vienīgais veids kā to lietotājs var veikt ir izpildīt dažas komandas SQL*Plus vidē. Bet, tā kā lielākā daļa
lietotāju nav pazīstami ar SQL*Plus
(un vispār nezin kādam nolūkam tas paredzēts), ir vajadzīga vienkāršāka
iespēja.

2.15. attēls. Paroles maiņa.
Lai nomainītu lietotāja paroli, ir
jāizveido maza forma, kas pārprasa lietotāja veco paroli, lūdz ievadīt jauno
paroli un pēc tam to nomaina. Lietotāja vārdu un tekošo paroli var uzzināt
izmantojot Get_Application_Property
funkciju [3]. Savukārt lai nomainītu lietotāja paroli ir jāizpilda sekojoša
komanda:
Forms_DDL(‘ALTER
USER ‘|| :block.name ||’ IDENTIFIED
BY ‘|| :block.new_password);
Ja paroles maiņa bijusi veiksmīga, tad
tikai atliek aizvērt esošo savienojumu (disconnect)
ar Oracle datu bāzi un atkal atjaunot savienojumu (reconnect), izmantojot komandas:
LOGOUT;
LOGON(:block.user,
:block.new_password || ‘@’||
ConnectString, TRUE);
2.4.9. Progresa rādītājs
Salīdzinoši ar citām DBVS sistēmām, tādām kā MS Fox Pro, MS Access un citām, Oracle strādā salīdzinoši lēnāk
vairāku iemeslu dēļ. Pirmkārt jau grafiskā interfeisa vide, kas salīdzinoši ar
teksta vidi ir lēnāka. Otrkārt, nodrošinot lielu datu drošumu, tiek zaudēts
daudz laika, kaut vai veicot visparastākās ierakstīšanas vai labošanas
operācijas datu bāzē. Taču lietotājs parasti vērojot ilgus procesus, kas tiek
īsi aprakstīti ar frāzi “Mazliet uzgaidiet…” vai “Working…” ir ne pārāk
apmierināts, jo nezin, cik ilgi vēl mazliet būs jāgaida. Tāpēc gadījumos, kad
operācijas ar datiem varētu ievilkties ilgāk par 20-30 sekundēm, būtu ieteicams
lietot progresa rādītāju, kas parāda cik ātri noris process un cik ilgi tas vēl
iespējams turpināsies.

2.16. attēls. Progresa rādītājs.
Oracle Forms to nepiedāvā kā daļu no sava interfeisa, bet to viegli var
izveidot kā *.dll failu kādā citā programēšanas vidē (C++, Delphi). Piemēru kā
to veikt, var aplūkot pielikumā, darba beigās.
2.4.10. Lietojumprogrammu palaišana
Viens no parastākajiem veidiem kā startēt
Developer/2000 lietojumprogrammu ir
izpildīt komandrindu, kas startē Oracle Runforms, kā parametru saņemot
izpildāmās formas vārdu:
c:\orawin\bin\f45run.exe c:\mydir\myapp.fmx
Taču tas izskatītos daudz labāk, ja
lietojumprogramma tiktu startēta, piemēram šādi:
c:\mydir\myapp.exe
Tādējādi tiks atvieglota sistēmas
palaišanas problēma un konfigurēšana. Lielākais vairums liela apjoma
lietojumprogrammu, kas startējas zināmu laiku, izmanto pagaidu (Splash) ekrānus, kas tiek rādīti, kamēr
ielādējas sistēma, parādot, ka notiek sistēmas ielāde. Tas ir labāk nekā
skatīties kā deg diska aktivitātes lampiņa, un domāt vai notiek sistēmas
ielāde, vai atmiņas pārnešana uz disku. Tam ir liela nozīme gadījumos, ja
sistēma startējas ilgu laiku, kas ilgāks par 4-5 sekundēm, it sevišķi kā tas ir
Developer/2000 gadījumā (Oracle Runform ielāde uz Pentium 133MHz datora ar 16Mb
atmiņu aizņem 15-25s). Pagaidu (Splash) ekrāns var tikt iekļauts .exe
failā, kas arī startē lietojumprogrammu.
Programmas piemēru var aplūkot pielikumā, darba beigās.
![]() |
2.17. attēls. Pagaidu ekrāns programmas startēšanas laikā.
Tādu .exe moduli var izveidot, lietojot
daudzus programmēšanas rīkus, kā C, Delphi, Visual Basic. Startējot programmu no šīs vides, tiek
parādīts grafisks attēls, un pēc tam tiek ielādēta Oracle lietojumprogramma,
izpildot sekojošu komandu rindu:
c:\orawin\bin\f45run.exe
c:\mydir\myapp.fmx
Lai programma varētu izpildīties no jebkuras mašīnas, pirms Oracle
lietojumprogrammas startēšanas no sistēmas reģistrija jānolasa Oracle
instalācijas katalogs, lai zinātu, kur atrodas formu startēšanas programma f45run.exe. Oracle instalācijas katalogs sistēmas reģistrijā atrodas zem atslēgas -
My Computer\HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\ORACLE_HOME
2.4.11. MS Windows palīdzības logi
Ja darbam ar lietojumprogrammu
nepieciešama labi organizēta palīdzība un visas lietojumprogrammas tiek
izstrādātas MS Windows vidē, tad šeit
it tikai viens veids kā to panākt - MS
Help. MS Help ir lielisks līdzeklis
sistēmas palīdzības aprakstīšanai, pie kam lietotājs papildus nav jāapmāca ar
to rīkoties, kā tas ir gadījumā ar Oracle
Book 2.2 (programma Oracle palīdzības failu lasīšanai), kas bez tam prasa
laiku un datora resursus, lai to lietotu. Lai to veiktu, var izmantot jebkuru MS Windows palīdzības tekstu
veidotāj-lietojumprogrammu. Tās ir viegli lietojamas, kas ļauj ātri veidot
palīdzības failus. Kad palīdzības faili ir gatavi, tos var integrēt Developer/2000 lietojumprogrammu vidē.
No Oracle vides standarta palīdzību var
izsaukt, izmantojot ORA_FFI (Oracle
Foreign Function Interface) paketi [3], kas atļauj izsaukt standarta
palīdzības funkcijas no Developer/2000
lietojumprogrammu vides. Tādējādi iespējams izveidot kontekst-jūtīgu palīdzību
jebkurai Oracle lietojumprogrammai.
2.4.12. Nodaļlapas (Tabbed pages) - jauns interfeisa standarts
Nodaļu lapu (tabbed pages) interfeiss kļuva ļoti populārs tūlīt pēc MS Windows95 iznākšanas. Nodaļu lapas ir viegli saprotams veids
informācijas grupēšanai un pasniegšanai lietojumprogrammā. Šāda veida
informācijas attēlošana, ļauj lietotājam viegli apskatīt visu informāciju
lietojumprogrammā.
Oracle Forms 4.5-ās nodaļlapas var izveidot lietojot vizuālos pamatelementus VBX (Visual Basic Control) [3] vai arī
vienkāršas bildes, kurām pievieno triggerus, lai apstrādātu gadījumus kad
lietotājs nopiež vienu vai otru pogu un veiktu pāreju uz citu lapu. Lai šādas
lapas izveidotu Oracle Forms 4.5
vidē, ir nepieciešams uzrakstīt programmas kodu, taču kā informē Oracle Corp.,
nodaļlapas kā interfeisa objekts jau ir iekļautas jaunajā Oracle Forms 6.0 versijā (Developer 6.0).
![]() |
2.18. attēls. Nodaļlapas Oracle Forms 4.5.
Bez tam eksistē dažas nianses, ko daži autori iesaka ievērot, veidojot
nodaļlapas. Katru nodaļu vajag nosaukt īsi, parasti vienā vārdā un tam ir jābūt
saprotamam, kā arī viennozīmīgi jāraksturo zem tā esošās lapas ideja. Bez tam,
nav ieteicams veidot vairāk par 7 nodaļām vienlaikus, jo cilvēka vizuālās
informācijas uztveres spējas ir ierobežotas.
2.4.13. Palīdzības teksta (Hint) krāsa
Standarta palīdzības teksti (Hint message), kas tiek parādīti Oracle Forms 4.5 konsoles logā (console window), izpildot Message
funkciju, ir ļoti grūti pamanāmi, jo tie tiek rakstīti ar maziem melniem
burtiem uz pelēka fona, kā rezultātā lietotāji tos parasti neievēro. Problēmas
sākas gadījumos, kad lietotājs ir palaidis garām kādu svarīgu informāciju.
Protams pastāv iespēja, izmantot Oracle formu Alert funkciju, kas parāda informatīvu logu un gaida kamēr
lietotājs nospiedīs OK pogu. Taču šāds risinājums no lietotāju viedokļa ne
vienmēr ir pieņemams, jo tas prasa lieku darbību izpildīšanu, kas ne vienmēr ir
vēlama. Viena no iespējām būtu parādīt šo palīdzības tekstu lielākā fontā, taču
sakarā ar to ka šis tekstam paredzētais laukums nav maināms, palielinot fontu
būs redzama tikai daļa no teksta - vai nu augšējā vai apakšējā. Otrs
risinājums, kas arī ir viegli realizējams, ir izmainīt šī teksta krāsu, teiksim
uz sarkanu va zilu, kas uzreiz pievērš lietotāja uzmanību.
Lai izmainītu Oracle Forms 4.5 palīdzības loga teksta krāsu ir jālieto programma Oracle Terminal. Tā atļauj lietotājam
mainīt krāsas, fontus un citus atribūtus, izveidojot resursu datni, kurā visa
šī informācija tiek glabāta. Konkrēti Oracle Forms 4.5 palīdzības teksta krāsas maiņa veicama, labojot atribūta forms_logical īpašības Status-Message un Status-Hint. Pirmais no tiem nosaka palīdzības līnijas krāsas, kas
tiek parādītas ar funkcijas Message palīdzību, bet otrais attiecīgi palīdzības
tekstu, kas tiek rādīts nostādot kursoru kādā no ievadlaukiem (lauka
informatīvais teksts - hint). Beidzot
darbu ar šo programmu, tās dati jāsaglabā kā atsevišķa resursu datne, kas
jānorāda kā parametrs startējot sistēmu. Izpildīšanas sintakse ir:
c:\orawin\bin\f45run.exe
c:\mydir\myapp.fmx
term=resource.res:windows
![]() |
2.19. attēls. Palīdzības teksts sarkanā krāsā.
Nobeigums
Tā kā Oracle formu veidošanas rīks nav
pārāk populārs, salīdzinot kaut vai ar Delphi un citiem produktiem, vēl nav
pieejams pietiekoši daudz literatūras par dažādiem izstrādes aspektiem, nemaz
nerunājot, ka literatūra latviešu valodā par Oracle nav pieejama praktiski
vispār. Rakstot šo darbu, tika atklāts daudz vērtīgas informācijas, kas lasot
oriģinālās Oracle grāmatas, bija iepriekš palaists garām, tieši apgūstamās
informācijas lielā apjoma dēļ. Gūtās iemaņas jau ir palīdzējušas vieglāk un
efektīvāk veidot Oracle formas un formu šablonformas, kas ietvertu visu
nepieciešamos objektus turpmākai izstrādei. Liels ieguvums bija iegūtā
informācija par formu izejas koda optimizāciju. Prasības pēc sistēmas izejas
koda optimizācijas radās automātiski, tiklīdz pieauga ekspluatējamās sistēmas
datu apjoms un veicamie darbi sāka izpildīties lēnāk tikai lielā datu apjoma
dēļ vien. Pirmā reālā problēma bija optimizēt datņu veidošanu, kas sekmīgi tika
realizēta, kā tas tika aprakstīts darbā. Organizācijā, kurā es pašlaik
strādāju, drīzumā ekspluatācijā tiks palaista sistēma, kurā daudz klientu
atradīsies ļoti tālu no datu bāzes servera. Savienojums tiks organizēts, izmantojot
modema pieslēgumu. Rakstot šo darbu, tika atklātas daudzas nianses formas
objektu atribūtu vērtībās, kas rakstot sistēmas darbam normālā datortīklā
netiek ņemtas vērā, kaut vai tāda iemesla dēļ, ka Oracle kompānija tās savā
produktā piedāvā kā noklusētās vērtības. Taču startējot sistēmu attālinātā
režīmā tās darbība ir krietni lēnāka, nekā pēc formu optimizācijas. Kā jau tika
minēts darba gaitā, turpmāk ir vēlēšanas izpētīt vēl dažas Oracle formu un
Oracle servera iespējas, kas ļautu dažus uzdevumus risināt vēl ātrāk.
Ļoti liels ieguvums bija arī 2.
nodaļā aprakstītā šablonformu izmantošana formu ģenerācijā. Arī līdz šim tika
lietotas šablonformas, taču bez atsaucēm uz objektiem. Tas radīja lielu laika
patēriņu sistēmas izstrādes gaitā, kad atklājās, ka vajadzīgs jauns objekts vai
jālabo kāda vizuālā atribūta īpašības (visbiežāk krāsas), jo izrādās, ka citos
datoros, ar citu izšķirtspēju un krāsu paleti, to nav iespējams redzēt.
Nepieciešamo objektu aprakstīšana šablonformā, izmantojot atsauces, to minimizēja
līdz minimumam, jo izmaiņas tagad bija jāveic tikai vienā vietā - formā no
kuras tiek veidota objektu atsauce. 2.4. nodaļā aprakstītie piemēri novērš
dažus Oracle formu lietotāja-datora interfeisa trūkumus. Šeit jāatceras, ka
Oracle formas ir produkts, kas tiek lietots uz daudzām platformām, kā rezultātā
produktam ir savas lietotāja-datora interfeisa īpatnības, kas MS Windows lietotājam nevienmēr ir
pieņemamas. Daži no tiem tika apkopoti no rakstiem žurnālos un internetā, daži
manis doti, kas kļuva aktuāli pēc sarunām ar lietotājiem vai vienkārši
iedomājoties sevi lietotāja vietā. Vēl līdz galam neizpētīta ir palikusi tikai
lietotāju palīdzības logu veidošana, izmantojot MS Help, ko autors cer realizēt tuvākajā laikā.
Kā tika minēts darbā, jaunajā produkta versijā Oracle Forms 6.0 ir paredzami uzlabojumi un papildinājumi lietotāja-datora
interfeisa jomā - vairāki jauni interfeisa objekti, kas tagad ir standarta
interfeisa objekti MS Windows vidē.
Literatūra
1.
Oracle
Designer/2000 A Guide to Developer/2000 Generation, ORACLE 1995
2.
Oracle
Designer/2000 Online Documentation
3.
Oracle
Developer/2000 Forms 4.5 Reference Manual vol.1/ vol. 2, ORACLE 1994
4.
Oracle
Developer/2000 Forms 4.5 Advanced Techniques Manual, ORACLE 1994
5.
Oracle
Developer/2000 Forms 4.5 Getting Started Manual, ORACLE 1994
6.
Oracle
Forms 4.5 Online Help
7.
Oracle
Informant, March 1997, vol.2. #3, “Your Game Face - Tips for Developing a
Quality User Interface” p. 8-13, An Informant Communications Group Publication
1997
11.
DBMS_PIPE
pakotnes apraksts datu bāzē
Pielikums
Programmu teksti
Formu koda optimizācija
-----------------------------------
-- Datnes ielasīšana
formu daļa --
-----------------------------------
BEGIN
if NOT
VISA_SYSTEM.Get_Parameter_Value('DSPL_LINES', s_lines) then
s_lines := '5';
end if;
sync_lines := To_Number(s_lines);
LOG.pInit;
MyList.InitRetrieval('SELECTED_FILES',vFileNameForLog );
p.SingleFilename := MyList.GetListElement;
IF p.SingleFilename IS NULL then
RAISE NotFile;
END IF;
:BLOCK1.idi:=NULL;
go_item('block1.sview');
Set_Item_Property('BLOCK1.ok', ENABLED,
Property_False);
Set_Item_Property('BLOCK1.exit', ENABLED,
Property_False);
START_TIME := DBMS_UTILITY.Get_Time;
VISA_READ_IN_CTF.Reset_Perf_Time;
LOG.log_time := 0;
WHILE p.SingleFilename IS NOT NULL LOOP
write_sum := True;
begin
LOG.ResetVariables(iMonTransactions,Line,iBatch_nr);
:block1.cur_file := p.SingleFilename;
begin
sREAD_TIME :=
DBMS_UTILITY.Get_Time;
in_file :=
TEXT_IO.FOPEN(p.StartDir||
p.SingleFilename, 'r');
READ_TIME := READ_TIME +
(DBMS_UTILITY.Get_Time - sREAD_TIME);
exception when OTHERS then
LOG.MyErrorMsg :=
CanNotOpenMsg||p.StartDir||
p.SingleFilename;
RAISE MyError;
end;
:block1.line := 0;
:block1.batch_nr := 0;
:block1.transaction := 0;
synchronize;
IF NOT
VISA_READ_IN_CTF.Init(p.SingleFilename,
LOG.MyErrorMsg,nFileID) then
RAISE MyError;
END
IF;
SET_APPLICATION_PROPERTY(CURSOR_STYLE, 'busy');
BEGIN -- process file
:BLOCK1.idi:=:BLOCK1.idi||to_char(nFileID)||',';
LOOP
sREAD_TIME :=
DBMS_UTILITY.Get_Time;
BEGIN
TEXT_IO.GET_LINE(in_file,
linebuf);
EXCEPTION
WHEN NO_DATA_found then
Raise Faila_beigas;
When
OTHERS then
LOG.MyErrorMsg := VISA_SYSTEM.Get_Error_Message(50,
p.StartDir||
p.SingleFilename, NULL, NULL);
RAISE MyError;
END;
READ_TIME := READ_TIME +
(DBMS_UTILITY.Get_Time - sREAD_TIME);
LOG.pCalculateSummaries(linebuf,
iMonTransactions,Line,iBatch_nr);
---------------------------------------------
-- Ivo 20.01.99
-- Nosakam banku kurai pieder
fails
---------------------------------------------
IF Line = 1 then
BEGIN
SELECT NAME
INTO Bank_name
FROM VISA_BANKS
WHERE
bin = SubStr(linebuf, 3,6);
Exception WHEN OTHERS then
Bank_name :=
'Unknown';
END;
----------------
LOG.AddErrMesgInList(VISA_SYSTEM.
Get_Error_Message(98,p.StartDir||
p.SingleFilename, Bank_name, NULL));
END IF;
-------------------------------------
-- TE IR VISA SAALS
-------------------------------------
IF NOT VISA_READ_IN_CTF.WRITE_DATA(linebuf,
LOG.MyErrorMsg) then
RAISE
MyError;
END IF;
IF
LOG.MyErrorMsg IS NOT NULL then
:BLOCK1.sview := 2;
Show_view('LOG');
END IF;
LOG.AddErrMesgInList(LOG.MyErrorMsg,TRUE);
END LOOP;
EXCEPTION
WHEN no_data_found or Faila_beigas THEN
sREAD_TIME
:= DBMS_UTILITY.Get_Time;
TEXT_IO.FCLOSE(in_file);
READ_TIME
:= READ_TIME +
(DBMS_UTILITY.Get_Time –
sREAD_TIME);
END; -- process file
:block1.line := Line;
:block1.batch_nr := iBatch_nr;
:block1.transaction := iMonTransactions;
synchronize;
--process End
IF
NOT VISA_READ_IN_CTF.ValidateEnd(LOG.MyErrorMsg)
then
RAISE MyError;
ELSE
IF LOG.MyErrorMsg IS NOT NULL then
LOG.AddErrMesgInList(LOG.MyErrorMsg,TRUE);
write_sum := False;
END IF;
END
IF;
BEGIN
sREAD_TIME := DBMS_UTILITY.Get_Time;
message(VISA_SYSTEM.Get_Error_Message(21,
p.SingleFilename,p.Destination, NULL),
NO_ACKNOWLEDGE);
synchronize;
Destination := p.Destination
||p.SingleFilename;
Win_Api_Utility.move_file(p.StartDir||p.SingleFilename, Destination);
READ_TIME := READ_TIME + (DBMS_UTILITY.Get_Time
- sREAD_TIME);
message(' ' , NO_ACKNOWLEDGE);
synchronize;
exception
when no_data_found then
LOG.AddErrMesgInList(VISA_SYSTEM.
Get_Error_Message(9021,Destination,NULL,
NULL));
END;
--*********************************
LOG.AddErrMesgInList(OkMsg);
IF
write_sum then
LOG.pWriteSummary(Settlement=>FALSE);
END
IF;
totallines := totallines + line;
--********* Addind from Plus Bin -> to
BIN TMP ..
sPLUS_TIME := DBMS_UTILITY.Get_Time;
AddPlusBin;
PLUS_TIME := PLUS_TIME +
(DBMS_UTILITY.Get_Time
- sPLUS_TIME);
/**********STOPLIST creation*/
sSTOP_TIME := DBMS_UTILITY.Get_Time;
CreateStopList;
STOP_TIME := STOP_TIME +
(DBMS_UTILITY.Get_Time
- sSTOP_TIME);
/**********VSM file creation*/
sVSM_TIME := DBMS_UTILITY.Get_Time;
CreateVSMFile;
VSM_TIME := VSM_TIME
+ (DBMS_UTILITY.Get_Time –
sVSM_TIME);
-- Ivo 12.08.98
tuksha liinija aiz katra faila
LOG.AddErrMesgInList(' ');
EXCEPTION
when MyError then
pError;
when OTHERS then
LOG.MyErrorMsg := SQLERRM;
pError;
END;
LOG.sLOG_TIME := DBMS_UTILITY.Get_Time;
:block1.cur_file := NULL;
:block1.transaction := NULL;
line
:= 0;
:block1.line
:=NULL;
:block1.batch_nr:=NULL;
p.SingleFilename
:= MyList.GetListElement;
LOG.LOG_TIME := LOG.LOG_TIME +
(DBMS_UTILITY.Get_Time –
LOG.sLOG_TIME);
END LOOP;
TOTAL_TIME := DBMS_UTILITY.Get_Time - (START_TIME +
PLUS_TIME + STOP_TIME + VSM_TIME);
lTIME :=
LOG.LOG_TIME;
-- Savaadaak kameer shitos
drukaas buus
-- jau lielaaks
IF totallines <> 0 then
tsecperline :=
Round((TOTAL_TIME)/totallines, 0);
ELSE
tsecperline := 0;
END IF;
-- PERFORMANCE
LOG.AddErrMesgInList('--- Performance ---');
LOG.AddErrMesgInList('Total Time :
'||VISA_SYSTEM.Perf_Time(TOTAL_TIME, TOTAL_TIME));
LOG.AddErrMesgInList(' File operations:
'||VISA_SYSTEM.Perf_Time(READ_TIME, TOTAL_TIME));
LOG.AddErrMesgInList(' Checking data :
'||VISA_SYSTEM.Perf_Time(VISA_READ_IN_CTF.CHECKTIME,
TOTAL_TIME));
LOG.AddErrMesgInList(' Inserting data :
'||VISA_SYSTEM.Perf_Time(VISA_READ_IN_CTF.INSERTTIME,
TOTAL_TIME));
LOG.AddErrMesgInList(' ----------------');
vDummy :='1';
IF totallines <>
0 then
LOG.AddErrMesgInList(' Time per TCR :
'||VISA_SYSTEM.Perf_Time(tsecperline,
tsecperline));
END IF;
LOG.pWriteFromList('block1.messages','READ_VISA_CTF',
nFileID,
vFileNameForLog);--
:BLOCK1.tasknr:=nFileID;
set_item_property('block1.print_log',
enabled,
property_true);
END;
-------------------------------------
-- Datnes ielasīšana
servera daļa --
-------------------------------------
FUNCTION
WRITE_DATA(str IN VarChar2, err_text OUT
VarChar2) Return BOOLEAN IS
galva VarChar2(2) := SubStr(str, 1, 2);
MasterTransNotFound
EXCEPTION;
PRAGMA
EXCEPTION_INIT(MasterTransNotFound, -02291);
BEGIN
-- PERFORMANCE
sCHECK_TIME := DBMS_UTILITY.Get_Time;
/****Kontrole****/
if nLine=1 then
if LENGTH(str)=0 then --File is empty
Return(DoError(10, err_text));
elsif galva != '90' then
-- File doesn’t begin with Header record
-- ''90''
Return(DoError(11, err_text));
end if;
end if;
IF galva='92' AND
IeprieksejaGalva <>'91' then
--Pirms beigaam
nav kopsavilkuma
Return(DoError(12, err_text));
END IF;
IF galva <> '90' then
-- not Header ->
calculate TRANSACTIONs
gTcrSk := gTcrSk + 1;
fTcrSk := fTcrSk + 1;
END IF;
/****IELASIISHANA****/
IF galva = '90' then
-- Faila KONTROLE !!!!!! Ivo 20.01.99
IF NOT Check_File_Header then
Return false;
END IF;
InsertHeader_buf;
ELSIF galva = '01' or galva = '02' or
galva = '03' then
IF SubStr(str, 4, 1) IN('0', '1',
'2', '3',
'4', '5', '6', '7', '8') then
InsertRETURNED_ITEM08;
if SubStr(str, 4, 1) = '0'
then
gMonTrnSk := gMonTrnSk
+ 1;
fMonTrnSk := fMonTrnSk
+ 1;
end if;
ELSIF SubStr(str, 4, 1) = '9'
then
InsertRETURNED_ITEM9;
ELSE --error
Return(DoError(3,
err_text));
END IF;
ELSIF galva IN
('05','06','07','15','16','17',
'25','26','27','35','36','37') then
IF SubStr(str, 4, 1) = '0' then
InsertDRAFT0_BUF;
gMonTrnSk := gMonTrnSk +
1;
fMonTrnSk := fMonTrnSk +
1;
ELSIF SubStr(str, 4, 1) = '1'
then
InsertDRAFT1_BUF;
ELSIF SubStr(str, 4, 1) = '3'
then
InsertDRAFT3_BUF;
ELSIF SubStr(str, 4, 1) = '4'
then
InsertDRAFT4_BUF;
ELSIF SubStr(str, 4, 1) = '5'
then
InsertDRAFT5_BUF;
ELSIF SubStr(str, 4, 1) = '6'
then
InsertDRAFT6_BUF;
ELSE --error
Return(DoError(4,
err_text));
END IF;
ELSIF galva IN ('10','20') then
InsertFEE_COL_FUNDS_DISB;
gMonTrnSk := gMonTrnSk + 1;
fMonTrnSk := fMonTrnSk + 1;
ELSIF galva = '33' then
IF SubStr(str, 35, 10) =
'TAPEHEADER' then
PLUS_HEAD := TRUE;
InsertPLUS_BIN_HEADER;
ELSIF SubStr(str, 35, 11) =
'TAPETRAILER' then
PLUS_TRAIL :=TRUE;
InsertPLUS_BIN_TRAILER;
ELSIF SubStr(str, 35, 6) =
'HEADER' then ROUTE_HEAD := TRUE;
Route_Line := nLine;
ELSIF SubStr(str, 35, 7) =
'TRAILER' then ROUTE_TRAIL :=TRUE;
err_text :=
VISA_SYSTEM.Get_Error_Message(42,
to_char(Route_line),to_char(nLine),
NULL);
ELSIF SubStr(str, 35, 6) =
vVSM_VERS||'000' then
VSM_HEAD := TRUE;
InsertVsmHEADER;
ELSIF SubStr(str, 35, 6) =
vVSM_VERS||'900' then
if VSM_HEAD then
VSM_TRAIL := TRUE;
InsertVsmTRAILER;
VSM_HEAD := FALSE;
WasInsertedVSM := TRUE;
else
Return(DoError(30,
err_text));
end
if;
ELSE
if PLUS_HEAD then
if NOT PLUS_TRAIL then
InsertPLUS_BIN_DETAILS;
WasInsertedPlusBinDetails := TRUE;
else
Return(DoError(31,
err_text));
end if;
elsif ROUTE_HEAD then
if NOT ROUTE_TRAIL then
NULL;
else
Return(DoError(43,
err_text));
end if;
elsif VSM_HEAD then
if SubStr(str, 35, 6) =
vVSM_VERS||'200' then
InsertVsmTran1;
elsif SubStr(str, 35,
6) =
vVSM_VERS||'210' then
InsertVsmTran2;
elsif SubStr(str, 35,
6) =
vVSM_VERS||'220' then
InsertVsmTran3;
elsif SubStr(str, 35,
6) =
vVSM_VERS||'225' then
InsertVsmTran4;
elsif SubStr(str, 35, 6) =
vVSM_VERS||'250' then
InsertVsmATM;
elsif SubStr(str, 35,
6) =
vVSM_VERS||'260' then
InsertVsmMultiCCY;
elsif SubStr(str, 35,
6) =
vVSM_VERS||'500' then
InsertVsmRECM1;
elsif SubStr(str, 35,
6) =
vVSM_VERS||'510' then
InsertVsmRECM2;
else
err_text :=
VISA_SYSTEM.Get_Error_Message(32,to_char(nLine),SubStr(str,
35, 6), NULL);
RememberError(err_text);
end if;
else
err_text :=
VISA_SYSTEM.Get_Error_Message(33,to_char(nLine),SubStr(str,
35, 6), NULL);
RememberError(err_text);
Return(DoError(33,
err_text,SubStr(str, 35, 6)));
end if;
END If;
ELSIF galva = '44' then
IF UPPER(SubStr(str, 36, 1)) IN
('R','A') then
InsertCBATCH_ACKNOW_TRN_AR;
ELSIF UPPER(SubStr(str, 4, 1)) !=
'0' then
InsertCBATCH_ACKNOW_TRN_18;
ELSE
Return(DoError(5, err_text));
END IF;
ELSIF galva = '45' then
InsertGEN_DEL_REPORTS;
ELSIF galva = '46' then
IF UPPER(SubStr(str, 60, 2)) IN
('4F','4G','6F','7 ','8A','9A') then
InsertMEMB_SETTL_DATA0;
ELSIF SubStr(str, 60, 2) = '12'
then
InsertMEMB_SETTL_DATAB;
ELSIF SubStr(str, 60, 2) = 'C4'
then
InsertMEMB_SETTL_DATAC;
ELSIF SubStr(str, 60, 2) = '89'
then
InsertMEMB_SETTL_DATAI;
ELSE
Return(DoError(6,
err_text));
END IF;
ELSIF galva = '48' then
IF SubStr(str, 4, 1) = '0' then
IF SubStr(str, 17, 1) = '0'
then
InsertBASEI_ADV_REC0F0;
ELSIF SubStr(str, 17, 1) =
'1' then
InsertBASEI_ADV_REC0F1;
END IF;
ELSIF SubStr(str, 4, 1) = '1'
then
InsertBASEI_ADV_REC1;
ELSIF SubStr(str, 4, 1) = '2'
then
InsertBASEI_ADV_REC2;
ELSE
Return(DoError(7,
err_text));
END IF;
ELSIF galva = '50' then
IF UPPER(SubStr(str, 23, 5)) =
'CTMFI' then
NULL;
ELSIF
UPPER(SubStr(str, 23, 5)) <> 'CTMFI' then
InsertTEXT_MESSAGES;
irteksts:=TRUE;
ELSE
Return(DoError(8, err_text));
END IF;
ELSIF galva IN('51','52','53') then
IF SubStr(str, 4, 1) = '0' then
InsertRETREQ_CONFIRM0;
ELSIF SubStr(str, 4, 1) = '1'
then
InsertRETREQ_CONFIRM1;
ELSIF SubStr(str, 4, 1) = '4' then
InsertRETREQ_CONFIRM4;
ELSE
Return(DoError(9,
err_text));
END IF;
ELSIF galva = '55' then
IF SubStr(str, 4, 1) = '0' then
InsertRCRF_UPDATE0;
ELSIF SubStr(str, 4, 1) IN
('1','2') then
InsertRCRF_UPDATE12;
ELSE
Return(DoError(29,
err_text));
END IF;
WasInsertedSTOPLIST := TRUE;
ELSIF galva = '56' then
InsertCCY_RATE_UPDATES;
ELSIF galva = '91' then
--Kopsavilkums, Batch
beigas
if NOT
InsertBATCH_FILE_TRAILER_BUF(err_num) then
Return(DoError(err_num,
err_text));
end if;
BatchNr := BatchNr +1;
gTcrSk :=0; --Batch level Check
gMonTrnSk :=0;
gDestAmount :=0;
ELSIF galva = '92' then -- trailer
if VSM_HEAD then
return(DoError(36, err_text));
end if;
if NOT
InsertBATCH_FILE_TRAILER_BUF(err_num) then
Return(DoError(err_num,
err_text));
end if;
BatchNr := BatchNr - 1;
ELSE
err_text :=
VISA_SYSTEM.Get_Error_Message(20,
to_char(nLine),SubStr(str,1,4), NULL);
END IF; -- galva
nLine := nLine +1;
IeprieksejaGalva := galva;
-- Performance
CHECK_TIME := CHECK_TIME +
(DBMS_UTILITY.Get_Time –
sCHECK_TIME);
return(TRUE);
EXCEPTION
WHEN MasterTransNotFound then
if galva
IN('01','02','03','05','06','07',
'15','16','17','25','26','27',
'35','36','37','51','52','53') then
-- Performance
CHECK_TIME := CHECK_TIME +
(DBMS_UTILITY.Get_Time - sCHECK_TIME);
return(DoError(24, err_text));
else
-- Performance
CHECK_TIME := CHECK_TIME +
(DBMS_UTILITY.Get_Time - sCHECK_TIME);
return(DoError(48, err_text));
end if;
WHEN OTHERS then
-- Performance
CHECK_TIME := CHECK_TIME +
(DBMS_UTILITY.Get_Time - sCHECK_TIME);
return(DoError(19, err_text));
END; -- WRITE_DATA
---------------------------------
-- Datu atlasīšana pēc
maskas --
---------------------------------
PROCEDURE Set_Mask (pre_form IN BOOLEAN) IS
bnk VarChar2(2) := IZD_RESTR_ACC.acc_bank;
grp VarChar2(2) := IZD_RESTR_ACC.acc_card_grup;
id VarChar2(6) := IZD_RESTR_ACC.user_id;
-----------------------------------
mask VarChar2(1234);
xclient IZD_CL_ACCT_SEARCHW_MASK.client%TYPE;
xf_names IZD_CL_ACCT_SEARCHW_MASK.f_names%TYPE;
xsurname IZD_CL_ACCT_SEARCHW_MASK.surname%TYPE;
xccy IZD_CL_ACCT_SEARCHW_MASK.ccy%TYPE;
xcard_acct IZD_CL_ACCT_SEARCHW_MASK.card_acct%TYPE;
xcard_name IZD_CL_ACCT_SEARCHW_MASK.card_name%TYPE;
BEGIN
If pre_form then
-- Savacam vecos datus
SELECT client, f_names, surname, ccy,
card_acct, card_name
INTO xclient, xf_names, xsurname,
xccy, xcard_acct,
xcard_name
FROM IZD_CL_ACCT_SEARCHW_MASK
WHERE usrid = id and bank_c = bnk and
groupc = grp;
Set_Block_Property('MASK',
DEFAULT_WHERE,
'usrid='''||id||''' and
bank_c='''||bnk||''' and
groupc='''||grp||'''');
ELSE
xclient :=
:MASK.client;
xf_names :=
:MASK.f_names;
xsurname :=
:MASK.surname;
xccy :=
:MASK.ccy;
xcard_acct :=
:MASK.card_acct;
xcard_name :=
:MASK.card_name;
End IF;
mask := '';
If xclient IS NOT NULL then
mask := 'client like '''||xclient||'''
and client=client';
End if;
If xf_names IS NOT NULL or xsurname IS NOT
NULL then
If mask IS NOT NULL then
mask := mask||' and search_name
like
UPPER('''||xf_names||'%'||xsurname||'%'')';
ELSE
mask := 'search_name like
UPPER('''||xf_names||'%'||xsurname||'%'')';
End If;
End if;
If xccy IS NOT NULL then
If mask IS NOT NULL then
mask := mask||' and UPPER(ccy)
like
UPPER('''||xccy||''')';
ELSE
mask := 'UPPER(ccy) like
UPPER('''||xccy||''')';
End If;
End if;
If xcard_acct IS NOT NULL then
If mask IS NOT NULL then
mask := mask||' and card_acct
like
'''||xcard_acct||''' and card_acct=card_acct';
ELSE
mask := 'card_acct like
'''||xcard_acct||''' and
card_acct=card_acct';
End If;
End if;
If xcard_name IS NOT NULL then
If mask IS NOT NULL then
mask := mask||' and
UPPER(card_name) like
UPPER('''||xcard_name||''')';
ELSE
mask := 'UPPER(card_name) like
UPPER('''||xcard_name||''')';
End If;
End if;
IF :PARAMETER.next_hop = 'MAKE_ACCNT_DORM'
then
If mask IS NOT NULL then
mask := mask||' and status
<> ''3''';
ELSE
mask := 'status <> ''3''';
End If;
ELSIF :PARAMETER.next_hop = 'MAKE_DORM_ACTIV' then
If mask IS NOT NULL then
mask := mask||' and status =
''3''';
ELSE
mask := 'status = ''3''';
End If;
ELSIF :PARAMETER.next_hop = 'MAKE_ACCNT_CLOS' then
If mask IS NOT NULL then
mask := mask||' and status =
''3''';
ELSE
mask := 'status = ''3''';
End If;
END IF;
Set_Block_Property('ACSEARCH',
DEFAULT_WHERE,mask);
If NOT pre_form then
:CG$CTRL.changed := 'TRUE';
END IF;
END;
Lietotāja interfeisa uzlabošana
----------------------------
-- RĪKU JOSLAS DARBĪBAS --
----------------------------
/ PROCEDURE TOOLBAR_ACTIONS /
-- This procedure implements the toolbar functionality.
-- The logic reads the pressed button name and then calls
-- the appropriate function. If you want to change the
-- toolbar then make sure the if statement below has one
-- entry for each button.
----------------------------------------------
--
Standart from ORACLE FORMS GENERATOR
--
Modified by me, May 1997
----------------------------------------------
PROCEDURE TOOLBAR_ACTIONS IS
button_name varchar2(61);
button varchar2(31);
BEGIN
show_window(get_view_property(get_item_property(
name_in('SYSTEM.CURSOR_ITEM'),
item_canvas), window_name));
button_name :=
name_in('SYSTEM.TRIGGER_ITEM');
button := substr(button_name, instr(button_name,
'.')+1);
if (button = 'SAVE') then
do_key('COMMIT_FORM');
elsif (button = 'PRINT') then
do_key('PRINT');
elsif (button = 'CLEAR_FORM')
then
do_key('CLEAR_FORM');
elsif (button = 'QUERY_FIND') then
if (name_in('SYSTEM.MODE') != 'ENTER-QUERY') then
do_key('ENTER_QUERY');
else
do_key('EXECUTE_QUERY');
end if;
ELSIF (button =
'INSERT_RECORD') THEN
do_key('CREATE_RECORD');
ELSIF (button =
'DELETE_RECORD') THEN
do_key('DELETE_RECORD');
ELSIF (button = 'CLEAR_RECORD')
THEN
do_key('CLEAR_RECORD');
ELSIF (button = 'LIST') THEN
do_key('LIST_VALUES');
ELSIF (button = 'EDIT') THEN
do_key('EDIT_FIELD');
ELSIF (button = 'HELP') THEN
do_key('HELP');
ELSIF (button = 'OPNAME' ) THEN
-- Operators name who
changed this record
get_operator_name ;
ELSIF (button = 'SWITCH' ) THEN
-- Change layout mode from BROWSE to RECORD
change_layout_mode ;
ELSIF (button = 'HISTORY' )
THEN
-- Record’s update history
Hist.History_Show ;
ELSIF (button = 'EXIT') THEN
do_key('EXIT_FORM');
END IF ;
END;
/PROCEDURE Change_Layout_Style/
PROCEDURE change_layout_mode IS
-- Blocks need always end '1' and
'2'
-- blockname1 and blockname2
l_Block_Name VARCHAR2(30) :=
Name_In(':SYSTEM.CURRENT_BLOCK') ;
l_block_name_head VARCHAR2(30) := SUBSTR( RTRIM( l_Block_Name ), 1,
LENGTH(
RTRIM( l_Block_Name ) ) - 1 );
l_block_name_tail VARCHAR2(1) := SUBSTR( RTRIM( l_Block_Name ),-1,1);
l_go_block_name VARCHAR2(30) ;
l_go_block BLOCK ;
BEGIN
-- Change to………
IF l_block_name_tail = '1' THEN
l_go_block_name :=
l_block_name_head || '2' ;
ELSE
l_go_block_name :=
l_block_name_head || '1' ;
END IF ;
-- Block’s ID
l_go_block := FIND_BLOCK(
l_go_block_name ) ;
IF ID_NULL( l_go_block ) THEN
-- Block not found ->
go to the same block
l_go_block_name :=
l_block_name_head ;
l_go_block := FIND_BLOCK(
l_go_block_name ) ;
END IF ;
IF NOT ID_NULL( l_go_block
)THEN
BEGIN
GO_BLOCK(
l_go_block_name ) ;
EXCEPTION
WHEN OTHERS THEN
MESSAGE(
'Unable change layout :' ||
ERROR_TEXT ) ;
END ;
END IF ;
END;
----------------
-- TOOLTIPS --
----------------
-- Uses:
Hint.pll -- From ORACLE Corp.
-- Shwhnt32.dll
/ PACKAGE HINT.pll /
PACKAGE HINT IS
PROCEDURE ShowButtonHelp( timedelay NUMBER := 500);
PROCEDURE ShowButtonHelpHandler;
PROCEDURE HideButtonHelp;
END HINT;
/ WHEN-TIMER-EXPIRED TRIGGER /
BEGIN
-- Shows tootip
hint.ShowButtonHelpHandler;
END;
/ WHEN-MOUSE-UP TRIGGER /
/ WHEN-MOUSE-LEAVE TRIGGER /
/ WHEN-MOUSE-DOWN TRIGGER /
/ WHEN-NEW-BLOCK-INSTANCE TRIGGER /
/ WHEN-WINDOW-CLOSED TRIGGER /
/ WHEN-WINDOW-ACTIVATED TRIGGER /
/ WHEN-WINDOW-DEACTIVATED TRIGGER /
BEGIN
-- Hides tootip
hint.HideButtonHelp;
END;
/ WHEN-MOUSE-ENTER TRIGGER /
BEGIN
-- Creates timer for tooltip
hint.ShowButtonHelp;
END;
-------------------------------------
-- IEVADLAUKU KRĀSU
APRAKSTĪŠANA --
-------------------------------------
/ WHEN-NEW-FORM TRIGGER /
Set_Field_DSPL_Property(‘BLOCK_NAME’, ‘FIELD_NAME’, Property);
-- Property : 0 -
DISABLED
1 - ENABLED, Optional
2 - ENABLED, Mandatory
/PROCEDURE Set_Field_DSPL_Property/
PROCEDURE Set_Field_DSPL_Property(
block_name IN CHAR,
field_name IN CHAR,
value IN CHAR) IS
can_update VarChar2(10);
BEGIN
IF value = '0' Then
-- DISABLED Item
Set_Item_Property(block_name||'.'||field_name,
UPDATEABLE, Property_False);
Set_Item_Property(block_name||'.'||field_name,
VISUAL_ATTRIBUTE, 'DISABLED_ITEM');
Set_Item_Property(block_name||'.'||field_name,
ENABLED, Property_False);
ELSIF value = '1' Then
-- OPTIONAL Item
Set_Item_Property(block_name||'.'||field_name,
ENABLED, Property_True);
Set_Item_Property(block_name||'.'||field_name,
NAVIGABLE, Property_True);
Set_Item_Property(block_name||'.'||field_name,
REQUIRED, Property_False);
Set_Item_Property(block_name||'.'||field_name,
VISUAL_ATTRIBUTE, 'CG$ITEM');
ELSIF value = '2' Then
-- MANDOTARY Item
can_update:=Get_Item_Property(block_name||'.'||
field_name, UPDATEABLE);
Set_Item_Property(block_name||'.'||field_name,
ENABLED, Property_True);
Set_Item_Property(block_name||'.'||field_name,
NAVIGABLE, Property_True);
Set_Item_Property(block_name||'.'||field_name,
VISUAL_ATTRIBUTE, 'CG$ITEM');
-- REQUIRED var uzstadīt
tikai ja UPDATEABLE=true
Set_Item_Property(block_name||'.'||field_name,
UPDATEABLE, Property_True);
Set_Item_Property(block_name||'.'||field_name,
REQUIRED, Property_True);
IF can_update = 'FALSE'
then
Set_Item_Property(block_name||'.'||
field_name, UPDATEABLE, Property_False);
END IF;
END IF;
END;
-----------------------
-- LOGU
VIRSRAKSTI --
-----------------------
/PRE-FORM TRIGGER/
Set_Window_Property(FORMS_MDI_WINDOW, WINDOW_STATE, MAXIMIZE);
Set_Window_Property(FORMS_MDI_WINDOW, TITLE, ‘MY APPLICATION’);
Set_Window_Property(‘WINDOW_NAME’, TITLE, ‘MY MODULE’);
---------------------------------
-- SISTĒMAS RESURSU
PĀRBAUDE --
---------------------------------
-- Uses:
MemInfo.pll -- Interface for MemInfo.dll
MemInfo.dll -- Written by Eriks
Aleksans
/ MemInfo.pll /
PACKAGE MemInfo IS
FUNCTION TotalPhysMem RETURN
PLS_INTEGER;
FUNCTION FreePhysMem RETURN
PLS_INTEGER;
FUNCTION TotalVirtualMem RETURN
PLS_INTEGER;
FUNCTION FreeVirtualMem RETURN
PLS_INTEGER;
END;
PACKAGE BODY MemInfo IS
---------------------------------------------------------
-- Special THANKS to Eriks Aleksans (Xire) for
-- MEMINFO.DLL /written in Delphi II/
---------------------------------------------------------
lu ORA_FFI.LIBHANDLETYPE :=
ORA_FFI.load_Library('',
'MEMINFO.DLL');
f1 ORA_FFI.FUNCHANDLETYPE :=
ORA_FFI.Register_Function(lu, 'TotalPhysMem',
ORA_FFI.PASCAL_STD);
f2 ORA_FFI.FUNCHANDLETYPE :=
ORA_FFI.Register_Function(lu, 'FreePhysMem',
ORA_FFI.PASCAL_STD);
f3 ORA_FFI.FUNCHANDLETYPE :=
ORA_FFI.Register_Function(lu,’TotalVirtualMem',
ORA_FFI.PASCAL_STD);
f4 ORA_FFI.FUNCHANDLETYPE :=
ORA_FFI.Register_Function(lu, 'FreeVirtualMem',
ORA_FFI.PASCAL_STD);
---------------------------------------------------------
FUNCTION GetResult(fh IN
ORA_FFI.FUNCHANDLETYPE)
RETURN PLS_INTEGER;
PRAGMA interface(c, GetResult,
11265);
---------------------------------------------------------
Function TotalPhysMem return
PLS_INTEGER IS
BEGIN
Return
Round(GetResult(f1)/1024);
END;
Function FreePhysMem return
PLS_INTEGER IS
BEGIN
Return
Round(GetResult(f2)/1024);
END;
Function TotalVirtualMem return
PLS_INTEGER IS
BEGIN
Return
Round(GetResult(f3)/1024);
END;
Function FreeVirtualMem return
PLS_INTEGER IS
BEGIN
Return Round(GetResult(f4)/1024);
END;
---------------------------------------------------------
BEGIN
ORA_FFI.Register_Return(f1,
ORA_FFI.C_INT);
ORA_FFI.Register_Return(f2,
ORA_FFI.C_INT);
ORA_FFI.Register_Return(f3,
ORA_FFI.C_INT);
ORA_FFI.Register_Return(f4, ORA_FFI.C_INT);
END;
/ FUNCTION FreeMemResources /
FUNCTION FreeMemResources return PLS_INTEGER IS
BEGIN
Return
Round(((MemInfo.FreePhysMem + MemInfo.FreeVirtualMem) /
(MemInfo.TotalPhysMem + MemInfo.TotalVirtualMem))
* 100);
END;
/ PROCEDURE Call_My_Form with no parameters/
PROCEDURE Call_My_Form (name IN char) IS
min_mem NUmber := 1;
al_id Alert;
al_button Number;
BEGIN
IF FreeMemResources >
min_mem then
-- OK. Call form
Call_Form(name, HIDE,
NO_REPLACE, NO_QUERY_ONLY);
ELSE
al_id :=
Find_Alert('YES_NO_CHOICE');
IF Id_Null(al_id)
THEN
MSG_ALERT('Error:
ALERT ''YES_NO_CHOICE''
not found!', 'E', True);
ELSE
Set_Alert_Property(al_id,
alert_message_text,
'WARNING: There are less than ' || To_Char(min_mem) || '% of
memory free! Do You want to continue?');
END IF;
al_button := Show_Alert(
al_id );
IF al_button =
alert_button1 then
Call_Form(name,
HIDE, NO_REPLACE, NO_QUERY_ONLY);
ELSE
Return;
END IF;
END IF;
END;
/ PROCEDURE Call_My_Form with parameters /
PROCEDURE Call_My_Form_With_Param (name IN CHAR,
pl_id IN PARAMLIST) IS
min_mem NUmber := 1;
al_id Alert;
al_button Number;
BEGIN
IF FreeMemResources >
min_mem then
-- OK. Call form
Call_Form(name, HIDE,
NO_REPLACE, NO_QUERY_ONLY, pl_id);
ELSE
al_id :=
Find_Alert('YES_NO_CHOICE');
IF Id_Null(al_id)
THEN
MSG_ALERT('Error:
ALERT ''YES_NO_CHOICE''
not found!', 'E', True);
ELSE
Set_Alert_Property(al_id,
alert_message_text,
'WARNING: There are less than ' || To_Char(min_mem) || '% of
memory free! Do You want to continue?');
END IF;
al_button := Show_Alert(
al_id );
IF al_button =
alert_button1 then
Call_Form(name,
HIDE, NO_REPLACE, NO_QUERY_ONLY,
pl_id);
ELSE
Return;
END IF;
END IF;
END;
-----------------------------------------------------
-- PAR - ĀTRA
INFORMĀCIJA PAR LIETOJUMPROGRAMMU --
-----------------------------------------------------
/WHEN-NEW-FORM-INSTANCE TRIGGER/
DECLARE
vcVer varchar2(40);
BEGIN
Set_Window_Property('ABOUTWINDOW',
TITLE, 'About ‘
||:parameter.system);
show_window_centered('ABOUTWINDOW');
IF :parameter.version_number is
not null then
vcVer := ' Version: ‘
||:parameter.version_number;
END IF;
:about.System :=
:parameter.System;
:about.version := vcVer;
:about.Copyright := :parameter.copyright_msg;
:about.user := User;
:about.database :=
Get_Application_Property(Connect_String);
IF :about.database IS NULL then
:about.database := 'Default';
END IF;
IF
Get_Application_Property(Calling_Form) IS NOT
NULL then
:about.form :=
Get_Application_Property(Calling_Form);
ELSE
:about.form := 'None';
END IF;
:about.mem :=
To_Char(FreeMemResources)||
' %';
Go_Item('ABOUT.CLOSE');
END;
---------------------
-- PAROLES MAIŅA --
---------------------
/WHEN-BUTTON-PRESSED TRIGGER/
-- Uses
: OUO package --
SIMPLE ALERTS SERVICE
SRV package -- SIMPLE PACKAGE, that returns
ITEMS ID
DECLARE curr_butt VARCHAR2(61) := :SYSTEM.TRIGGER_ITEM;
i NUMBER;
BEGIN
IF curr_butt = 'BT.OK_BUTT'
THEN
IF NVL( :BT.PASSWORD ,
CHR(7) ) <> :BT.PWD THEN
-- old password does not match
i :=
ouo.up_alert( ouo.A_WARNING,
'WARNING',
'Old password does not match!');
GO_ITEM(
srv.ptr_password );
ELSIF :BT.NEW_PASSWORD IS NULL THEN
i :=
ouo.up_alert( ouo.A_WARNING,
'WARNING',
'Password cannot be empty!');
GO_ITEM(
srv.ptr_password );
ELSIF :BT.NEW_PASSWORD <> NVL(
:BT.NEW_VERIFY
,
CHR(7) ) THEN
-- old password OK, new isn't NULL
i :=
ouo.up_alert( ouo.A_WARNING,
'WARNING',
'New passwords does not match!');
GO_ITEM(
srv.ptr_password );
ELSE
Change_Password;
END IF;
ELSIF curr_butt = 'BT.CANC_BUTT' THEN
DO_KEY('EXIT_FORM');
END IF;
END;
/PROCEDURE Change_Password /
-- Uses
: OUO package -- SIMPLE ALERTS SERVICE
SRV package -- SIMPLE PACKAGE, that returns
ITEMS ID
PROCEDURE Change_Password IS
i NUMBER;
SQL_Text VARCHAR2(128);
BEGIN
i := ouo.up_alert(
ouo.A_ACCEPT, 'ACCEPT', 'Are you sure you
wish
to change the password?');
IF i = ALERT_BUTTON1 THEN
i := ouo.up_alert(
ouo.A_ACCEPT,
'ACCEPT','Accept once more : are you sure you wish to change
the password?');
IF i = ALERT_BUTTON1 THEN
-- Do IT!
i := ouo.up_alert(
ouo.A_ACCEPT,
'WARNING', 'Attempt to change password will commit all
uncommited changes! Do You want to continue?');
IF i =
ALERT_BUTTON1 THEN
IF
:BT.NEW_PASSWORD IS NULL THEN
SQL_Text
:= 'ALTER USER '|| :BT.USR ||
' IDENTIFIED EXTERNALLY';
ELSE
SQL_Text
:= 'ALTER USER '||
:BT.USR ||
' IDENTIFIED BY "'|| :BT.NEW_PASSWORD||'"';
END IF; --
:BT.NEW_PASWORD IS NULL
FORMS_DDL(
SQL_Text );
IF
FORM_SUCCESS THEN
i :=
ouo.up_alert( ouo.A_INFORM,
'NOTE', 'Your password has been changed successfuly.');
DO_KEY('EXIT_FORM');
ELSE
DECLARE et VARCHAR2(200) :=
DBMS_ERROR_TEXT;
t VARCHAR2(200):= ERROR_TEXT;
BEGIN
i := ouo.up_alert( ‘CFG_ERROR',
'DBMS_ERROR', et);
GO_ITEM( srv.ptr_new_password);
END;
END IF; --
FORM_SUCCESS
ELSE
GO_ITEM(
srv.ptr_password );
END IF; -- i = ALERT_BUTTON1
ELSE
GO_ITEM(
srv.ptr_password );
END IF; -- i =
ALERT_BUTTON1 THEN -- Do IT!~
ELSE
GO_ITEM( srv.ptr_password
);
END IF;
END;
/ PACKAGE OUO /
PACKAGE OUO IS -- Often Used
Objects
-- for F45 with STDT_KON referenced objects
A_SYS_ERR ALERT := FIND_ALERT('CFG_SYSTEM_ERROR');
A_ERROR ALERT; :=
FIND_ALERT('CFG_ERROR');
A_INFORM ALERT :=
FIND_ALERT('CFG_INFORMATION');
A_WARNING ALERT := FIND_ALERT('CFG_WARNING_A');
A_ACCEPT ALERT :=
FIND_ALERT('CFG_ACCEPT_A');
-- PROCEDURES AND FUNCTIONS
-- ALERTS SERVICES
FUNCTION Up_ALERT ( a_id ALERT, a_Title VARCHAR2,
a_Message VARCHAR2)
RETURN NUMBER;
FUNCTION Up_ALERT ( a_name VARCHAR2, a_Title VARCHAR2,
a_Message
VARCHAR2)RETURN NUMBER;
-- Error message from code
FUNCTION Treat_Error_Code ( eCode NUMBER ) RETURN VARCHAR2;
END;
/PACKAGE SRV/
PACKAGE srv IS
-- Returns Items ID for
“Change_Password” form’s objects
ptr_password ITEM := FIND_ITEM( 'BT.PASSWORD' ) ;
ptr_new_password ITEM := FIND_ITEM( 'BT.NEW_PASSWORD' ) ;
ptr_new_verify ITEM := FIND_ITEM( 'BT.NEW_VERIFY' ) ;
ptr_ok_butt ITEM := FIND_ITEM( 'BT.OK_BUTT' ) ;
ptr_canc_butt ITEM := FIND_ITEM( 'BT.CANC_BUTT' ) ;
END;
-------------------------
-- PROGRESA
RĀDĪTĀJS --
-------------------------
-- Uses:
INDI.pll -- Interface library for
-- INDI32.dll
INDI32.dll -- Writen by Karlis Ogsts in C++
/ INICIALIZĀCIJA /
If INDI.LoadLibrary(err_txt) then
INDI.Open;
Msg_Txt:='Preparing interface
files ...';
INDI.SetInfoMessage(msg_txt);
INDI.SetIndicator( 0 );
else
Message(err_txt);
Return;
End If;
/ TEKOŠĀS VĒRTĪBAS PARĀDĪŠANA /
INDI.SetIndicator( 2 );
/ PROGRESA RĀDĪTĀJA AIZVĒRŠANA /
INDI.CLOSE;
INDI.FreeLibrary;
/ INDI.pll /
package indi is
function LoadLibrary(szErrorMessage in out varchar2)
return boolean;
procedure Open;
procedure SetIndicator(plsComplete pls_integer);
procedure SetInfoMessage(szInfoMessage in out varchar2);
procedure Close;
procedure FreeLibrary;
END;
--------------------------------------------------------
-- LIETOJUMPROGRAMMAS STARTĒŠANA AR SPLASH EKRĀNU un --
-- RESURSU PĀRBAUDI --
--------------------------------------------------------
/ WHEN-NEW-FORM-INSTANCE TRIGER /
IF USER = 'GHOST' then
-- kill splash screen
HOST('Erase c:\issuing.knt',
NO_SCREEN);
-- Reconect;
LOGOUT ;
WHILE NOT Connected LOOP
LOGON_SCREEN;
o_user :=
GET_APPLICATION_PROPERTY( USERNAME ); o_pwd := GET_APPLICATION_PROPERTY( PASSWORD );
o_cs :=
GET_APPLICATION_PROPERTY(
CONNECT_STRING ) ;
IF RTRIM( o_user ) IS NOT
NULL THEN
IF RTRIM( o_cs ) IS
NOT NULL THEN
LOGON( o_user
, o_pwd ||'@'|| o_cs , FALSE);
ELSE
LOGON( o_user
, o_pwd , FALSE );
END IF ;
ELSE
-- Atgriezts tukss USER vaards
EXIT_FORM;
END IF ;
BEGIN
test := USER;
Connected := True;
EXCEPTION
WHEN OTHERS Then
LOGOUT;
-- Ļaujam
konektētie tikai 3x
IF Try = 3
then
EXIT_FORM;
END IF;
Try
:= Try + 1;
END;
END LOOP;
END IF;
/ MY_APPLICATION.EXE written in DELPHI II /
program mpcs;
uses
Forms,
Unit1 in 'Unit1.pas' {main};
{$R *.RES}
begin
Application.Initialize;
Application.CreateForm(Tmain,
main);
Application.Run;
end.
unit Unit1;
interface
uses
Windows, Messages, SysUtils,
Classes, Graphics, Controls, Forms, Dialogs,
ExtCtrls, T3Dt, StdCtrls, nbutton,
NoTask, RegFiles;
type
Tmain = class(TForm)
Panel1: TPanel;
Image1: TImage;
Timer1: TTimer;
Timer2: TTimer;
NoTask1: TNoTask;
Reg: TRegFile;
Text3D1: TText3D;
Text3D2: TText3D;
Text3D3: TText3D;
Text3D4: TText3D;
procedure FormKeyDown(Sender:
TObject; var Key: Word;
Shift: TShiftState);
procedure Timer1Timer(Sender:
TObject);
procedure Timer2Timer(Sender:
TObject);
procedure FormCreate(Sender:
TObject);
private
{ Private declarations }
f : file;
tagadvar : boolean;
procedure OuttaHere;
public
{ Public declarations }
end;
var
main: Tmain;
implementation
{$R *.DFM}
procedure Tmain.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
-- Avārijas gadijumā vienmēr
varam aizvērt splash screen ar F12
if Key = VK_F12 then Halt;
end;
procedure Tmain.OuttaHere;
begin
Halt;
end;
procedure Tmain.Timer1Timer(Sender: TObject);
var
i : integer;
s : TSearchRec;
begin
if not tagadvar then Exit;
// Skatamies uz fiktiivu failu
ko, savukārt dzēš ieks
// FORMS 4.5 kad taa
stratējusies.
//
------------------------------------------------------
// DEREETU PAARTAISIIT UZ REGISTRI
!!!!!!!!!!!!
if FindFirst('c:\forms45.knt',
faArchive, s) <> 0 then begin
FindClose(s);
Timer1.Enabled := False;
OuttaHere;
end;
FindClose(s);
end;
procedure Tmain.Timer2Timer(Sender: TObject);
var
s,
s1 : string;
i
: integer;
begin
s :=
Reg.ValueDefault['ORACLE_HOME', s];
-- Palaizam formu, kas
pieslēdzas ar fiktiivu useri GHOST
s := s + '\bin\f45run32.exe
TOP_MPCS.fmx USERID=GHOST/G';
for i := 1 to ParamCount do
begin
s := s + ParamStr(i);
end;
Timer2.Enabled := False;
// Izveidojam fiktiivo failu
AssignFile(f, 'c:\forms45.knt');
ReWrite(f, 1);
CloseFile(f);
tagadvar := True;
WinExec(PChar(s), 1);
end;
function FreePhysMem : integer; stdcall external 'meminfo.dll'
index 1;
function TotalPhysMem : integer; stdcall external 'meminfo.dll'
index 2;
function FreeVirtualMem : integer; stdcall external 'meminfo.dll'
index 3;
function TotalVirtualMem : integer; stdcall external 'meminfo.dll'
index 4;
procedure Tmain.FormCreate(Sender: TObject);
const
st = ' ';
var
s : string;
i : integer;
begin
s := Reg.ValueDefault['LOCAL',
s];
if s = '' then begin
// Registrija jaabut LOCAL datubaazei
defineetai…
ShowMessage(' Local connect string not defined
in registry! ');
Halt;
end;
i := Round( ((FreePhysMem +
FreeVirtualMem) /
(TotalPhysMem +
TotalVirtualMem)) * 100);
// RESURSU Pa’rbaude………
if i <= 10 then begin
if
Application.MessageBox('Free memory resources less than
10 %. ' + 'Do You want to continue?',
'Warning',
MB_ICONQUESTION +
MB_YESNO) = IDNO
then Halt;
end;
tagadvar := False;
end;
end.
Nav komentāru:
Ierakstīt komentāru