Overloading in PL/SQL

venerdì 6 marzo 2009 alle 06:33 | Pubblicato su PL/SQL | 6 commenti

Ieri ho trovato un problema che secondo me sarebbe stato bene nel blog “Annals of Oracle’s Improbable Errors“, infatti l’ho cercato li, ma no l’ho trovato.

Un programmatore aveva l’esigenza di avere una funzione PL/SQL per il calcolo dell’hash con l’algoritmo MD5; per conto suo aveva già effettuato una ricerca sul web ed era arrivato al package DBMS_OBFUSCATION_TOOLKIT, con un esemprio di funzione che però gli dava un errore che però non ha saputo mostrarmi (ecco perché non amo certi strumenti grafici). Siccome l’esigenza era di utilizzare questa funzione su 9iR2 ho fatto una indagine, anche perché confesso di non aver mai utilizzato ne tale funzione ne tale package, però mi sembrava di ricordare che ci fossero (come dovrebbe essere normale) differenze tra la versione 9 e la 10. Infatti, sulla 10gR2 per questo scopo esiste la funzione HASH del packge DBMS_CRYPTO. Sulla 9iR2 tale package non esiste, e nella documentazione del package DBMS_OBFUSCATION_TOOLKIT non compaiono funzioni MD5. In realtà, facendo un desc del package da SQL*Plus, si ha una sorpresa:

SVILUPPO30@perseo92 > desc dbms_obfuscation_toolkit

PROCEDURE MD5
Argument Name                  Type                    In/Out Default?
—————————— ———————– —— ——–
INPUT                          RAW                     IN
CHECKSUM                       RAW                     OUT
FUNCTION MD5 RETURNS RAW(16)
Argument Name                  Type                    In/Out Default?
—————————— ———————– —— ——–
INPUT                          RAW                     IN
PROCEDURE MD5
Argument Name                  Type                    In/Out Default?
—————————— ———————– —— ——–
INPUT_STRING                   VARCHAR2                IN
CHECKSUM_STRING                VARCHAR2                OUT
FUNCTION MD5 RETURNS VARCHAR2(16)
Argument Name                  Type                    In/Out Default?
—————————— ———————– —— ——–
INPUT_STRING                   VARCHAR2                IN

Ho tagliato la parte che non mi interessa. Come si vede compaiono delle funzioni MD5. Il problema è che provando la funzione si ha un errrore:


SVILUPPO30@perseo92 > select dbms_obfuscation_toolkit.md5('cristian') from dual;
select dbms_obfuscation_toolkit.md5('cristian') from dual
       *
ERROR at line 1:
ORA-06553: PLS-307: too many declarations of 'MD5' match this call

Una ricerca sul metalink mi ha portato alla nota 734764.1 la quale riporta:

error is because there are 2 DESEncrypt functions and the SQL parser does not know which one to call

In questo caso parla della funzione DESEncrypt che evidentemente soffre dello stesso problema.

Utilizando la versione procedurale della funzione MD5 si riesce ad aggirare il problema. Il punto è che ho notato che l’overloading di funzioni PL/SQL con paremetri VARCHAR2 o RAW non funziona, ovvero se ho due funzioni uguali, una con un parametro di input di tipo RAW e l’altra con una parametro di input di tipo VARCHAR2, Oracle non è in grado di “disambiguare” e identificare la corretta definizione della funzione e ritorna l’errore riportato. Ho avuto la prova di questa facendo un banalissimo test:


create or replace package test_pkg as
function a (i_p number) return number;
function a (a_p varchar2) return number;
function a (r_p raw) return number;
end;
/
create or replace package body test_pkg as
function a (i_p number) return number is
l_var number;
begin
l_var:=1;
return l_var;
end;
function a (a_p varchar2) return number is
l_var number;
begin
l_var:=2;
return l_var;
end;
function a (r_p raw) return number is
l_var number;
begin
l_var:=3;
return l_var;
end;
end;
/

SVILUPPO30@perseo92 >  select test_pkg.a(8) from  dual;

TEST_PKG.A(8)
-------------
1

SVILUPPO30@perseo92 >  select test_pkg.a('11') from dual;
select test_pkg.a('11') from dual
*
ERROR at line 1:
ORA-06553: PLS-307: too many declarations of 'A' match this call

Ho provato anche con la funzione CAST o il package UTL_RAW ma non ho trovato un modo per aggirare il problema. Va detto poi che lo stesso test l’ho fatto su una istanza 10.2.0.4 e il problema persiste

6 commenti »

RSS feed for comments on this post. TrackBack URI

  1. Il PL/SQL era un ottimo linguaggio 10 anni fa.
    Oggi è ancora ottimo, ma mostra tutti i difetti della sua età.

    La mancanza di un vero supporto per la programmazione ad oggetti, l’assenza di strumenti per la gestione di grandi progetti e, appunto, il mancato supporto a caratteristiche ormai necessario come l’overloading lo rendono difficile da usare in modo massivo, anche nel suo ambito naturale di utilizzo (il batch processing).

    Anche da questo punto di vista oracle rischia di farsi superare da microsoft.

  2. Nel libro di Tom Kyte “Expert One-on-One Oracle” c’è un esempio dell’uso del crypting MD5 mediante il package DBMS_OBFUSCATION_TOOLKIT (è su Oracle 8.1.7 ma credo che non faccia differenza). Non l’ho sinceramente mai provato, né approfondito, ma credo che possa esserti utile, a te serve, dargli un’occhiata.

  3. Hai ragione Roberto, qui in ufficio ho il CD con la versione elettronica del libro inclusa nell’ultimo libro di Thomas Kyte e oltre all’esempio Kyte parla dello stesso problema dell’overloading.

  4. Interessante!
    In effetti dando un aiutino al parser anche la versione funzionale funziona (bella frase!):

    declare
    c varchar2(16) := ‘cristian’;
    x varchar2(16);
    begin
    dbms_obfuscation_toolkit.md5(input_string => c, checksum_string => x);
    dbms_output.put_line(x);
    x := dbms_obfuscation_toolkit.md5(input_string => c);
    dbms_output.put_line(x);
    end;
    /

    La questione come fai notare tu è che il parser non sente la differenza tra RAW e VARCHAR2, a meno che non si usi il metodo per chiamata nominale dei parametri, cosa che peraltro non è possibile fare da SQL, ma solo da PL/SQL. A quel punto occorrerebbe farsi una funzione wrapper per conto proprio che al suo interno chiama la MD5 come mostrato sopra.

    Comunque mi ero già occupato del PLS-00307, ma mi dai lo spunto per segnalare questo curioso problema che affligge la combinazione RAW/VARCHAR2.

    Ciao!
    Flavio

  5. Tom Kyte ne parla al seguente link:

    http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:4447619263064

    certo che dbms_obfuscation_toolkit non risulterebbe essere il package Oracle maggiormente apprezzato da Tom😉


Lascia un commento

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione / Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione / Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione / Modifica )

Google+ photo

Stai commentando usando il tuo account Google+. Chiudi sessione / Modifica )

Connessione a %s...

Crea un sito o un blog gratuitamente presso WordPress.com.
Entries e commenti feeds.

%d blogger cliccano Mi Piace per questo: