Feltételes fordítás során a tényleges fordítást előfordítás előzi meg. Az előfordító a fordításkor fennálló körülményektől függően a megadott kód szövegéből egy előfordítói direktívákat már nem tartalmazó kódot állít elő, ez kerül azután lefordításra. A direktívák kis- és nagybetűre nem érzékenyek. A feltételes fordítás használatának tipikus esetei:
Egy általános rutin megírásakor fel tudunk készülni arra, hogy a kód különböző adatbázis-kezelő verziókban is ki tudja használni a nyelv új eszközeit az adott környezetben rendelkezésre álló verziótól függően.
Nyomkövetési kódot helyezhetünk el a programban, amit a feltételes fordítás segítségével csak fejlesztői környezetben használunk. Éles környezetben ez a kód nem kerül lefordításra, nem csökken a teljesítmény, még egy feltétel vizsgálatának erejéig sem.
Az előfordítói szerkezetekben használható kifejezések speciálisan csak fordítási időben kiértékelhető BOOLEAN, PLS_INTEGER és VARCHAR2 típusú kifejezések lehetnek. Ezek jelölésére a formális leírásban rövidítve rendre a bkf, pkf, vkf nemterminálisokat használjuk.
bkf:
{TRUE | FALSE | NULL |
bkf hasonlító_operátor bkf |
pkf hasonlító_operátor pkf |
NOT bkf | bkf AND bkf | bkf OR bkf |
{bkf|pkf|vkf} IS [NOT] NULL |
csomagbeli_boolean_statikus_nevesített_konstans |
boolean_értékdirektíva}
pkf:
{pls_integer_literál | NULL |
csomagbeli_pls_integer_statikus_nevesített_konstans |
pls_integer_értékdirektíva}
vkf:
{char_literál | NULL |
TO_CHAR(pkf) | TO_CHAR(pkf, vkf, vkf) |
{pkf|vkf} || {pkf|vkf} |
varchar2_értékdirektíva}
A használni kívánt csomagbeli nevesített konstansokat CONSTANT kulcsszóval kell a csomag specifikációjában deklarálni, típusuk BOOLEAN vagy PLS_INTEGER lehet, kezdőértékként pedig megfelelő típusú fenti konstanskifejezés használható. Az ilyen nevesített konstansok hivatkozása csomag.név formájú, $ jel nélkül. Az értékdirektívák alakja:
$$azonosító
Az értékdirektívák a PLSQL_CCFLAGS paraméterből kapnak értéket. A paraméterben vesszővel elválasztva több értéket is megadhatunk azonosító:érték formában. Az érték BOOLEAN vagy PLS_INTEGER literál vagy NULL lehet. Ha a direktíva a PLSQL_CCFLAGS paraméterben nem szereplő azonosítóra hivatkozik, akkor értéke NULL lesz PLW-6003 figyelmeztetés mellett.
Ha a PLSQL_CCFLAGS paraméterben nincsenek explicit módon megadva, akkor a következő azonosítók speciális jelentéssel bírnak egy értékdirektívában:
A nevükkel lekérdezhetők a fordító működését szabályozó inicializációs paraméterek értékei (például $$PLSQL_CCFLAGS, $$PLSQL_OPTIMIZE_LEVEL stb.).
$$PLSQL_LINE értéke a kódsor sorszáma a programegységen belül.
$$PLSQL_UNIT értéke a forrás programegységének neve, névtelen blokk esetén NULL.
Az elágaztató direktíva formája:
$IF bkf $THEN kód
[ $ELSIF bkf $THEN kód ]…
[ $ELSE kód ]
$END
A szemantika megegyezik az IF…THEN utasításéval. Használható még a hibadirektíva, amely kiértékelése PLS-00179 fordítási idejű hibát generál:
$ERROR vkf $END
1. példa
ALTER SESSION SET PLSQL_CCFLAGS='debug:2';
CREATE OR REPLACE PROCEDURE proc_preproc
IS
BEGIN
$IF $$debug = 1 $THEN
DBMS_OUTPUT.PUT_LINE('Van DEBUG');
$ELSIF $$debug = 0 $THEN
DBMS_OUTPUT.PUT_LINE('Nincs DEBUG');
$ELSIF $$debug IS NOT NULL $THEN
$ERROR 'Érvénytelen DEBUG beállítás: ' ||
'PLSQL_CCFLGAS=' || $$PLSQL_CCFLAGS $END
$END
DBMS_OUTPUT.PUT_LINE('Kód');
END proc_preproc;
/
SHOW ERRORS;
/*
Figyelmeztetés: Az eljárás létrehozása fordítási hibákkal fejeződött be.
Hibák PROCEDURE PROC_PREPROC:
LINE/COL ERROR
-------- -----------------------------------------------------------------
9/5 PLS-00179: $ERROR: Érvénytelen DEBUG beállítás:
PLSQL_CCFLGAS=debug:2
*/
Az előfordító elérhető programból is a DBMS_PREPROCESSOR csomagon keresztül. Lehetőségünk van szöveggel adott vagy már tárolt kód előfordítására. Az előfordított kód lekérdezésére szolgál a túlterhelt GET_POST_PROCESSED_SOURCE függvény. A szintén túlterhelt PRINT_POST_PROCESSED_SOURCE az előfordított kódot írja a szerverkimenetre. Tárolt kód esetén akkor is működnek az eljárások, ha a kód utolsó fordítása nem volt sikeres fordítási hiba miatt, ilyenkor azonban az előfordító csak a hiba helyéig alakítja át a kódot, akkor is, ha a fordítási hibát nem hibadirektíva váltotta ki.
2. példa
-- Lefordítjuk sikeresen az eljárást, hogy szép kódot lássunk majd.
ALTER PROCEDURE proc_preproc COMPILE PLSQL_CCFLAGS='debug:1';
SET SERVEROUTPUT ON FORMAT WRAPPED;
BEGIN
DBMS_PREPROCESSOR.PRINT_POST_PROCESSED_SOURCE(
object_type => 'PROCEDURE'
, schema_name => 'PLSQL'
, object_name => 'PROC_PREPROC'
);
END;
/
/*
Az eljárás módosítva.
PROCEDURE proc_preproc
IS
BEGIN
DBMS_OUTPUT.PUT_LINE('Van DEBUG');
DBMS_OUTPUT.PUT_LINE('Kód');
END proc_preproc;
A PL/SQL eljárás sikeresen befejeződött.
*/
Ha az előfordítás előtti eredeti kód hivatkozik csomagbeli nevesített konstansra, a kód és a csomag specifikációja között függőség alakul ki, még akkor is ha az előfordítás utánikód már nem hivatkozik a csomagra. Egy hivatkozott programegység újrafordítása a függőprogramegységek teljes újrafordítását vonja maga után, beleértve az esetleges előfordításokat is.
3. példa
ALTER SESSION SET PLSQL_CCFLAGS='konstansom_erteke:TRUE';
CREATE OR REPLACE package pack_konstansok
IS
c_Konstans CONSTANT BOOLEAN := $$konstansom_erteke;
END;
/
CREATE OR REPLACE PROCEDURE proc_preproc_pack
IS
BEGIN
$IF pack_konstansok.c_Konstans $THEN
DBMS_OUTPUT.PUT_LINE('pack_konstansok.c_konstans TRUE');
$ELSE
DBMS_OUTPUT.PUT_LINE('pack_konstansok.c_konstans FALSE');
$END
END proc_preproc_pack;
/
SET SERVEROUTPUT ON FORMAT WRAPPED;
EXEC proc_preproc_pack;
-- pack_konstansok.c_konstans TRUE
-- A csomag explicit újrafordítása az eljárást érvényteleníti
ALTER PACKAGE pack_konstansok COMPILE
PLSQL_CCFLAGS='konstansom_erteke:FALSE';
-- Most fog az eljárás újrafordulni automatikusan
EXEC proc_preproc_pack;
-- pack_konstansok.c_konstans FALSE
Az adatbázis-kezelő verziója lekérdezhető a DBMS_DB_VERSION csomag PLS_INTEGER típusú VERSION és RELEASE nevesített konstansaival. A csomagban további nevesített konstansok is megtalálhatók (lásd [18]).
Az előfordítói direktívák használatára vonatkozóan a következő szabályok érvényesek:
Nem befolyásolhatják tárolt adatbázistípusok szerkezetét, ezért nem használhatók objektumtípus specifikációjában és sémában tárolt kollekciótípusok megadásakor.
Használhatók a paraméter nélküli programegységekben az IS/AS kulcsszó után.
Használhatók a paraméterrel rendelkező tárolt függvényben és eljárásban a formálisparaméter-listát nyitó zárójel után.
Használhatók triggerekben és névtelen blokkokban közvetlenül a kezdő DECLARE vagy BEGIN után.
Környezeti gazdaváltozó helykijelölője nem szerepelhet elágaztató direktíván belül. Ez névtelen blokkban fordulhatna elő.