Josef Troch (troch@mail.ru)
5.11.2002 (poslední změna 14.1.2003)
4GL - procedurální programovací jazyk v Informixu
Pozn.: Všechny níže uvedené informace by se měly vztahovat k Informixu verze 7.
Co to je a k čemu to je?
V helpu k Informixu se dozvíte, že je to programovací jazyk 4. generace (odtud název 4.
Generation Language), který je použitelný úplně na všechno. Tento jazyk je ve skutečnosti
jakýmsi procedurálním rozšířením SQL (SQL je samo o sobě deklarativní).
4GL nám tedy nabízí (kromě toho, co umí SQL samé) možnosti známé z běžných procedurálních
programovacích jazyků, jako jsou C/C++ atp. Jedná se především o možnost vytvářet vlastní funkce,
cykly a možnost podmíněného vykonávání kódu.
Překlad, spouštění atd.
Informix nám nabízí dvě možnosti práce se systémem:
- 4GL C Compiler Version (c4gl) - používá se preprocessor, který přeloží program do
Embedded SQL - to se pak zpracovává klasicky: další prekompilací dostáváme korektní C-čkový
kód, který se pak již normálně přeloží a slinkuje.
Zjednodušená syntaxe spuštění všech výše uvedených kroků najednou:
c4gl filename.4gl
(Kompletní nápovědu k c4gl získáte spuštěním bez parametrů.)
- 4GL Rapid Development System (RDS) - jakýmsi kompilátorem se program přeloží do
pseudokódu, který je pak nutné spouštět pomocí interpreteru.
Syntaxe kompilace:
fglpc filename[.4gl]
(Máme-li více takto přeložených souborů, které "patří k sobě", je třeba je
skonkatenovat (třeba přes cat) do jednoho, až na ten pustíme interpreter.)
Syntaxe spuštění programu v interpreteru:
fglgo filename[.4go]
Dojde-li během překladu k chybě (chybám), vznikne soubor *.err - ten poměrně přehledně
ukazuje, kde k chybám došlo, obsahuje i krátké popisy chyb a hlavně jejich číslo, dle kterého lze
třeba tady zjistit přesný popis chyby.
Finální versi programu je samozřejmě vhodné překládat pomocí 4GL C Compiler Version - kvůli
rychlosti.
Konvence: nepřeložené soubory s 4GL je zvykem pojmenovávat *.4gl, po překladu přes fglpc
*.4go, po konkatenaci *.4gi
Integrovaná programovací prostředí
Hned na úvod poznamenávám, že tato prostředí není třeba používat - programy lze psát ve vašem
oblíbeném textovém editoru a kompilovat výše uvedeným způsobem. Osobně mi to připadá výrazně
pohodlnější.
- i4gl - integrované prostředí využívající c4gl
Obsah příslušných nabídek s vysvětlením:
Module:
New, Modify: vyvolání externího editor pro editaci 4GL kódu
Compile: překlad 4GL souboru (modulu)
Program-Compile: překlad programu definovaného ve volbě Program v main menu
Run: spustění preloženého programu
Program:
New, Modify: zadání/změna jmen modulů (4GL, Other = Embedded SQL, *.c, *.o) a
cest k nim, knihoven, přepínačů pro překladač jazyka C
Compile: přeloží celý program (obdobně k make - "nepřekládá
zbytečně")
Planned_Compile: výpis příkazových řádek pro překlad
- r4gl - integrované prostředí využívající RDS
Nabídky stejné s předchozím, navíc je jen v nabídkách Module a Program volba Debug, která
volá debugger INFORMIX-4GL ID.
Příklad jednoduchého programu ve 4GL
DEFINE vstup, vysledek FLOAT, mocnina INTEGER
MAIN
PROMPT "Zadej cislo:" FOR vstup
LET vysledek = 1
DISPLAY " Mocnina Vysledek"
FOR mocnina = 1 TO 4
LET vysledek = vysledek * vstup
DISPLAY mocnina, vysledek
END FOR
SLEEP 5
END MAIN
Pokud si chcete program zkompilovat a spustit, zde ho máte přímo v
souboru.
Složitější příklad bude k vidění na konci referátu.
Vysvětlivky k zápisu syntaxe výrazů:
[vyraz] - znamená, že vyraz se může na daném místě vyskytnout 0 či 1-krát.
[vyraz]* - znamená, že vyraz se může na daném místě vyskytnout 0 až
libovolně-krát.
Vše ostatní se na daném místě tedy může vyskytnout právě jedenkrát.
Syntaxe byla ve většině případů velmi zjednodušena - všechny možnosti syntaxe příslušných výrazů
lze nalézt v dokumentaci k Informixu.
Základy 4GL
- 4GL není case sensitive.
- Program se skládá z modulů (jednotlivé zdrojové soubory).
- V jednotlivých modulech se definují funkce.
- Program musí obsahovat právě jednu funkci MAIN, ukončuje se
END MAIN
- Obecná funkce začíná klíčovým slovem FUNCTION, končí END FUNCTION.
(Příklad viz níže.)
- Funkce pro generování tiskových výstupů začínají kl. slovem REPORT (konec funkce -
END REPORT). V těle reportu lze volat některé funkce, které jinde volat nelze.
- Všechny funkce jsou dostupné globálně. (Asi není třeba ani nic includovat.)
- Program lze odkudkoliv ukončit pomocí EXIT PROGRAM.
- Komentáře:
- jednořádkové - začínají "--" nebo "#"
- (potencielně) víceřádkové - vypadají nějak takto: { Toto je komentar. }
Typy, proměnné, operátory a konstanty
- Typy (bližší informace viz dokumentace Informixu -
4GL Quick Syntax Version
6.00):
ARRAY OF type, CHAR, CHARACTER, DATE, DATETIME, DEC, DECIMAL, DOUBLE PRECISION, FLOAT,
INT, INTEGER, INTERVAL, MONEY, NUMERIC, REAL, RECORD, SMALLFLOAT, SMALLINT.
... a některé další, které nelze použít všude či na všech verzích Informixu.
Pozn.: Literály číselné zapisujeme bez jakéhokoliv uvozování, řetězcové do úvozovek.
- Proměnné je třeba definovat.
Syntaxe: DEFINE prom TYP [, prom TYP]*
Místo typu proměnné lze uvést: LIKE tabulka.sloupec - tím říkáme, že chceme použít
typ příslušného sloupce.
Příklady:
DEFINE i INTEGER
DEFINE jmeno LIKE zamestnanec.jmeno
Globální proměnné musí být definované v sekci GLOBALS v samostatném modulu.
Příklad:
GLOBALS
DEFINE globalni CHAR (20)
END GLOBALS
Viditelnost: lokální proměnná překrývá globální.
- Pole
Syntaxe: DEFINE p ARRAY [rozmer1, rozmer2, rozmer3] OF typ
Zde hranaté závorky opravdu znamenají hranaté závorky. Rozměry pole - min. 1, max. 3. K
položkám pole se přistupuje klasicky přes hranaté závorky (jako v C).
Příklad:
DEFINE matice ARRAY[10, 20] OF INT
Záznamy
Syntaxe: DEFINE jmeno RECORD atr TYP [, atr TYP]* END RECORD
K položkám záznamu se přistupuje klasicky přes tečku (jako v C).
Příklad:
DEFINE komplex RECORD
r INT,
i INT
END RECORD
- Operátory:
- Aritmetické (binární): +, -, *, /, mod, ** (umocnění)
- Boolovské: AND, OR, NOT
- Relační: <, <=, >, >=, == (nebo =), != (nebo
<>)
- Předdefinované konstanty:
FALSE, TRUE, NULL (lze přiřadit libovolnému typu), NOTFOUND (vrací se při
nenalezení dalšího řádku u kursoru atp.)
Přiřazovací příkaz
Syntaxe: LET prom=value
Příklad:
LET i=0
Funkce
Níže uvedené platí obdobně i pro reporty.
Volání funkce, předávání parametrů, návratové hodnoty
Syntaxe: CALL jmenoFce ([param [, param]*]) [RETURNING ret [, ret]*]
Data se předávají pouze hodnotou. Funkce může vracet více hodnot (viz klausule RETURNING) -
bez jejich sdružování do záznamu.
Příklady:
CALL mojeFce()
CALL mojeFce2(12, "retezec")
CALL mojeFce3(12, "retezec") RETURNING ret1, ret2, ret3
Volání funkce, předávání parametrů, návratové hodnoty
Syntaxe:
FUNCTION jmenoFce ([param [, param]*])
[DEFINE param TYP [, param TYP]*]
...
[RETURN ret [, ret]*]
END FUNCTION
Funkce nemusí volat RETURN pokud nic nevrací, RETURN nemusí být nutně pouze na
konci funkce.
Příklad:
FUNCTION mojeFce3 (p1, p2)
DEFINE p1 INT, p2 CHAR (10), i INT
...
...
RETURN p1, i, p2
END FUNCTION
Řídící struktury
- IF ... THEN ... ELSE
Syntaxe:
IF podminka THEN ...
[ELSE ...]
END IF
Příklad:
IF x==4 THEN LET y=1
ELSE LET y=0
END IF
- FOR cyklus
Syntaxe:
FOR citac = start TO konec [STEP krok]
.....
END FOR
zacatek, konec i krok jsou typu INT; krok udává, jaká hodnota se
v každé iteraci přičítá k čítači. Tento musí být opět typu INT či SMALLINT.
Příkazem EXIT FOR lze vyskočit z cyklu, příkazem CONTINUE FOR spustit další
iteraci cyklu.
- WHILE cyklus
Syntaxe:
WHILE podminka
.....
END WHILE
EXIT WHILE, CONTINUE WHILE - obdobně jako u FOR cyklu
- GOTO
Syntaxe skoku: GOTO mujLabel
Syntaxe label-u: mujLabel: ...
- CASE - větvení programu
Syntaxe:
CASE [(promenna)]
WHEN podminka
....
[WHEN podminka]
....
[OTHERWISE]
....
END CASE
Výše uvedená syntaxe nám nabízí 2 možnosti užití - pokud za CASE neuvedeme proměnnou, pak
se podmínky za WHEN berou opravdu jako podmínky - rozhoduje se dle jejich platnosti. Pokud
proměnnou uvedeme, podmínky za WHEN se chápou jako hodnoty, na které se má testovat zadaná
proměnná - a rozhoduje se dle výsledků těchto testů.
Splňuje-li podmínku více WHEN větví, spustí se jen ta první. Po skončení libovolné WHEN
větve se skáče na pozici za END CASE (narozdíl od switch v C). Skok na toto místo lze
také odkudkoliv (z příslušného CASE-u) vyvolat pomocí EXIT CASE.
Příklady (oba dělají totéž):
CASE (x)
WHEN 4 LET y=1
WHEN 8 LET y=0
OTHERWISE EXIT PROGRAM
END CASE
CASE
WHEN x==4 LET y=1
WHEN x==8 LET y=0
OTHERWISE EXIT PROGRAM
END CASE
Používání SQL ve 4GL, práce s DB obecně
Práce se samotnou databází:
- DATABASE jmeno - otevření databáze
Přesněji: Toto klíčové slovo znamená 2 různé věci dle toho, kde je užito:
- Je-li použito na začátku souboru - mimo těla funkcí, jde o specifikaci defaultní
databáze - tu kompilátor používá mimo jiné při deklaracích datových typů dle tabulek v DB
(... LIKE ...). Takováto DB bude automaticky při startu programu otevřena.
- Je-li použito "normálně" uvnitř funkce, jde o příkaz k otevření dané databáze.
- CLOSE DATABASE - uzavření databáze (nelze uvést jméno - a ani to není třeba - v jednom
okamžiku může být otevřena nejvýše jedna DB).
- CREATE DATABASE jmeno - vytvoří novou prázdnou databázi (jméno může být uloženo v
řetězcové proměnné).
- DROP DATABASE jmeno smaže databázi (musí být uzavřená).
Libovolný SQL příkaz, který nevrací data (ALTER,
CREATE atp.) lze zapsat kamkoliv mezi 4GL příkazy. V tomto příkazu lze používat
proměnné 4GL. Totéž platí i pro SELECT, který vrací pouze 1 řádek - můžeme jím naplnit
zvolené proměnné.
Příklad:
DATABASE ctenari
DEFINE ct_id LIKE ctenari.id
SELECT id INTO ct_id FROM ctenari WHERE prijmeni="Vozihnoj"
CLOSE DATABASE ctenari
Kdyby výše uvedený SELECT vrátil více než 1 záznam, došlo by k chybě. Tento problém lze
řešit pomocí kursorů.
Kursor - odpovídá jednomu řádku příslušného dotazu, lze jím řádky
dotazu procházet.
Postup práce: deklarace kurzoru (DECLARE), otevření
kurzoru (OPEN), načtení dat (FETCH), uzavření kurzoru (CLOSE).
Příklad:
...
DEFINE zam RECORD LIKE zamestnanci.*
DECLARE kurzor CURSOR FOR SELECT * FROM zamestnanci
OPEN kurzor
WHILE (TRUE)
FETCH kurzor INTO zam.*
IF (STATUS == NOTFOUND) THEN EXIT WHILE
END IF
DISPLAY zam.*
END WHILE
CLOSE kurzor
...
STATUS je systémová proměnná; není-li v kursoru už další záznam, má hodnotu
NOTFOUND.
Celý výše uvedený cyklus lze napsat elegantněji s použitím klausule FOREACH:
DEFINE zam RECORD LIKE zamestnanci.*
DECLARE kurzor CURSOR FOR SELECT * FROM zamestnanci
FOREACH kurzor INTO zam.*
DISPLAY zam.*
END FOREACH
Analogicky jako u běžných cyklů zde lze používat EXIT FOREACH a CONTINUE FOREACH.
Pozn.: Existují i SCROLL kursory - deklarace je stejná jako u normálních, jen místo
CURSOR píšeme SCROLL CURSOR. Tyto kursory nám umožňují při FETCH pohnout
kursorem zvoleným způsobem (FIRST, LAST, PREVIOUS, NEXT, CURRENT, RELATIVE n (skok o n
záznamů vpřed, n může být i záporné - pak vzad), ABSOLUTE n(skok na n-tý řádek)).
Příklad:
FETCH PREVIOUS muj_kurzor INTO x
Příklad mírně složitějšího programu ve 4GL - SCROLL kursory
Zde uvádím trochu složitější příklad programu ve 4GL - předvádí, co umí
SCROLL kursory. Chcete-li program opravdu vyzkoušet, stáhněte si i vytvářecí a
likvidační skript.
Zdroje a odkazy:
Tento článek smí být používán libovolně, za předpokladu, že nebude modifikován a že
takto
bude učiněno se zmínkou o autorovi a odkazem na stránku
http://jt.sf.cz, odkud by měla být dostupná aktuální verse
tohoto
článku.
Snažím se, aby informace zde uvedené byly pravdivé a pokud možno přesné, nicméně nenesu žádnou
odpovědnost za to, že tomu tak opravdu je, ani za jakékoli škody, které by někomu v důsledku
případných
špatných či nepřesných informací z tohoto článku mohly vzniknout.
Jakékoliv dotazy či připomínky mi můžete poslat mailem.
Zpět na stránku referátů a jiných výtvorů