YOU ARE DOWNLOADING DOCUMENT

Please tick the box to continue:

Transcript
Page 1: Oracle PL/SQL - Creative Conditional Compilation

SAGE Computing ServicesCustomised Oracle Training Workshops and

Consulting

Creative Conditional Compilation … and “raising the bar” with your PL/SQL

Scott WesleySystems Consultant

Page 2: Oracle PL/SQL - Creative Conditional Compilation
Page 3: Oracle PL/SQL - Creative Conditional Compilation

The example everybody’s seen…FUNCTION qty_booked(p_resource IN VARCHAR2 ,p_date IN DATE) RETURN NUMBER$IF dbms_db_version.ver_le_10 $THEN $ELSE RESULT_CACHE $END IS li_total PLS_INTEGER := 0;BEGIN SELECT SUM(b.qty) INTO li_total FROM bookings b, events e WHERE p_date BETWEEN e.start_date AND e.end_date AND b.resource = p_resource; RETURN li_totalEND qty_booked;

Page 4: Oracle PL/SQL - Creative Conditional Compilation

The example everybody’s seen…FUNCTION qty_booked(p_resource IN VARCHAR2FUNCTION qty_booked(p_resource IN VARCHAR2 ,p_date IN DATE) ,p_date IN DATE) RETURN NUMBERRETURN NUMBER$IF dbms_db_version.ver_le_10 $THEN $ELSE RESULT_CACHE $END ISIS li_total PLS_INTEGER := 0;li_total PLS_INTEGER := 0;BEGINBEGIN SELECT SUM(b.qty)SELECT SUM(b.qty) INTO li_totalINTO li_total FROM bookings b, events eFROM bookings b, events e WHERE p_date BETWEEN e.start_date AND e.end_dateWHERE p_date BETWEEN e.start_date AND e.end_date AND b.resource = p_resource;AND b.resource = p_resource; RETURN li_totalRETURN li_totalEND qty_booked;END qty_booked;

Page 5: Oracle PL/SQL - Creative Conditional Compilation

• PL/SQL User’s Guide & Reference10g Release 2– Fundamentals of the PL/SQL Language

• Conditional Compilation

Page 6: Oracle PL/SQL - Creative Conditional Compilation

Availability

• 11g• 10g Release 2

– Enabled out of the box

• 10.1.0.4 – Once patched, enabled by default– Disable using “_parameter”

• 9.2.0.6 – Once patched, disabled by default– Enable using “_parameter”

Page 7: Oracle PL/SQL - Creative Conditional Compilation

Catch 22

INDICES OF

Page 8: Oracle PL/SQL - Creative Conditional Compilation

Catch 22

ConditionalCompilation

Patch

INDICES OF

Page 9: Oracle PL/SQL - Creative Conditional Compilation

Facilitates removal of unnecessary code at compile time

PerformanceReadability

Accuracy Testing

It's cool!

Page 10: Oracle PL/SQL - Creative Conditional Compilation

Selection Directives

$IF boolean_static_expression $THEN text

[ $ELSIF boolean_static_expression $THEN text ]

[ $ELSE text ]

$ENDInquiry Directives

DBMS_OUTPUT.PUT_LINE($$PLSQL_LINE);

ALTER SESSION SET PLSQL_CCFLAGS='max_sentence:100';IF sentence > $$max_sentence THEN

Error Directives

$IF $$PLSQL_OPTIMIZE_LEVEL != 2

$THEN

$ERROR 'intensive_program must be compiled with maximum optimisation'

$END

$END

Semantics

Page 11: Oracle PL/SQL - Creative Conditional Compilation

First demo

cc1acc1bcc1ccc1d

Page 12: Oracle PL/SQL - Creative Conditional Compilation

Inquiry Directives

Page 13: Oracle PL/SQL - Creative Conditional Compilation

<< anon >>BEGIN DBMS_OUTPUT.PUT_LINE('Unit:'||$$PLSQL_UNIT); DBMS_OUTPUT.PUT_LINE('Line:'||$$PLSQL_LINE);END anon;/

Unit: Line:4

Page 14: Oracle PL/SQL - Creative Conditional Compilation

> CREATE OR REPLACE PROCEDURE sw_test ISBEGIN DBMS_OUTPUT.PUT_LINE('Unit:'||$$PLSQL_UNIT); DBMS_OUTPUT.PUT_LINE('Line:'||$$PLSQL_LINE);END sw_test;/

Procedure created.

> exec sw_test

Unit:SW_TESTLine:4

Page 15: Oracle PL/SQL - Creative Conditional Compilation

ALTER SESSION SET PLSQL_CCFLAGS = 'max_sentence:100';

Session altered.

Page 16: Oracle PL/SQL - Creative Conditional Compilation

> BEGIN

IF p_sentence > $$max_sentence THEN

DBMS_OUTPUT.PUT_LINE('Parole Available');

ELSE

DBMS_OUTPUT.PUT_LINE('Life');

END IF;

END;

/

Life

Page 17: Oracle PL/SQL - Creative Conditional Compilation

ALTER SYSTEM SET PLSQL_CCFLAGS =

'VARCHAR2_SIZE:100, DEF_APP_ERR:-20001';

DECLARE

lc_variable_chr VARCHAR2($$VARCHAR2_SIZE);

e_def_app_err EXCEPTION;

PRAGMA EXCEPTION_INIT (e_def_app_err, $$DEF_APP_ERR);

BEGIN

--> rest of your code

END anon;

/

Page 18: Oracle PL/SQL - Creative Conditional Compilation

Reuse Settings

Page 19: Oracle PL/SQL - Creative Conditional Compilation

ALTER SESSION SET PLSQL_CCFLAGS = 'MY_PI:314';

CREATE OR REPLACE PROCEDURE universe_alpha IS

BEGIN

DBMS_OUTPUT.PUT_LINE('Alpha pi = '||$$my_pi/100);

END;

CREATE OR REPLACE PROCEDURE universe_gamma IS

BEGIN

DBMS_OUTPUT.PUT_LINE('Gamma pi = '||$$my_pi/100);

END;

CREATE OR REPLACE PROCEDURE universe_oz IS

BEGIN

DBMS_OUTPUT.PUT_LINE('Oz pi = '||$$my_pi/100);

END;ALTER PROCEDURE universe_alpha COMPILE

PLSQL_CCFLAGS = 'MY_PI:289'

REUSE SETTINGS; ALTER PROCEDURE universe_gamma COMPILE

PLSQL_CCFLAGS = 'MY_PI:423'

REUSE SETTINGS;

> BEGIN

universe_alpha;

universe_gamma;

universe_oz;

END;

/

Alpha pi = 2.89

Gamma pi = 4.23

Oz pi = 3.14

Page 20: Oracle PL/SQL - Creative Conditional Compilation

Some actual examples?

Page 21: Oracle PL/SQL - Creative Conditional Compilation

Using new version code today

$IF dbms_db_version.ver_le_10 $THEN

-- version 10 and earlier code

$ELSIF dbms_db_version.ver_le_11 $THEN

-- version 11 code

$ELSE

-- version 12 and later code

$END

Page 22: Oracle PL/SQL - Creative Conditional Compilation

10.1 vs 10.2 dbms_output

Page 23: Oracle PL/SQL - Creative Conditional Compilation

CREATE OR REPLACE PROCEDURE sw_debug (p_text IN VARCHAR2) IS

$IF $$sw_debug_on $THEN l_text VARCHAR2(32767); $ENDBEGIN $IF $$sw_debug_on $THEN -- Let’s provide debugging info $IF dbms_db_version.ver_le_10_1 $THEN -- We have to truncate for <= 10.1 l_text := SUBSTR(p_text, 1 ,200); $ELSE l_text := p_text; $END DBMS_OUTPUT.PUT_LINE(p_text); $ELSE -- No debugging NULL; $ENDEND sw_debug;

Page 24: Oracle PL/SQL - Creative Conditional Compilation

CREATE OR REPLACE PROCEDURE sw_debug (p_text IN CREATE OR REPLACE PROCEDURE sw_debug (p_text IN VARCHAR2) ISVARCHAR2) IS

$IF $$sw_debug_on $THEN l_text VARCHAR2(32767); $ENDBEGINBEGIN $IF $$sw_debug_on $THEN -- Let’s provide debugging info $IF dbms_db_version.ver_le_10_1 $THEN -- We have to truncate for <= 10.1 l_text := SUBSTR(p_text, 1 ,200); $ELSE l_text := p_text; $END DBMS_OUTPUT.PUT_LINE(p_text); $ELSE$ELSE -- No debugging-- No debugging NULL;NULL; $END$ENDEND sw_debug;END sw_debug;

Page 25: Oracle PL/SQL - Creative Conditional Compilation

CREATE OR REPLACE PROCEDURE sw_debug (p_text IN CREATE OR REPLACE PROCEDURE sw_debug (p_text IN VARCHAR2) ISVARCHAR2) IS

$IF $$sw_debug_on $THEN$IF $$sw_debug_on $THEN l_text VARCHAR2(32767);l_text VARCHAR2(32767); $END$ENDBEGINBEGIN $IF $$sw_debug_on $THEN$IF $$sw_debug_on $THEN -- Let’s provide debugging info-- Let’s provide debugging info $IF dbms_db_version.ver_le_10_1 $THEN -- We have to truncate for <= 10.1 l_text := SUBSTR(p_text, 1 ,255); $ELSE$ELSE l_text := p_text;l_text := p_text; $END$END DBMS_OUTPUT.PUT_LINE(p_text);DBMS_OUTPUT.PUT_LINE(p_text); $ELSE$ELSE -- No debugging-- No debugging NULL;NULL; $END$ENDEND sw_debug;END sw_debug;

Page 26: Oracle PL/SQL - Creative Conditional Compilation

10g vs 11g result_cache

FUNCTION quantity_ordered

(p_item_id IN items.item_id%TYPE)

RETURN NUMBER

$IF dbms_version.ver_le_10 $THEN

-- nothing

$ELSE

RESULT_CACHE

$END

IS

BEGIN

...

Page 27: Oracle PL/SQL - Creative Conditional Compilation

9i vs 10g Bulk Insert

Page 28: Oracle PL/SQL - Creative Conditional Compilation

CREATE OR REPLACE PACKAGE BODY sw_bulk_insert IS PROCEDURE sw_insert (sw_tab IN t_sw_tab) IS BEGIN $IF dbms_db_version.ver_le_9 $THEN DECLARE l_dense t_sw_tab; ln_index PLS_INTEGER := sw_tab.FIRST; BEGIN << dense_loop >> WHILE (l_index IS NOT NULL) LOOP l_dense(l_dense.COUNT + 1) := sw_tab(l_index); l_index := sw_tab.NEXT(l_index); END LOOP dense_loop;

FORALL i IN 1..l_dense.COUNT INSERT INTO sw_table VALUES l_dense(i); END; $ELSE FORALL i IN INDICES OF sw_tab INSERT INTO sw_table VALUES sw_tab(i); $END END sw_insert;END sw_bulk_insert;

Page 29: Oracle PL/SQL - Creative Conditional Compilation

CREATE OR REPLACE PACKAGE BODY sw_bulk_insert IS PROCEDURE sw_insert (sw_tab IN t_sw_tab) IS BEGIN $IF dbms_db_version.ver_le_9 $THEN DECLARE l_dense t_sw_tab; ln_index PLS_INTEGER := sw_tab.FIRST; BEGIN << dense_loop >> WHILE (l_index IS NOT NULL) LOOP l_dense(l_dense.COUNT + 1) := sw_tab(l_index); l_index := sw_tab.NEXT(l_index); END LOOP dense_loop;

FORALL i IN 1..l_dense.COUNT INSERT INTO sw_table VALUES l_dense(i); END; $ELSE$ELSE FORALL i IN INDICES OF sw_tabFORALL i IN INDICES OF sw_tab INSERT INTO sw_tableINSERT INTO sw_table VALUES sw_tab(i);VALUES sw_tab(i); $END$END END sw_insert;END sw_bulk_insert;

Page 30: Oracle PL/SQL - Creative Conditional Compilation

CREATE OR REPLACE PACKAGE BODY sw_bulk_insert IS PROCEDURE sw_insert (sw_tab IN t_sw_tab) IS BEGIN $IF dbms_db_version.ver_le_9 $THEN$IF dbms_db_version.ver_le_9 $THEN DECLAREDECLARE l_dense t_sw_tab;l_dense t_sw_tab; ln_index PLS_INTEGER := sw_tab.FIRST;ln_index PLS_INTEGER := sw_tab.FIRST; BEGINBEGIN << dense_loop >><< dense_loop >> WHILE (l_index IS NOT NULL) LOOPWHILE (l_index IS NOT NULL) LOOP l_dense(l_dense.COUNT + 1) := sw_tab(l_index);l_dense(l_dense.COUNT + 1) := sw_tab(l_index); l_index := sw_tab.NEXT(l_index);l_index := sw_tab.NEXT(l_index); END LOOP dense_loop;END LOOP dense_loop;

FORALL i IN 1..l_dense.COUNTFORALL i IN 1..l_dense.COUNT INSERT INTO sw_table VALUES l_dense(i);INSERT INTO sw_table VALUES l_dense(i); END;END; $ELSE FORALL i IN INDICES OF sw_tab INSERT INTO sw_table VALUES sw_tab(i); $END END sw_insert;END sw_bulk_insert;

Page 31: Oracle PL/SQL - Creative Conditional Compilation

Paradigm Examples

Page 32: Oracle PL/SQL - Creative Conditional Compilation

Latent debugging code

Page 33: Oracle PL/SQL - Creative Conditional Compilation

CREATE OR REPLACE PACKAGE pkg_debug IS

debug_flag CONSTANT BOOLEAN := FALSE;

END pkg_debug;

/

CREATE OR REPLACE PROCEDURE sw_proc IS

BEGIN

$IF pkg_debug.debug_flag $THEN

dbms_output.put_line ('Debug=T');

$ELSE

dbms_output.put_line ('Debug=F');

$END

END sw_proc;

/

Page 34: Oracle PL/SQL - Creative Conditional Compilation

Assertions

Page 35: Oracle PL/SQL - Creative Conditional Compilation

“Assertions should be used to document logically impossible situations —

Development tool

Testing Aid

In-line Documentation

if the ‘impossible’ occurs, then something fundamental is clearly wrong.

This is distinct from error handling.”

Run-time Cost

Page 36: Oracle PL/SQL - Creative Conditional Compilation

Latent Assertions

Page 37: Oracle PL/SQL - Creative Conditional Compilation

“The removal of assertions from production code is almost always done automatically.

It usually is done via conditional compilation.”

Page 38: Oracle PL/SQL - Creative Conditional Compilation

$IF $$asserting OR CC_assertion.asserting$THEN IF p_param != c_pi*r*r THEN raise_application_error(.. END IF;$END

-- individual program unit-- entire application

Page 39: Oracle PL/SQL - Creative Conditional Compilation

Testing subprograms only in package body

Page 40: Oracle PL/SQL - Creative Conditional Compilation

CREATE PACKAGE universe IS

PROCEDURE create_sun;

PROCEDURE create_planets;

-- CC test procedure

PROCEDURE test_orbit;

END universe;

CREATE PACKAGE BODY universe IS

-- Private

PROCEDURE orbit IS .. END;

-- Public

PROCEDURE create_sun IS .. END;

PROCEDURE create_planets IS .. END;

-- Testers

PROCEDURE test_orbit IS

BEGIN

$IF $$testing $THEN

orbit;

$ELSE

RAISE program_error;

$END

END test_orbit;

END universe;

Page 41: Oracle PL/SQL - Creative Conditional Compilation

CREATE PACKAGE universe IS

PROCEDURE create_sun;

PROCEDURE create_planets;

-- CC test sequence

PROCEDURE test_run;

END universe;

CREATE PACKAGE BODY universe IS

-- Private

PROCEDURE orbit IS .. END;

-- Public

PROCEDURE create_sun IS .. END;

PROCEDURE create_planets IS .. END;

-- Test sequence

PROCEDURE test_run IS

BEGIN

$IF $$testing $THEN

create_sun;

create_planets;

orbit;

$ELSE

RAISE program_error;

$END

END test_run;

END universe;

Page 42: Oracle PL/SQL - Creative Conditional Compilation

Mock objects

Page 43: Oracle PL/SQL - Creative Conditional Compilation

FUNCTION get_emp(p_emp_id IN emp.emp_id%TYPE)

RETURN t_emp IS

l_emp t_emp;

BEGIN

$IF $$mock_emp $THEN

l_emp.emp_name := 'Scott';

..

RETURN l_emp;

$ELSE

SELECT *

FROM emp

INTO l_emp

WHERE emp_id = p_emp_id;

RETURN l_emp;

$END

END get_emp;

Page 44: Oracle PL/SQL - Creative Conditional Compilation

Comparing competing implementationsduring prototyping

Page 45: Oracle PL/SQL - Creative Conditional Compilation

PROCEDURE xyz IS

$IF $$alternative = 1 $THEN

-- varray declaration

$$ELSIF $$alternative = 2 $THEN

-- nested table declaration

$END

BEGIN

$IF $$alternative = 1 $THEN

-- simple varray solution

$$ELSIF $$alternative = 2 $THEN

-- elegant nested table solution

$END

END xyz;

PROCEDURE xyz ISPROCEDURE xyz IS

$IF $$alternative = 1 $THEN$IF $$alternative = 1 $THEN

-- varray declaration -- varray declaration

$$ELSIF $$alternative = 2 $THEN$$ELSIF $$alternative = 2 $THEN

-- nested table declaration-- nested table declaration

$END$END

BEGINBEGIN

$IF $$alternative = 1 $THEN$IF $$alternative = 1 $THEN

-- simple varray solution -- simple varray solution

$$ELSIF $$alternative = 2 $THEN$$ELSIF $$alternative = 2 $THEN

-- elegant nested table solution-- elegant nested table solution

$END$END

END xyz;END xyz;

$IF $$alternative = 1 $THEN

-- first verbose solution that came to mind

$$ELSIF $$alternative = 2 $THEN

-- some crazy idea you came up with at 3am you need to try out

$END

Page 46: Oracle PL/SQL - Creative Conditional Compilation

Component Based Installation

Page 47: Oracle PL/SQL - Creative Conditional Compilation

PACKAGE BODY core ISPROCEDURE execute_component(p_choice IN VARCHAR2) ISBEGIN CASE p_choice -- Base is always installed. WHEN 'base' THEN base.main(); $IF CC_licence.cheap_installed $THEN WHEN 'cheap' THEN cheap.main(); $END ... $IF CC_licence.pricey_installed $THEN WHEN 'pricey' THEN pricey.main(); $END END CASE;EXCEPTION WHEN case_not_found THEN dbms_output.put_line('Component '||p_choice||' is

not installed.');END execute_component;END core;

Page 48: Oracle PL/SQL - Creative Conditional Compilation

Get It Right with the Error Directive

Page 49: Oracle PL/SQL - Creative Conditional Compilation

$IF $$PLSQL_OPTIMIZE_LEVEL != 2

$THEN

$ERROR 'intensive_program must be compiled with maximum optimisation'

$END

$END

Page 50: Oracle PL/SQL - Creative Conditional Compilation

BEGIN

...

/*

*

* Note to self: Must remember to finish this bit

*

*/

...

END;

Page 51: Oracle PL/SQL - Creative Conditional Compilation

BEGIN

...

-- Jacko: this doesn’t work, fix before moving to prod!

...

END;

Page 52: Oracle PL/SQL - Creative Conditional Compilation

1 CREATE PROCEDURE process_court_outcome IS

2 BEGIN

3 IF lr_victim.age > 18 THEN

4 send_to_prison(lr_victim);

5 ELSE

6 $ERROR

7 'Waiting for business to advise '||

8 $$PLSQL_UNIT||' line: '||$$PLSQL_LINE

9 $END

10 END IF;

11 END process_court_outcome;

12 /

Warning: Procedure created with compilation errors.

SQL> sho err

LINE/COL ERROR

-------- ----------------------------------------

6/6 PLS-00179: $ERROR: Waiting for business to

advise PROCESS_COURT_OUTCOME line: 8

Page 53: Oracle PL/SQL - Creative Conditional Compilation

Post-processed Source

Demo: cc2

Page 54: Oracle PL/SQL - Creative Conditional Compilation

Smaller, Faster Run-Time Code Is in Your Future

Page 55: Oracle PL/SQL - Creative Conditional Compilation

Good Practices

Page 56: Oracle PL/SQL - Creative Conditional Compilation

Inquiry directives have null values for normal behaviour

$IF $$cc_flag = 'x' $THEN cc_code;$END

Page 57: Oracle PL/SQL - Creative Conditional Compilation

Choose restriction type carefully

$IF $$debug_onOR module_y.cc_debug $THEN sw_debug('Error'); $END

Page 58: Oracle PL/SQL - Creative Conditional Compilation

but there’s always this...

Page 59: Oracle PL/SQL - Creative Conditional Compilation

SQL> define debug=/*

begin

&debug

select 'conditionally'

from dual;

-- */

select 'always'

from dual;

end;

/

Page 60: Oracle PL/SQL - Creative Conditional Compilation

SAGE Computing ServicesCustomised Oracle Training Workshops and

Consulting

Questions and Answers?

Presentations are available from our website:http://www.sagecomputing.com.au

[email protected]@sagecomputing.com.auhttp://triangle-circle-square.blogspot.com


Related Documents