310 likes | 452 Views
Distribuirane i objektne baze podataka vežbe, školska 2009/10. Univerzitet u Beogradu, Matematički fakultet Biljana Stojanović. Objektno-relacioni model u sistemu DB2 Transform funkcije i grupe. Čas 11. Transform funkcije i grupe.
E N D
Distribuirane i objektne baze podatakavežbe, školska 2009/10 Univerzitet u Beogradu, Matematički fakultet Biljana Stojanović januar 2010, Biljana Stojanović
Objektno-relacionimodel u sistemu DB2Transform funkcije i grupe Čas 11 januar 2010, Biljana Stojanović
Transform funkcije i grupe • Transform funkcije se koriste za razmenuvrednosti strukturnog tipa sa aplikacijama na matičnom programskom jeziku ili sa eksternim funkcijama i metodima. • Transform funkcije se obično javljaju u paru: • jedna FROM SQL transfrom funkcija (konvertuje objekat strukturnog tipa u tip koji može da se razmeni sa klijentskim programom ili eksternom funkcijom) i • jedna TO SQL transform funkcija (konstruiše objekat strukturnog tipa) • Logički par transform funkcija čini grupu. Ime transform grupe jednoznačno identifikuje par ovih funkcija za dati strukturni tip. Januar 2010, Biljana Stojanović
Naredba CREATE TRANSFORM identifikuje jednu ili više postojećih funkcija kao transform funkcije za dati strukturni tip. • Primer: • Imenuju se dve transform grupe za tip Adresa_t: CREATE TRANSFORM FOR Adresa_t func_group ( FROM SQL WITH FUNCTION addresstofunc, TO SQL WITH FUNCTION functoaddress ) client_group ( FROM SQL WITH FUNCTION stream_to_client, TO SQL WITH FUNCTION stream_from_client • Mogu naknadno da se dodaju transform grupe tako što se promeni definicija – ponovo se pozove naredba CREATE TRANSFORM sa dodatnim funkcijama. • DROP TRANSFORM – raskida se veza postojećih funkcija sa strukturnim tipom, tj. postojeće funkcije se ne koriste više kao transform funkcije za dati tip. Funkcije i dalje postoje. • Primer: DROP TRANSFORM func_group FOR Adresa_t; DROP TRANSFORM client_group FOR Adresa_t; Januar 2010, Biljana Stojanović
Imena transfrom grupa su nekvalifikovani identifikatori, dakle, nisu dodeljeni nijednoj shemi. • Imena grupa treba da oslikavaju njihovu namenu, bez obzira na imena strukturnih tipova ili logiku transform funkcija. • Primer: func_group ili object_func za bilo koju grupu • client_group ili program_group za grupe sa funkcijama za rad sa klijentima. • CREATE TRANSFORM FOR Adresa_t func_group (TO SQL WITH FUNCTION functoaddress, FROM SQL WITH FUNCTION addresstofunc ) ; • CREATE TRANSFORM FOR Polygon func_group (TO SQL WITH FUNCTION functopolygon, FROM SQL WITH FUNCTION polygontofunc ) ; U ovim primerima imena grupa za oba tipa su ista, iako tipovi koriste transform funkcije različite prirode. Ime transform grupe ne sme da počinje prefiksom ‘SYS’. Ova grupa je rezervisana od strane sistema. Januar 2010, Biljana Stojanović
Kada se definiše eksterni metod ili funkcija i nije specifikovano ime transform grupe, DB2 pokušava da koristi ime DB2_FUNCTION i pretpostavlja da je upravo to ime zadato kao ime grupe za dati tip. • Ako se ne zada ime grupe kada se preprocesira klijentski program koji koristi odgovarajući strukturni tip, DB2 pokušava da koristi ime DB2_PROGRAM i ponovo pretpostavlja da je to ime zadato kao ime grupe za dati tip. Januar 2010, Biljana Stojanović
Specifikacija transform grupa • Kada se definiše eksterna funkcija ili metod, specifikuje se transform grupa koja sadrži odgovarajuće transform funkcije. • Kada se vrši preprocesiranje i ugradnja paketa, takođe se specifikuje transform grupa kao opcija komande PRECOMPILE ili BIND (za statički SQL). Januar 2010, Biljana Stojanović
Specifikacija transform grupa za eksterne funkcije (rutine) • Funkcije pisane na SQL-u ne zahtevaju transform grupe, što nije slučaj sa eksternim funkcijama. CREATE FUNCTION stream_from_client (VARCHAR(150)) RETURNS Adresa_t ... TRANSFORM GROUP func_group EXTERNAL NAME ‘addressudf.adress_stream_from_client’ … CREATE METHOD distance(point) FOR Polygon RETURNS integer … TRANSFORM GROUP func_group; Januar 2010, Biljana Stojanović
Specifikacija transform grupa za statički SQL PRECOMPILE ... (ili BIND) TRANSFORM GROUP client_group • Specifikuje se statička transform grupa koja se koristi od strane statičkih SQL naredbi za razmenu vrednosti različitih tipova sa host-programima. • Ovakva transform grupa se ne primenjuje za razmenu parametara i rezultata sa eksternim funkcijama i metodama. Januar 2010, Biljana Stojanović
Upotreba transform funkcija sa klijentskim programima • Klijentska aplikacija ne može direktno da dobije ceo objekat strukturnog tipa iz baze, dok je moguće selektovati pojedinačne atribute. • Takođe, aplikacija obično ne umeće ceo objekat u bazu. • Za razmenu kompletnih objekata strukturnog tipa između servera i klijentske aplikacije ili eksterne funkcije, moraju da se napišu transform funkcije. • FROM SQL transform funkcija definiše kako DB2 konvertuje objekat strukturnog tipa u dobro definisan format koji omogućava pristup njegovom sadržaju (ili kako DB2 vrši bind out objekta). • TO SQL transfrom funkcija definiše kako DB2 vraća objekat koji treba da se sačuva u bazi (ili kako DB2 vrši bind in objekta). Januar 2010, Biljana Stojanović
Transform funkcije SELECT my_func(adresa) FROM Kadrovi; • my_func je eksterna funkcija koja uzima adresu kao ulazni parametar i modifikuje je. • 1. Prvo FROM SQL fja vrši razlaganje strukturnog tipa na uređenu listu njegovih atributa. Time eksterna funkcija dobija objekat kao listu parametara osnovnog tipa. U gornjem primeru najpre FROM SQL fja prihvata objekat (adresu) kao ulaz i vraća listu parametara VARCHAR, VARCHAR, VARCHAR, VARCHAR. Ovakav format objekta se onda prosleđuje funkciji my_func . Ako je funkcija pisana u C-u neophodno je pored 4 odvojena parametra proslediti i 4 odgovarajuća indikatora za null vrednosti parametara kao i null indikator za sam strukturni tip. Ako funkcija ima povratnu vrednost, treba proslediti null indikator i za tu vrednost. • 2. Spoljašnja fja prihvata razloženu adresu kao ulaz, vrši procesiranje i vraća atribute adrese kao izlaz. • 3. TO SQL fja prevodi listu parametara VARCHAR, VARCHAR, VARCHAR i VARCHAR koje je vratila spoljašnja funkcija u objekat tipa Adresa_t. Vrednosti atributa kreiranog objekta postavljaju se na vrednosti koje je vratila spoljašnja fja. Januar 2010, Biljana Stojanović
U slučaju da fja my_func() vraća vrednost strukturnog tipa, neophodna je još jedna transform fja, koja će transformisati rezultujuću vrednost kada se rutina koristi u SELECT naredbi. • Da bi se izbeglo kreiranje još jedne funkcije, može se koristiti SELECT naredba sa pristupnim metodima, kao na primer: select ime from Nastavnik where my_func(adresa)..grad LIKE ‘Beo%’ Januar 2010, Biljana Stojanović
Implementacija transform fja pomoću SQL korisničkih fja • -- funkcija vraca red od 4 kolone primitivnog tipa • -- sql funkcija (nije spoljasnja) • -- A.ulica je drugi nacin za poziv pristupnog metoda A..ulica(), obzirom da nema parametre CREATE FUNCTION addresstofunc (A Adresa_t) RETURNS ROW (ulica varchar(100), broj varchar(20), grad varchar(100), drzava varchar(100)) language sql return values (A..ulica(), A..broj(), A..grad(), A..drzava()) • -- poredak atributa u listi parametara nije bitan, ali sve funkcije koje pozivaju ovu TO SQL fju kako bi vratile • -- adrese moraju da koriste ovaj isti poredak CREATE FUNCTION functoaddress(ulica varchar(100), broj varchar(20), grad varchar(100), drzavavarchar(100)) RETURNS Adresa_t LANGUAGE SQL CONTAINS SQL RETURN Adresa_t()..ulica(ulica)..broj(broj)..grad(grad)..drzava(drzava) • -- DB2 ne moze da zna da li korisnik namerava da gornje fje koristi kao transform fje, sve dok se ne kreira • -- transform grupa koja ih sadrzi Januar 2010, Biljana Stojanović
Prosleđivanje parametara strukturnog tipa eksternim funkcijama • Ako se koristi PARAMETER STYLE SQL, pri pozivu eksterne funkcije moraju se proslediti: • parametri za sve atribute strukturnog tipa • po jedan null indikator za svaki IN/OUT/INOUT parametar u istom redosledu kao i parametri na koje se odnose • null indikator za sam strukturni tip • Dodatni parametri: • Sqlstate – vraća se pozivaocu kao indikator stanja • Ime fje – kvalifikovano ime fje (ulazni parametar) • Specifično ime fje (ulazni parametar) • Poruka za dijagnostiku – opcioni string koji se vraća pozivaocu (izlazni parametar) • Kao alternativa navođenja dodatnih parametara, može se koristiti makro SQLUDF_TRAIL_ARGS koji je definisan u zaglavlju sqludf.h. • Kada se u funkciji referiše na dodatne parametre, treba koristiti imena iz definicije makroa SQLUDF_TRAIL_ARGS: sqludf_sqlstate, sqludf_fname, sqludf_fspecname, sqludf_msgtext. Januar 2010, Biljana Stojanović
Primer 1 • Neka je kreirana sledeća eksterna funkcija: CREATE FUNCTION stream_to_client (Adresa_t) RETURNS VARCHAR(150) EXTERNAL NAME 'udfsrv!stream_to_client' SPECIFIC addrString LANGUAGE C TRANSFORM GROUP func_group DETERMINISTIC NO EXTERNAL ACTION NOT FENCED PARAMETER STYLE SQL Januar 2010, Biljana Stojanović
Odgovarajuće zaglavlje definicije funkcije ima sledeći oblik: void SQL_API_FN stream_to_client( /* parametri koji odgovaraju atributima strukt. tipa */ SQLUDF_VARCHAR *ulica SQLUDF_VARCHAR *broj, SQLUDF_VARCHAR *grad, SQLUDF_VARCHAR *drzava, /* izlazni parametar */ SQLUDF_VARCHAR *output, /* null indikatori za parametre atributa strukt. tipa SQLUDF_NULLIND *ulica_ind, SQLUDF_NULLIND *broj_ind, SQLUDF_NULLIND *grad_ind, SQLUDF_NULLIND *drzava_ind, /* null indikator za instancu strukt. tipa SQLUDF_NULLIND *adresa_ind, /* null indikator za izlazni parametar SQLUDF_NULLIND *out_ind, SQLUDF_TRAIL_ARGS) Januar 2010, Biljana Stojanović
Primer 2 • Pretpostavimo da spoljašnja funkcija prihvata dva parametra različitih strukturnih tipova st1 i st2 i vraća vrednost strukturnog tipa st3. CREATE FUNCTION myudf (int, st1, st2) RETURNS st3 • Atributi strukturnih tipova su redom: • st1: st1_att1 VARCHAR, st2_att2 INTEGER • st2 : st2_att1 VARCHAR, st2_att2 CHAR, st2_att3 INTEGER • st3: st3_att1 INTEGER, st3_att2CLOB Januar 2010, Biljana Stojanović
Odgovarajuće zaglavlje definicije funkcije ima sledeći oblik: void SQL_API_FN myudf( SQLUDF_INTEGER *INT, ⁄* Decomposed st1 input *⁄ SQLUDF_VARCHAR *st1_att1, SQLUDF_INTEGER *st1_att2, ⁄* Decomposed st2 input *⁄ SQLUDF_VARCHAR *st2_att1, SQLUDF_CHAR *st2_att2, SQLUDF_INTEGER *st2_att3, ⁄* Decomposed st3 output *⁄ SQLUDF_VARCHAR *st3_att1out, SQLUDF_CLOB *st3_att2out, ⁄* Null indicator of integer *⁄ SQLUDF_NULLIND *INT_ind, ⁄* Null indicators of st1 attributes and type *⁄ SQLUDF_NULLIND *st1_att1_ind, SQLUDF_NULLIND *st1_att2_ind, SQLUDF_NULLIND *st1_ind, ⁄* Null indicators of st2 attributes and type *⁄ SQLUDF_NULLIND *st2_att1_ind, SQLUDF_NULLIND *st2_att2_ind, SQLUDF_NULLIND *st2_att3_ind, SQLUDF_NULLIND *st2_ind, ⁄* Null indicators of st3_out attributes and type *⁄ SQLUDF_NULLIND *st3_att1_ind, SQLUDF_NULLIND *st3_att2_ind, SQLUDF_NULLIND *st3_ind, ⁄* trailing arguments *⁄ SQLUDF_TRAIL_ARGS ) Januar 2010, Biljana Stojanović
Klijent transformacije • Pomoću ovakvih funkcija za transformaciju vrši se razmena vrednosti strukturnih tipova iz baznih tabela sa klijentskim aplikacijama. • 1. Pretpostavimo da želimo da pokrenemo sledeću SQL naredbu (čitanje adrese zaposlenog iz baze – BIND OUT): EXEC SQL SELECT adresa FROM Kadrovi INTO :addrhv WHERE jmbg = ‘0305960123456’ • Odgovarajuća host-promenljiva mora biti adekvatno deklarisana na sledeći način: • SQL TYPE IS Adresa_t AS VARCHAR(150) addrhv; • Ova deklaracija znači da se tip VARCHAR(150) koristi kao reprezentacija strukturnog tipa Adresa_t. Januar 2010, Biljana Stojanović
Na strani servera se izvšavaju sledeće operacije: • Poziv FROM SQL transform fje koja razlaže adresu na atribute, tj. generiše uređenu listu atributa strukturnog tipa • Poziv FROM SQL klijent transfrom fje koja kodira datu listu atributa u jedan ugrađeni tip, npr VARCHAR ili BLOB. Na taj način se omogućuje klijenskom programu da prihvati celu vrednost u jednu host-promenljivu. U opštem slučaju, ova fja ne može da se napiše u SQL-u, već se najčešće definiše kao eksterna fja. • Nakon što klijenski program prihvati adresu kao VARCHAR, može da dekodira njene atribute i da im pristupi na odgovarajući način. Januar 2010, Biljana Stojanović
2. Neka je potrebno realizovati suprotan postupak – proslediti adresu nekog zaposlenog nazad u bazu (BIND IN). • INSERT INTO Kadrovi(adresa) VALUES(:addrhv); • Na strani servera se izvršavaju sledeće operacije: • Poziv klijent transform fje (TO SQL) – kodira se adresa u formatu koji očekuje odgovarajuća TO SQL transform fja za tip Adresa_t (što je lista atributa). Odnosno, ova fja dekodira host-promenljivu u listu atributa tipa Adresa_t. • Poziv TO SQL transform fje koja generiše instancu tipa Adresa_t koju server umeće u tabelu. • U oba slučaja neophodno je prilikom definicije klijent transfrom fja navesti klauzulu TRANSFORM GROUP da bi se znalo koje se transfrom fje koriste. Januar 2010, Biljana Stojanović
Implementacija klijent transform fja kao eksternih fja • from_sql_to_client – FROM SQL klijent transform fja CREATE FUNCTION from_sql_to_client (Adresa_t) RETURNS VARCHAR(150) EXTERNAL NAME ‘addressudf!address_from_sql_to_client' SPECIFIC addrToString LANGUAGE C TRANSFORM GROUP func_group DETERMINISTIC NO EXTERNAL ACTION NOT FENCED PARAMETER STYLE SQL ; Deluje kao da fja prihvata parametar tipa Adresa_t. Zapravo, za svaki red za koji se poziva fja from_sql_to_client, odgovarajuća transform fja (addresstofunc) dekomponuje adresu u listu atributa. from_sql_to_client fja potom generiše npr. string i formatira atribute adrese za prikaz. SELECT ime, prezime, from_sql_to_client(adresa) FROM Kadrovi; Januar 2010, Biljana Stojanović
to_sql_from_client – TO SQL klijent transform fja CREATE FUNCTION to_sql_from_client (VARCHAR(150)) RETURNS Adresa_t EXTERNAL NAME ‘addressudf!address_to_sql_from_client' SPECIFIC StringToAddr LANGUAGE C TRANSFORM GROUP func_group DETERMINISTIC NO EXTERNAL ACTION NOT FENCED PARAMETER STYLE SQL ; Funkcija ne vraća adresu direktno, već konvertuje VARCHAR(150) najpre u listu atributa tipa Adresa_t, a potom DB2 implicitno poziva TO SQL transfrom fju functoaddress da konstruiše objekat koji se vraća bazi. Januar 2010, Biljana Stojanović
Napomena • U nekim situacijama klijentske transformacije mogu da se napišu na SQL-u: • U ovakvim slučajevima ne mora da se zavisi od transform fja prilikom razmene vrednosti strukturnog tipa sa klijentskim aplikacijama. • Ako strukturni tip ima samo jedan atribut • Kodiranje i dekodiranje atributa u ugrađeni tip može biti postignuto nekom kombinacijom SQL operatora ili fja. Januar 2010, Biljana Stojanović
Izdvajanje podataka čiji je tip podtip strukturnog tipa • SELECT adresa INTO :hvaddr FROM Kadrovi; • Aplikacija koja izvršava upit ne može da zna da li će biti vraćena instanca tipa Adresa_t ili nekog od podtipova. • Pretpostavimo da imamo dve mogućnosti: Adresa_t i AdresaZip_t (da bi se pojednostavilo razmatranje). • Ovi tipovi imaju različitu strukturu, tako da i odgovarajuće transform fje moraju da se razlikuju. • Da bi se obezbedilo pozivanje odgovarajuće transform fje, treba omogućiti sledeće: • 1. Kreirati FROM SQL transform fju za obe varijante adrese: CREATE FUNCTION addresstofunc (A Adresa_t) RETURNS ROW (ulica varchar(100), broj varchar(20), grad varchar(100), drzava varchar(100)) language sql return values (A..ulica(), A..broj(), A..grad(), A..drzava()) CREATE FUNCTION Zip_addresstofunc (A AdresaZip_t) RETURNS ROW (ulica varchar(100), broj varchar(20), grad varchar(100), drzava varchar(100), postbroj VARCHAR(20)) language sql return values (A..ulica(), A..broj(), A..grad(), A..drzava(), A..postbroj()) Januar 2010, Biljana Stojanović
2. Kreirati transform grupe, po jednu za svaku varijantu: CREATE TRANSFORM FOR Adresa_t funcgroup1 (FROM SQL WITH FUNCTION addresstofunc) CREATE TRANSFORM FOR AdresaZip_t funcgroup2 (FROM SQL WITH FUNCTION Zip_addresstofunc) • 3. Kreirati eksterne fje, po jednu za svaku rutinu. CREATE FUNCTION address_to_client (A Adresa_t) RETURNS VARCHAR(150) LANGUAGE C EXTERNAL NAME 'addressudf!address_to_client' … TRANSFORM GROUP funcgroup1 void SQL_API_FN address_to_client(SQLUDF_VARCHAR *ulica, SQLUDF_VARCHAR *broj, SQLUDF_VARCHAR *grad, SQLUDF_VARCHAR *drzava, SQLUDF_VARCHAR *output, SQLUDF_NULLIND *ulica_ind, SQLUDF_NULLIND *broj_ind, SQLUDF_NULLIND *grad_ind, Januar 2010, Biljana Stojanović
SQLUDF_NULLIND *drzava_ind, SQLUDF_NULLIND *adresa_ind, SQLUDF_NULLIND *out_ind, SQLUDF_TRAIL_ARGS) { sprintf (output, "[adresa_t] [ulaca:%s] [broj:%s] [grad:%s] [drzava:%s]", ulica, broj, grad, drzava); *out_ind = 0; } CREATE FUNCTION address_to_client (A AdresaZip_t) RETURNS VARCHAR(150) LANGUAGE C EXTERNAL NAME 'addressudf!Zip_address_to_client' … TRANSFORM GROUP funcgroup2 Januar 2010, Biljana Stojanović
void SQL_API_FN Zip_address_to_client(SQLUDF_VARCHAR *ulica, SQLUDF_VARCHAR *broj, SQLUDF_VARCHAR *grad, SQLUDF_VARCHAR *drzava, SQLUDF_VARCHAR *postbroj, SQLUDF_VARCHAR *output, SQLUDF_NULLIND *ulica_ind, SQLUDF_NULLIND *broj_ind, SQLUDF_NULLIND *grad_ind, SQLUDF_NULLIND *drzava_ind, SQLUDF_NULLIND *postbroj_ind, SQLUDF_NULLIND *adresa_ind, SQLUDF_NULLIND *out_ind, SQLUDF_TRAIL_ARGS) { sprintf (output, "[adresa_t] [ulaca:%s] [broj:%s] [grad:%s] [drzava:%s] [postbroj:%s] ", ulica, broj, grad, drzava, postbroj); *out_ind = 0; } Januar 2010, Biljana Stojanović
4. Kreirati SQL-fju koja bira ispravnu eksternu fju za procesiranje instance, npr add_stream. CREATE FUNCTION addr_stream (ab Adresa_t) RETURNS VARCHAR(150) LANGUAGE SQL RETURN WITH temp(addr) AS (SELECT address_to_client(ta.a) FROM TABLE (VALUES (ab)) AS ta(a) WHERE ta.a IS OF (ONLY Adresa_t) UNION ALL SELECT address_to_client(TREAT (tb.a AS AdresaZip_t)) FROM TABLE (VALUES (ab)) AS tb(a) WHERE tb.a IS OF (ONLY AdresaZip_t)) SELECT addr FROM temp; Sada aplikacija može da pozove odgovarajuću eksternu fju pozivom fje addr_stream. SELECT addr_stream(adresa) FROM Kadrovi ; Januar 2010, Biljana Stojanović
5. dodati addr_stream kao FROM SQL klijent transform fju za tip Adresa_t. CREATE TRANSFORM FOR Adresa_t client_group (FROM SQL WITH FUNCTION addr_stream) • 6. PREP myprogram TRANSFORM GROUP client_group Januar 2010, Biljana Stojanović
Objašnjenje: • Izvršavanje naredbe SELECT adresa INTO :hvaddr FROM Kadrovi; dovodi do sledećih akcija: • DB2 traži odgovarajuću FROM SQL klijent transfrom fju u okviru transform grupe client_group zato sto je ona specifikovana u fazi preprocesiranja (korak 6). • Fja addr_stream ima argument tipa Adresa_t i u zavisnosti od njegovog dinamičkog tipa poziva odgovarajuću spoljašnju fju (address_to_client za tip Adresa_t, odnosno Zip_address_to_client za tip AdresaZip_t). januar 2010, Biljana Stojanović