Feltételes fordítás

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:

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:

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: