Pokračujme ve vytváření našeho workoutlogu, index předchozích dílů zde. Dneska to bude vcelku izolovaný díl – do reportu s WODy (cvičení – workout of day), pro který jsme částečně připravili editovací/vkládací formulář přidáme i obrázek. Způsobů jak toho docílit je opravdu mnoho. Jedna z nejjednodušších cest je udělat klasický report a že má být ve sloupci obrázek z (B)LOBu vcelku jednoduše nakonfigurovat. Velice podobně jako s ikonkou “edit”, což jsme použil hned v prvním dílu. Takže tentokrát úplně jinak – nebudeme zakládat žádnou stránku v konfiguraci APEXu, ale vrátíme stránku pomocí PL/SQL funkce a to samé z obrázkem – vytvoříme pl/sql, které bude obrázek číst z tabulky a vracet. Ještě to trošku odlehčím na začátek, v Crossfitu existují 2 základní typy WODů:
Hero WODs – Cvičení pojmenovaná po hrdinech. Typicky se jedná o amerického vojáka padlého v boji, případně hasiče, příslušníka SWAT apod. Ke každému hero wods by měl být tedy i obrázek daného hrdiny. Pro příklad na obrázku níže je Randy, člen SWAT, který zahynul v boji (cvičení 75x power snatch na čas).
Benchmark girl WODs – Cvičení pojmenovaná po ženách, nikoliv však, že by jej nezbytně musely cvičit jen ženy. A pokud se nepletu tak se to neváže k žádné konkrétní ženě. Nicméně zde se určitě obrázky budou hodit také, například Cindy (5 přítahů, 10 kliků, 15 dřepů – maximální počet kol za 20 minut(AMRAP)). Já si třeba představuji Cindy nějak takto:
A pak budou patrně nějaká další WOD a vlastní, ale proč jim také nepřiřadit, nějaký obrázek, že? Hlavně to děláme kvuli obrázkám žen pro benchmark girls
To bylo na odlehčení a protože jsem se rozhodl psát to lehce formou tutoriálu (přecejen APEX v čechách moc nejede..) tak nejprve popis jak to asi bude fungovat. V Oracle je možné vytvořit funkci, kterou je možné provolat z browseru (či odkudkoliv). Funkci stačí vytvořit, nagrantovat jí a povolit její volání. Funkce může vracet výstup v html (package htp – v tom bude report – příští díl) a nebo případně jiný typ mime (image/jpg například pro obrázek).
Začněme s klasickým hello world/cindy:
create or replace procedure print_hello
is
begin
htp.p('hello world/cindy');
end;
Funkce je pod naším uživatelem APEX_WORKOUT, takže bez založení public synonyma jí lze provolat přes následující url:
http://localhost:8080/apex/APEX_WORKOUT.print_hello
Po otevření prohlížečem by se měla objevit chyba 404 – not found. Bez grantu to prostě nepůjde Chce to grant pro uživatele anonymous.
grant execute on print_hello to anonymous;
Nyní už by to mohlo fungovat – respektive adresa http://localhost:8080/apex/APEX_WORKOUT.print_hello by měla přestat vracet error 404 (not found) a začít vracet 403 (not autorized). Co je ještě potřeba povolit je print_hello v proceduře wwv_flow_epg_include_mod_local, která je přímo ve schématu APEX. Procedura má jeden parametr, kterým je jméno funkce nebo procedury. Pokud je návrat true je přístup povolen, pokud je návrat false je přístup zamítnut. Mám APEX 4.2, tedy u mě je tato procedura v APEX_040200 schématu. Na co je dobré upozornit je, že funkce má připraven IF statement s listem, kam je možné vypsat povolené funkce (pozor na prefix schématu, velká a malá písmena apod). Ovšem na prvním řádku je napsáno return false; Na což se typicky nováček nachytá a řádek přehlídne a nevykomentuje. Po úpravách vypadá má funkce nějak takto:
create or replace
function wwv_flow_epg_include_mod_local(
procedure_name in varchar2)
return boolean
is
begin
if upper(procedure_name) in (upper('APEX_WORKOUT.print_hello')) then
return TRUE;
else
return FALSE;
end if;
end wwv_flow_epg_include_mod_local;
Kdybych měl vyjmenovat top chyby, pak by to bylo nevykomentování rádku return false; (odstranil jsem ho zde kompletně i ty komentáře od Oracle), nepočítání s prefixem schématu/název package. Velikost písmen a umístění funkce, tam kde být nemá (v APEX_040200 schématu). A to by mohlo být vše. Takže po korektním přidání do wwv_flow_epg_inlude_mod_local už by mohla url fungovat.
To je hello world, a nyní by to chtělo proceduru, která bude vracet obrázek. Jako jeden parametr bude mít ID řádku (id_crossfit_wod_lov), který obrázek se má zobrazit. Bude číst z naší tabulky TBL_CROSSFIT_WOD_LOV. Dále musí vracet správný mime typ (image/jpeg). A pak už jen zbývá vytisknout na výstup LOB. Nacož se dá použít čtení LOBu po kouskách pomocí DBMS_LOB a tištění pomocí htp package nebo použít hotovou proceduru od Oracle z package WPG_DOCLOAD.
create or replace
PROCEDURE obrazek_wodu(p_image_id IN NUMBER)
AS
l_length NUMBER;
l_file_name VARCHAR2 (2000);
lob_loc BLOB;
BEGIN
/* Čtení BLOB obrázku z tabulky TBL_CROSSFIT_WOD_LOV */
SELECT picture, DBMS_LOB.getlength (picture)
INTO lob_loc, l_length
FROM TBL_CROSSFIT_WOD_LOV
WHERE id_crossfit_wod_lov = p_image_id;
/* vráceni správného mime typu a minimální hlavičky */
OWA_UTIL.mime_header ('image/jpeg', false);
HTP.p ('Content-length: ' || l_length);
OWA_UTIL.http_header_close;
/* vrácení dat obrázku */
WPG_DOCLOAD.download_file (lob_loc);
END obrazek_wodu;
Tedy by to chtělo zbavit se dlouhého jména, prefixu a udělat to tak jak se to dělat má – pomocí public synonyma:
create public synonym p_wod for apex_workout.obrazek_wodu;
Nagrantovat:
grant execute on p_wod to anonymous;
A opět přidat do wwv_flow_epg_inlude_mod_local:
create or replace
function wwv_flow_epg_include_mod_local(
procedure_name in varchar2)
return boolean
is
begin
if upper(procedure_name) in (upper('APEX_WORKOUT.print_hello'),'P_WOD') then
return TRUE;
else
return FALSE;
end if;
end wwv_flow_epg_include_mod_local;
A to je vše:
Příště udělejme PL/SQL funkci, která bude vracet stránku/report s WODama a někdy příště nebo dále bude možné na WOD kliknout a rovnou ho přidat do cvičení A to už se budeme pomaličku blížit k něčemu na čem se dá stavět. Hébičkám zdar!