05.11.2015 Views

Apress.Expert.Oracle.Database.Architecture.9i.and.10g.Programming.Techniques.and.Solutions.Sep.2005

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

CHAPTER 12 ■ DATATYPES 517<br />

Note that on line 2, we specify AUTHID CURRENT_USER. This makes the package run as the<br />

invoker, with all roles <strong>and</strong> grants in place. This is important for two reasons. First, we’d like the<br />

database security to not be subverted—this package will only return substrings of columns we<br />

(the invoker) are allowed to see. Second, we’d like to install this package once in the database<br />

<strong>and</strong> have its functionality available for all to use; using invoker rights allows us to do that. If we<br />

used the default security model of PL/SQL—definer rights—the package would run with the<br />

privileges of the owner of the package, meaning it would only be able to see data the owner of<br />

the package could see, which may not include the set of data the invoker is allowed to see.<br />

The concept behind the function SUBSTR_OF is to take a query that selects at most one row<br />

<strong>and</strong> one column: the LONG value we are interested in. SUBSTR_OF will parse that query if needed,<br />

bind any inputs to it, <strong>and</strong> fetch the results programmatically, returning the necessary piece of<br />

the LONG value.<br />

The package body, the implementation, begins with two global variables. The G_CURSOR<br />

variable holds a persistent cursor open for the duration of our session. This is to avoid having<br />

to repeatedly open <strong>and</strong> close the cursor <strong>and</strong> to avoid parsing SQL more than we need to. The<br />

second global variable, G_QUERY, is used to remember the text of the last SQL query we’ve<br />

parsed in this package. As long as the query remains constant, we’ll just parse it once. So, even<br />

if we query 5,000 rows in a query, as long as the SQL query we pass to this function doesn’t<br />

change, we’ll have only one parse call:<br />

ops$tkyte@ORA10G> create or replace package body long_help<br />

2 as<br />

3<br />

4 g_cursor number := dbms_sql.open_cursor;<br />

5 g_query varchar2(32765);<br />

6<br />

Next in this package is a private procedure, BIND_VARIABLE, that we’ll use to bind inputs<br />

passed to us by the caller. We implemented this as a separate private procedure only to make<br />

life easier; we want to bind only when the input name is NOT NULL. Rather than perform that<br />

check four times in the code for each input parameter, we do it once in this procedure:<br />

7 procedure bind_variable( p_name in varchar2, p_value in varchar2 )<br />

8 is<br />

9 begin<br />

10 if ( p_name is not null )<br />

11 then<br />

12 dbms_sql.bind_variable( g_cursor, p_name, p_value );<br />

13 end if;<br />

14 end;<br />

15<br />

Next is the actual implementation of SUBSTR_OF in the package body. This routine begins<br />

with a function declaration from the package specification <strong>and</strong> the declaration for some local<br />

variables. L_BUFFER will be used to return the value, <strong>and</strong> L_BUFFER_LEN will be used to hold the<br />

length returned by an <strong>Oracle</strong>-supplied function:

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!