Warning: Declaration of Suffusion_MM_Walker::start_el(&$output, $item, $depth, $args) should be compatible with Walker_Nav_Menu::start_el(&$output, $item, $depth = 0, $args = Array, $id = 0) in /DISK2/WWW/plsql.cz/www/wp-content/themes/suffusion/library/suffusion-walkers.php on line 39
Feb 262014
 

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!

 Posted by at 13:16
Feb 242014
 

Link na předchozí díly. Pokračování z minula, kde jsme založili stránku s formulářem pro editaci TBL_CROSSFIT_WOD_LOV a TBL_CIRCLE_WORKOUT_DEF_SERIE. Ovšem z minulých dílů si bereme spoustu neřešených věcí, které chci pořešit nyní. Aktuálně největší pain jsou LOV a navázené entity. Tedy v tomto díle:

  • Pro pole “Is Default” je vhodné udělat číselník, ať to trošku vypadá – seznam s hodnotamy Ano/Ne
  • Pro pole “Crossfit Target Lov Id” číselník z tabulky tbl_crossfit_target_lov kam jsme v minulém díle nacpali data
  • Přejmenovat formulářové labely na něco rozumného
  • Vytvořit List of Values i pro podřaženou entitu TBL_CIRCLE_WORKOUT_DEF_SERIE

Task číslo 1. -  Pro pole Is Default je vhodné udělat číselník.

Po nalogování se dostaneme na editaci stránky Master Detail. U mě je to ID 14, ale pokud někdo následuje dostal pravděpodobně jiné číslo. Čísla stránek jdou za sebou, nicméně nějaké už jsem vytvořil a smáznul na zkoušku. Tedy Master Detail a editace fieldu P14_IS_DEFAULT.

Při editaci itemu hned v části Identification je na výběr typ. Záleží na typu a hodnotách, které chceme či nechceme umožnit. Zrovna pro binární hodnotu – je či není to defaulutní wod – je logicky na výběr spousta možností – od checkboxu, radio.. atd. Dokonce APEX pro hodnoty Yes/No nabízí vlastní typ. Vyberme Select List, je to příjemný interface a více použitelnější než checkbox či radio.

Dále v sekci Label jsem změnil nehezký text z “Is Default” na hezčejší “Oficiální WOD“. A ještě v sekci List of Values je třeba nadefinovat číselník. Je to velice podobné jako v Sieblu,  možnosti jsou dvě – statický a dynamický. Statický je pevný list hodnot, u kterého se předpokládá že se nebude měnit. Dynamický je napak takový, kde se čtou možnosti z uživatelských dat, tedy z tabulky. Pro toto pole jsou logické jen dvě hodnoty Yes/No, tedy statický. Do hodnoty List of values definition napíšeme :STATIC2:Ano;1,Ne;0. Static řiká, že jde o statické LOV, 2ka protože chceme aby byly v pořadí vytvoření (pak je bez dvojky – pořadí dle abecedy. Zde je to vcelku jedno). A po té se střídá zobrazená hodnota v listu – Ano s její hodnotou ve formuláří – 1. Každá další položka v listu je oddělena čárkou.

Task číslo 2. – Pro pole “Crossfit Target Lov Id” číselník z tabulky tbl_crossfit_target_lov

Z minula máme tabulku TBL_CROSSFIT_TARGET_LOV naplněnou nějakými daty. Z pohledu použití by toto měl být spíše statický list hodnot, ale v rámci cvičení jsem to navrhl jako tabulku a udělejme z toho tedy dynamické LOV. Po kliknutí na editování pole P14_CROSSFIT_TARGET_LOV_ID.

V části Identification opět vybereme Select List. V části Label jsem upravil pole Label na “Cíl cvičení“. A nyní to nejdůležitější – v části List of Values do pole List of Value Definitions:

select target_name, id_crossfit_target_lov from apex_workout.tbl_crossfit_target_lov order by target_name

Obyčejný select z databáze, jediné co je nutné si pamatovat je, že musí vracet dva sloupce s tím že první je textová hodnota zobrazovaná na stránce (target_name) a druhé je hodnota, která je skutečně ve formuláři a která jde do databáze (id_crossfit_target_lov – primární klíč). A ideáně ještě order by pro příjemnější zobrazení.

Task číslo 3. – Přejmenovat formulářové labely na něco rozumného

U každého z Itemů je fajn nastavit nějaký smysluplný label - edit na každém z itemů formuláře, sekce label, pole label. Udělejme něco takovéhleho:

  • P14_NAME – Jméno WODu
  • P14_IS_DEFAULT - Oficiální WOD
  • P14_CROSSFIT_TATGET_LOV_ID - Cíl cvičení
  • P14_PICTURE – Obrázek
  • P14_ROUNDS – Počet kol
  • P14_NOTE – Poznámka

Takže by to mohlo vypadat nějak takto:

Task číslo 4. -Vytvořit List of Values i pro podřaženou entitu TBL_CIRCLE_WORKOUT_DEF_SERIE

Na založení master záznamu WOD je to dostatečné. Ještě bohužel není možné založit k záznamu seznam kol cvičení, protože potřebují odkaz na záznam v tabulce TBL_TABATA_LOV nebo TBL_WORKOUT_LOV. Ve sloupci WORKOUT_OR_TABATA_LOV_ID může být odkaz do jedné nebo druhé tabulky (podobně to řeší Siebel), takže constraint který z mého modelu vygeneroval Oracle SQL Data Modeler nemá moc smysl:

ALTER TABLE TBL_CIRCLE_WORKOUT_DEF_SERIE DROP CONSTRAINT FK_CIRCLE_WORKOUT_DEF_SERIE;

Tím jsme se zbavili nutnosti mít nějaké záznamy v tabulkách TBL_TABATA_LOV a TBL_WORKOUT_LOV, ovšem stejně se bez toho neobejdeme, takže nějaká seed data zase:

INSERT INTO TBL_TABATA_LOV(NAME,ATTRIBUTE_1V,NOTE) VALUES ('Kliky v zátěžové vestě','+9,5kg','Obyčejné kliky v zátěžové vestě'); INSERT INTO TBL_TABATA_LOV(NAME,ATTRIBUTE_1V,NOTE) VALUES ('Dřepy','','Dřepy'); INSERT INTO TBL_TABATA_LOV(NAME,ATTRIBUTE_1V,NOTE) VALUES ('Angličáci','','Angličáci s výskokem'); commit;

To by byla TABATA a ještě obyčejná cvičení:

INSERT INTO TBL_WORKOUT_LOV(WORKOUT_DESCRIPTION,WEIGHT,BODY_WEIGHT_RELATIVE,TARGET,TIME_REST,TIME_REST_DEGRESSION,NOTE) VALUES ('Dřepy',null,1,15,null,null,null); INSERT INTO TBL_WORKOUT_LOV(WORKOUT_DESCRIPTION,WEIGHT,BODY_WEIGHT_RELATIVE,TARGET,TIME_REST,TIME_REST_DEGRESSION,NOTE) VALUES ('Kliky',null,1,10,null,null,null); INSERT INTO TBL_WORKOUT_LOV(WORKOUT_DESCRIPTION,WEIGHT,BODY_WEIGHT_RELATIVE,TARGET,TIME_REST,TIME_REST_DEGRESSION,NOTE) VALUES ('Přítahy',null,1,5,null,null,null); commit;

Nyní zpět do APEXu a opět přidání dynamického listu. Tentokrát do editace detailu (tabulka TBL_CIRCLE_WORKOUT_DEF_SERIE). Týká se to pole WORKOUT_OR_TABATA_LOV_ID, které opět zeditujem:

V Column Attributes vybereme v Display As hodnotu  Select List (query based LOV).

A ještě je třebas v sekci List of Values naplácnout SQL Select do pole List of Values Definition:

select label,val from ( select workout_description ||' '|| case when weight is not null then 'Váha:'||weight else null end || case when target is not null then 'Počet:'||target else null end || case when time_rest is not null then 'Odpočinek:'||time_rest else null end ||' (WORKOUT)' as label, id_workout_lov as val,1 from TBL_WORKOUT_LOV union all select name || ' (TABATA)', id_tabata_lov,2 from TBL_TABATA_LOV order by 3,2)

Spojení unionem all hodnoty z tabulek TBL_WORKOUT_LOV a TBL_TABATA_LOV. Zbytek je tak nějak na krásu.

Pro dnešek předposlední krok. Ještě chybí jeden List of Values a to pro pole IS_TABATA_OR_WORKOUT_ID. Takže do editace itemu IS_TABATA_OR_WORKOUT_ID v sekci Column Attributes v poli Display As vybrat tentokrát Select List (static LOV) a v sekci List of Values opět upravit List of Values Definition na:

STATIC2:Cvik;0,TABATA;1

A  poslední krok – v editaci stránky kliknout praým na TBL_CIRCLE_WORKOUT_DEF_SERIE Detail a vybrat Edit Report Attributes. A upravit labely ke sloupcům:

  • ID_CIRCLE_ORDER – Pořadí
  • WORKOUT_OR_TABATA_LOV - Cvičení
  • IS_TABATA_OR_WORKOUT_ID - Cvičení nebo TABATA
  • ATTRIBUTE_1v - Volné pole (varchar2)
  • ATTRIBUTE_1n - Volné pole (number)
  • Note - Poznámka

Takže po úpravách by mohl formulář na vkládní WOD vypadat nějak takto:

Ve formuláři na obrázku je vyplněno cvičení se jménem Chelsea. Přesně podle definice na Crossfit.com. Pro nyní je to vše, pro příště se nabízí dva logické kroky – report se definovanými WODy – tedy report nad tabulkou TBL_CROSSFIT_WOD_LOV a ideálně i výpis s definicí. A druhá věc, která je aktuálně chybí je možnost editace entit (TBL_TABATA_LOV a TBL_WORKOUT_LOV), kterou jsem v tomto článku dočasně obešel přímými inserty do databáze.

 Posted by at 00:54
Feb 232014
 

Delší čas jsem se tomu nevěnoval, ale pokračuji ve vytváření workoutlogu v APEXu. Ze začátku jsem uváděl list dílů na začátku článku, což nebylo rozumné, protože patrně dojdu k tomu, že to bude mít opravdu hodně dílů. Tedy jsem vytvořil index-post, kde bud vést seznam dílů a na který se budu odkazovat. List předchozích dílů. Tenhle tutorál je ve stavu, kdy jsem je navržena datová vrstva, založen workspace, uživatelé a aplikace obsahuje následující stránky:

  • PAGE 1 -  main - zatím prázdná stránka
  • PAGE 2 – Master – TBL_WORKOUT - report kdy uživatel cvičil (Interactive report)
  • PAGE 3 –  Form on TBL_WORKOUT - editace hlavního záznamu cvičení
  • PAGE 101 – Login - automaticky generovaná stránka s loginem

Přemýšlel jsem o optimálním způsobu pokračování – na jednu stranu bych sem rád psal něco, co jde logicky za sebou na stranu druhou bych se co nejdříve rád přiblížil nějaké funkcionalitě, která je třebas i jen v obezené podobě použitelná. Aktuálně mi ze cvičení okouzlila Chelsea. Takže jsem se koukal na nějaké minimum, které je třeba implementovat, aby to šlo zaznamenávat a docela to dává smysl. Je na to potřeba možnost editace TBL_CIRCLE_WORKOUT_DEF_SERIE, kam mám v plánu ukládat definici cvičení – konkrétně pro Chelsea by tam měly být 3 rádky (jeden s 5 přítahama, druhý s 10 klikama a třetí s 15ti dřepy). A editaci nadřazné entity TBL_CROSSFIT_WOD_LOV, jako master záznam se jménem a parametrama. Obojí najednou se dá hezky vyřešit pomocí APEXového Master Detail Form. Takže začněme formulářem, kde je možné editovat WODy (workout of day):

Nalogujeme se do APEXu jako APEX_DEVELOPER a zeditujeme aplikaci WORKOUT_LOD (u mě 666):


A rovnou dáme “Create Page“. Nyní je na výběr typ stránky, kterou chceme vytvořit. Do tabulky je třebas umět zapisovat záznamy, takže FormNext.


Nyní je třebas nad čím či jak. Máme pod sebou dvě entity (TBL_CIRCLE_WORKOUT_DEF_SERIE a TBL_CROSSFIT_WOD_LOV), takže ideální je umět je zeditovat rovnou, tedy vybereme Master Detail Form a Next.


Nyní nás čeká vcelku rozsáhlý průvodce vytvořením stránek. První, co je požadováno je master tabulka, tedy:

  • Table/View Onwer: APEX_WORKOUT
  • Table/View Name: TBL_CROSSFIT_WOD_LOV
  • Defalutně se nepřidá LOB sloupec - nicméně obrázek uploadovat budeme chtít tedy do seznamu přidáme i PICTURE

A Next.


Nyní “detail” tabulka. Pro nás je to TBL_WORKOUT_CIRCLE_DEF_SERIE, ostatní default a Next.

Nyní APEX potřebuje vědět primární klíče pro obě tabulky:

  • APEX_WORKOUT.TBL_CROSSFIT_WOD_LOV – Zaškrtnout Select Primary Key Column(s) a pak ID_CROSSFIT_WOD_LOV.
  • APEX_WORKOUT.TBL_CIRCLE_WORKOUT_DEF_SERIE – Zaškrtnout Select Primary Key Column(s) a pak ID_CIRCLE_WORKOUT_DEF_SERIE

A zase Next..

Nyní je potřeba definovat pro obě tabulky z čeho se má generovat primární klíč. Prvně se vybírá pro master tabulku, tedy TBL_CROSSFIT_WOD_LOV.  Vybereme se sequence a pro touhle tabulku máme připravenou sequenci SEQ_ID_CROSSFIT_WOD_LOV. Next a po té následuje zase výběr zdroje primárního klíče pro tabulku TBL_CIRCLE_WORKOUT_DEFINITION, což je SEQ_ID_CIRCLE_WORKOUT_DEF_SERI.

A zase Next. Nyní je potřeba pořešit navigaci:

  • Include Master Row Navigator: No
  • Include Master Report: No (obojí si uděláme sami a hezečeji)

A zase Next. Dále je na výběr Layout, vybereme: Edit detail as tabular form on same page.

A Next. Ptát se to na atributy stránky (jméno čísla), necháme default a dáme zase Next. Vybrat Do not use Tabs a zase Next do posledního kroku, kde je summář:

A potvrdíme kliknutím na Create. Pak nás ideálně přivítá hláška o úspěšném vytvoření stránky. S možností jí rovnou otevřít. Problém je, že není možné založit záznam, protože je tu závislost na číselníku TBL_CROSSFIT_TARGET_LOV. Ve kterém nejsou žádná data. Interface a editace této entity počká, jedná se o číselník, který bude vcelku stabilní, takže naférovku inserty přímo do databáze:

insert into tbl_crossfit_target_lov(id_crossfit_target_lov,target_name,note) values (1,'For time','Na čas');
insert into tbl_crossfit_target_lov(id_crossfit_target_lov,target_name,note) values (2,'Numer of Rounds','Počet kol');
insert into tbl_crossfit_target_lov(id_crossfit_target_lov,target_name,note) values (3,'AMRAP','As many rounds as possible - maximální počet kol v časovém limitu');
insert into tbl_crossfit_target_lov(id_crossfit_target_lov,target_name,note) values (4,'OTM','Počet kol');
insert into tbl_crossfit_target_lov(id_crossfit_target_lov,target_name,note) values (5,'Complete','Prostě dokončit');
insert into tbl_crossfit_target_lov(id_crossfit_target_lov,target_name,note) values (6,'Kola v časovém limitu do selhání','Kola v časovém limitu do selhání');
commit;

Záznam již jde založit, ovšem zatím pouze pro master entitu, pro definici serie ještě nemáme data/lov číselníky. Nicméně už by to mohlo vypadat nějak takto:

Aktuálně jde pouze záznam založit. Teoreticky i zeditovat či smazat, ale aplikace zatím nemá nikde prolink ani nějak možnost otevřít již existující záznam. Lze toho docílit napsáním nějaké podobné url:

http://localhost:8080/apex/f?p=666:14:5516028830645::NO::P14_ID_CROSSFIT_WOD_LOV:2

Nemožnost editovat záznamy je zásadní nedostatek. Proklik ale bude až z nějakého reportu, kde bude možné vybírat si WODy k aktuálnímu cvičení a to určitě počká. Příště vylepšíme tenhle vkládací formulář. Hébičkám zdar!

 Posted by at 06:07
Feb 182014
 

Občas jsem zde ukázal nějakou vychytávku z pl/sql a nazval jsem to “rychlotipem”, krátký post, který si myslím že občas dokázal ukázat nějakou zajímavou funkci apod. Postupem času to lehce upadlo, neb mi přišly daleko zajímavější novinky (nejprve 11.2g pak 12.1c), kterým jsem udělal i vlastní kategorii. A protože jsem se rozhodl jít lehce více do šířky a začít k PL/SQL psát i něco o APEXU (a nebude to nejspíše jediné přidané topic - Informatica by mohla být další ;)). Tedy nová kategorie, kam budu cpát tipy a triky na APEX – paralelně se seriálem o workoutlogu. Takže rychlotip číslo# 1 –  jak nastavit delší přežití session, aby nás neotravovalo neustálé odlogovávání při vývoji (případně jde použít stránku bez nutnosti logování – public a je to hned).

Ještě trošku odbočka, dneska jsem narazil na hezký citát, který řiká proč je dobré si věci zkoušet a nejen o nich číst:

“když člověk čte, zapamatujete si v průměru 10–20 % obsahu, když člověk poslouchá přednášku, zapamatuje si jen 20–30 %, když člověk něco aktivně dělá, zapamatuje si až 60–70 %”

Autorem citátu je Robert Kiyosaki, autor investičního bestselleru “Bohatý táta, chudý táta”. Osobně jsem to nedočetl, to se fakt nedalo. Řiká se, že ani špatné knihy do koše nepatří, ale.. Podle mého názoru to neni kvalitní literatura. Raději Jitku Veslou z VŠE, George Sorose, André Kostolanyho. Nicméně hezký citát, škoda že nám nikdy ve škole podobná čísla neřekl (speciálně nám, co studovali dálkově).

Tolik dnešní citát a nyní k APEXu. V APEXu je možnost nastavení maximální délky session na dvou úrovních:

  • Na úrovni instance – nastavuje instance adminstrátor. Toto nastavení dědí aplikace, které mají nastavení délky session null (default a nikoliv 0).
  • Na úrovni jednotlivé aplikace – nastavuje workspace administrátor. Buď aplikace zdědí hodnotu z instance, když není vyplněno (null) nebo má vlastní (nějaké číslo) či má nekonečnou délku (0) – viz dále.

Takže jak to nastavit :

  • Na úrovni instance loginem administrátora /apex/apex_admin. V Manage Instance -> Security -> Session Timeout. Je tam parametr Maximum Session Length in Seconds (default 28800 = dva dny) a Maximum Session Idle Time In Seconds (dafault 3600 = hodina). Ohledně nejvyšší možné povolené hodnoty je nutné si všimnou poznámky v nápovědě: “This session duration may be superseded by the operation of the job that runs every hour which deletes sessions older than 12 hours.”. Viz dále.
  • Na úrovni aplikace loginem workspace administrátora /apex/apex. V Home -> Editace vybrané aplikace -> Edit Application Properties -> záložka Security -> sekce Session Timeout. A zde jsou možné 4 nastavení:

  • Maximum Session Length in Seconds - maximální délka session v sekundách, null – dědí z instance level, 0 – nekonečno, číslo – sekundy.
  • On Session timeout direct to this URL – Název mluví za vše. Přesměrování když vyprší uvedený čas. Nejspíše někam na stránku s loginem s chybovou hláškou apod. Stránka by měla být public, páč uživatel nebude přihlášen v tu chvíli.
  • Maximum Session Idle Time Second – maximální délka session v sekundách při nečinnosti, null – dědí s instance level, 0 – nekonečno, číslo – sekundy
  • On session idle time timeout direct to this URL – Název mluví za vše. Přesměrování když vyprší uvedený čas při nečinnosti. Nejspíše někam na stránku s loginem s chybovou hláškou apod. Stránka by měla být public, páč uživatel nebude přihlášen v tu chvíli.

Co je nepříjemné je hláška o tom, že i když nastaví programátor více, může ho stejně killnout job:

” The session duration may be superseded by the operation of the job that runs every eight hours which deletes sessions older than 12 hours.”

Což znamená, že na domácím prostředí by bylo fajn ošéfovat i tenhle job. Což se dá udělat třeba pod SYSem a pohledem do all_scheduler_jobs:

Nápověda v APEXu doslova řiká: “job který běží každých 8 hodin a killuje session starších 12 hodin”. Nevím, ale podle ALL_SCHEDULER_JOBS je job ORACLE_APEX_PURGE_SESSIONS nastaven na start každou hodinu a to také dělá dle ALL_SCHEDULER_JOB_RUN_DETAILS. Každopádně je třeba s ním něco udělat. Job volá WWV_FLOW_CACHE.PURGE_SESSIONS, která má nějakou takovouhle signaturu:

procedure purge_sessions (
--
-- Purge flow session state tables to avoid keeping session
-- state no longer needed. Purge all sessions older then a certain
-- age. May result in a very large number of delete transactions.
-- Commit is performed between delete commands.
--
p_purge_sess_older_then_hrs in number default 12,
p_security_group_id in number default null,
p_report_results in varchar2 default 'NO');

Job volá purge_sessons bez parametrů a dědí defaultní hodnoty, tedy p_purge_sess_older_then_hrs=12. Takže co s tím? Řešení je spousta od DISABLE jobu, přes DROP až po změnu spouštění. Nejlepší bude co nejméně invazivní akce, takže jen změna textu jobu a místo volaní procedury bez parametrů – s defaultními, tak se svými hezčejšími:

Nejprve asi PL/SQL Block – líp se do toho bude hrabat a případně přidávat:

begin
DBMS_SCHEDULER.SET_ATTRIBUTE (
name =>'APEX_040200.ORACLE_APEX_PURGE_SESSIONS',
attribute =>'JOB_TYPE',
value =>'PLSQL_BLOCK');
end;

Pak z toho tedy pl/sql block (nejen volání procky) a naše parametry – hodil jsem tam 48 hodin.

begin
DBMS_SCHEDULER.SET_ATTRIBUTE (
name =>'APEX_040200.ORACLE_APEX_PURGE_SESSIONS',
attribute =>'JOB_ACTION',
value =>'begin
WWV_FLOW_CACHE.PURGE_SESSIONS(48,null,''N'');
end;');
end;

A Oracle job nezdokumentoval, takže vložení komentáře, že to bylo upraveno.

begin
DBMS_SCHEDULER.SET_ATTRIBUTE (
name =>'APEX_040200.ORACLE_APEX_PURGE_SESSIONS',
attribute =>'COMMENTS',
value =>'Sprostě zeditováno');
end;

Ještě je třebas počkat si na jedno proběhnutí jobu, že je to všechno v pořádku a doběhne se stavem SUCCESS. Tolik k prodloužení života sessions.

 Posted by at 04:33
Feb 172014
 

Někdy na začátku roku 2014 jsem se rozhodl začít vytvářet aplikaci pro logování a sledování cvičení s tím, že si APEX procvičím a rovnou z toho napíšu tutoriál. Tento post je něco jako seznam dílů na který se mohu odkazovat v každé díle, abych nemusel všude psát odkaz na předchozí díl či díly. Ostatně to vypadá, že jich bude asi bžilion ;) So, enjoy.

1. Workoutlog v APEXu – hezky od začátku #1 – úvod
2. Workoutlog v APEXu – hezky od začátku #2 – návrh datové vrstvy(1)
3. Workoutlog v APEXu – hezky od začátku #3 – návrh datové vrstvy(2)
4. Workoutlog v APEXu – hezky od začátku #4 – APEX workspace&user
5. Workoutlog v APEXu – hezky od začátku #5 – APEX založení aplikace
6. Workoutlog v APEXu – hezky od začátku #6 – editace hlavní entity
7. Workoutlog v APEXu – hezky od začátku #7 – editace wod definice (1)
8. Workoutlog v APEXu – hezky od začátku #8 – editace wod definice (2)
9. Workoutlog v APEXu – hezky od začátku #9 – zobrazení obrázku

 

 Posted by at 22:52
Feb 072014
 

Dneska krátká zpráva – k dispozici na vyzkoušení (na stažení jsem nenašel) je Oracle Application Express 5.0 Early Adopter 1.  Oracle prezentuje jednu hlavní, za to zásadní, novinku – Page Desinger. Což se dá představit jako takové WYSIWYG. Hodně líbí – jestli se s něčím člověk vzteká nyní v APEXu, tak je to pozicování regionů.  Možnost vyzkoušt si to je zde: Oracle Application Express 5.0 Early Adopter 1.

Rozepsal jsem zde nějakou serii článků o vývoji cvičebního logu a i když nyní nemám moc času, určitě budu brzy zase pokračovat, zvlášť po tom, co jsem si prozatimní excel smáznul a přišel o měsíční log cvičení :D. Každopádně pro mě to znamená, že tyto články budu vést bez jakéhokoliv grafického návrhu, až bude 5.0 na stažení tak se to dokrášlí. A rovnou slibuji tedy článek o instalaci Apex 5.0 na Oracle 12c, který se určitě bude hodit ;)

 Posted by at 21:51
Jan 272014
 
První díl - Workoutlog v APEXu – hezky od začátku #1 – úvod
Druhý díl - Workoutlog v APEXu – hezky od začátku #2 – návrh datové vrstvy(1)
Třetí díl - Workoutlog v APEXu – hezky od začátku #3 – návrh datové vrstvy(2)
Čtvrtý díl - Workoutlog v APEXu – hezky od začátku #4 – APEX workspace&user
Pátý díl - Workoutlog v APEXu – hezky od začátku #5 – APEX založení aplikace

 

Takže další pokračování aplikace jejíž cílem je logovat cvičení a také snad trošku cvičence hnát a štvát a v dobách opočinku ukazovat pěkné grafy. V minulém díle jsme založili aplikaci a ve schématu se kterým budem pracovat 13 tabulek. Dobré je si zkusit nalogovat se jako developer do Apexu a kliknout na SQL Workshop a zde by v sekci Recently Created Tables měly být vidět naše založené tabulky pro log a všechno je tedy vpořádku.

Nyní si nalogujem jako developer (localhost:8080/apex w:APEX_WORKOUT, u:APEX_DEVELOPER, p:Developer_0) a pokračujeme vy vytváření aplikace.  A pokud ještě nyní APEX nemáte rádi, tak nyní ukáže svou sílu, jak rychle lze vytvořit stránku ve které lze plně editovat databázová tabulka. Po nalogování Application Builder – a Application 666 a tlačítko edit:

A dále následuje stránka ve které lze editovat aplikaci. Konkrétně jsou zde především vidět jednotlivé stránky aplikace (html, formuláře, prostě stránky) . Stránky je možné zde upravovat, mazat, editovat a kliknutím na tlačítku  Run je přímo otevřít v prohlížeči. Vše krásně intuitivní, nyní by editace naší aplikace měla vypadat nějak takto:


Nejlogičtějším krokem je asi nyní udělat jednouchou stránku, která umožňuje zobrazit naši hlavní entitu – TBL_WORKOUT ve které budou záznamy o tom, kdy jsme cvičili. Aktuálně má naše aplikace vě stránky – číslo 1 (blank), kterou necháme a 101 jako stránka, která podporuje nalogování (tzn. výzva k zadání uživatele a hesla). Takže dnes přidáme dvě další stránky – jedna, která flat zobrazí data z tabulky TBL_WORKOUT a druhou, která tabulku umožní editovat. Teoreticky je možné obě stránky vygenerovat najednou, nicméně v rámci cvičení to zkusme sami ;) Takže hurá do toho!

Nejprve se, ale ještě vraťme do Oracle a SQL Developeru a založme tam PL/SQL funkci pod uživatelem APEX_WORKOUT, která bude vypadat něja takto:

create or replace function get_time_of_workout(p_start date, p_end date) return varchar2
as
ln_mins number;
begin
if (p_end<p_start) or p_start is null or p_end is null
then
return 'wtf';
else
ln_mins:=round((((p_end-p_start)*24)-floor((p_end-p_start)*24))*60);
return to_char(floor((p_end-p_start)*24))||'hod. '|| case when ln_mins=0 then null else ln_mins||'min.' end;
end if;
end;

Funkce vrací text, který řiká jaký je rozdíl mezi dvěma datumy. Protože nás určitě bude zajímat jak dlouho jsme cvičili. Má to trošku cvičný charakter, protože by se to dalo dát přímo do case selectu, kde by to bylo dokonce výkonější, ale v rámci cvičení to zkusme takto – příště třeba jinak ;) Dobře, máme nyní funkci, která nám v sexy formátu (2hod. 32min.) zobrazí jak dlouho jsme cvičili. A nyní opět k APEXu, jsme tedy na stránce Application Builder – Aplikace 666 se seznamem všech stránek, které v dané aplikaci jsou. Přidáme nyní tu, která bude zobrazovat čistě tabulku TBL_WORKOUT. A pro to je třeba udělat násedující:

Klikeneme na Create Page a nyní je třebas rozhodnout, jakou stránku chceme přidat – na výběr jsou grafy, mapy, prázdná stránka atd. Chceme zobrazit tabulku, což je v terminologii Oracle Report.


A klikneme na Next. Následuje výběr typu reportu. Necháme interaktivní ačkoliv pro tento účel by klidně stačil classický. Tedy Interactive repor a opět Next. A následuje zadání základních attributů nové stránky:

  • Page Number: 2 – generováno ze sekvence, měla by se vygenerovat 2 (první byla blank stránka)
  • Page Name: Master – TBL_WORKOUT. Při vývoji dávám název entity/tabulky, pak se přejmenuje
  • Region Template: Jak má stránka vypadat – css a barvičky, dávám Region Without Buttons and Titles
  • Region Name: REG_TBL_WORKOUT - název regionu – je to místo, kam se části/itemy stránek umístují
  • Breadscrum: do not use breadscrum on page – bez navigace, uděláme si sami ;)


A opět Next, zde se to ptá na navigační záložky – vůbec, vyberme Do not use tabs a zase Next. A nyní se to ptá na select z jakého se má report sestavit, tedy:

select id_workout,
workout_start,
workout_end,
get_time_of_workout(workout_start,workout_end) as cas_cviceni,
workout_day,
workout_type,
note,
'' edit,
'' see
from tbl_workout
order by id_workout desc;

Je to sice, hloupý select, ale některé věci stojí za pozornost. Konkrétně Doba_cviceni, která volá nově založenou funkci get_time_of_workout a jejíž výsledek se v reportu objeví jako další sloupec. A sloupce edit a see. Které v reportu vytvoří dva nové sloupce se kterými mam jistý záměr. Konkrétně kliknutím na edit půjde záznam zdeditovat (nová stránka).  A kliknutím na see uvidí uživatel přehled daného cvičení. Záznamy jsem seřadil podle id_workout, což by mělo odpovídat času, jak uživatel cvičil. Ono by to šlo i podle workout_start, ale přecejenom mé naplácané testovací záznamy pak zbytečně matou ;) Link to single row view:NO, nechcem možnost mít na celou stránku jeden záznam, kliknou na “Next” a pokračujem.


Nyní už zbývá jen povrdit sumář, potěšit se zelenou fajvkou a hláškou o úspěšnosti vytvoření stránky a nyní kliknout na zkoušku na Run Page. S tím, že po nalogování by měl být vidět nějaký takovýto výsledek:

Ok. Máme k dispozici Interaktivní report, který možňuje filtrovat, grupovat, stahovat data, řadit, ukládat nastavení, vyhledávat atd. Kdo nezná, tak doporučuji si to vyzkoušet proklikat před dalšími kroky ;) Je to fajn, ale je třeba pokračovat a konkrétně se zbavit vyhledávacího baru – asi nikdo nebude potřebovat – takže delete. Skočíme do editace stránky (přímo z otevřené stránky je dole odkaz nebo se proklikáme v Application Builderu) A pravým tlačítkem klikneme na REG_TBL_WORKOUT a vybereme Edit.

Otevře se stránka s nastavením reportu a bueme nastavovat. Vybereme záložku Report Attributes a najedeme na sekci Search Bar a zde ho odstraníme: Include Search Bar: NO. Nyní scrollneme nahoru zpět do sekce Column atributes a zde to trošku vylepšíme a zkrášlíme. Konkrétně přejmenujem hlavičku sloupců na něco hezčího:

To by mohlo stačit, takže modré tlačítko Apply Changes. Nyní jsme odstranili možnost vyhledávání, pojmenovali názvy sloupců a report už vypaá trošku k světu. Co chybí nejvíce nyní je možnost editace jednotlivých záznamů. Záznamy chci editovat tím způsobem, že kliknu u příslušeného řádku na sloupec/ikonku edit a hodí mi to na stránku s možností editací záznamu. Takže bude potřeba upravit sloupec edit a udělat z něj klikací link. Na což je relativně brzy, protože ještě nevíme kam linkovat. Tedy nejprve přirozeně uděláme stránku, kde je možné záznamy z TBL_WORKOUT editovat. Takže zpět do editace aplikace na seznam stránek a opět “Create Page”. Nyní máme opět na výběr typy stránek, ale tentorkát jdeme po editaci, takže Form.


A opět Next. A nyní je na nás rozhonout odkud bude form vygenerován a jak bude vlastně vypadat. Například, když vyberu naši nově založenou funkci (respektive by to měla být procka, aby to bylo správně) get_time_of_workout, tak pro mě Oracle vygeneruje form, který bude mít dva fieldy, pro každý parametr jeden. My chceme primárně editovat tabulku TBL_WORKOUT, takže From a table or View.

Nyní nás čeká zase wizard/průvodce, takže:

  • Table/View Owner: APEX_WORKOUT – jiné schéma by nemělo být ani dostupné
  • Table/View Name: TBL_WORKOUT – tabulka, kterou chceme umět editovat

A opět Next a dávám:

  • Page Number:3
  • Page Name: Form on TBL_WORKOUT (nechávám)
  • Region Title: REG_FORM_TBL_WORKOUT
  • Region Template: Reports Region
  • Breadcrum: - do not add breascrum on page -

A opět Next na výběr záložek/tabů:

  • Tab Options: Do not use tabs - zase bez tabů, pak si prolinkujem jak budem potřebovat

A opět Next na výběr primárního klíče:

  • Primary Key Type: Select Primary Key Columns(s) – Apex potřebuje vědět pole čeho má identifikovat záznamy, protože máme vlastní primární klíč (u každé tabulky první sloupec s prefixem ID_)
  • Primary Key Column 1: ID_WORKOUT


A pokračujeme dál průvocem – Next - nyní výběr odkud se vezme primární klíč pro sloupec ID_WORKOUT. Máme sekvenci, tedy Existing Sequence a vybereme sekvenci, která patří k této tabulce, tedy SEQ_ID_WORKOUT a opět Next na výběr sloupců, pro které budou pole a které bude možné editovat. Necháme tak jak je - tedy všechny. Zde stojí za upozornění, že chybí primární klíč, který takto editovat nelze,a opět Next. Chceme všechna tlačítka Create/Delete/Save takže necháme všude yes a zase Next.

Nyní máme určit cíl, kam má stránka uživatele hodit po té co stiskne tlačítko Sumbit či Cancel. Moc stránek tu nemáme, ale logicky zpět na ůvodní seznam cvičení, tedy stránku 2.

  • After Page Sumbit and Processing Branch to Page: 2
  • When Cancel Button Pressed Branch to this Page: 2

A následuje summarizace před vytvořením:

A pokud hébičky pracovali dobře, mělo by se nám objevit po kliknutí na Run Page něco takovéhleho:

Což je formulář, který umožní editovat/smazat/přidat záznam TBL_WORKOUT. Když pominu nehezké názvy u polí. Tak ke splnění toho, co jsem si zadal na začátku tohoto dílu, chybí jedna podstatná věc. Nexistuje prolink na záznam ze stránky 2 (s reportem cvičení) na možnost editace záznamu – stránky 3. Teoreticky můžu otevřít editaci záznamu přes tento link:

http://localhost:8080/apex/f?p=666:3:::NO::P3_ID_WORKOUT:1

Který řiká aplikace 666, stránka 3, žádné session id (dostanu nové), NO – Žádný debug, žádný request a hlavně P3_ID_WORKOUT=1. Kde P3_ID_WORKOUT je hidden element na html formu na zákadě, kterého Oracle fetchnul záznam s where ID_WORKOUT=1 z databáze.

Takže opět klikačka. Tentokrát je třeba dostat se na editaci stránky číslo 2 a následovat podobné, kroky jako v první části tohoto článku, tedy nejprve pravým a editace.


Vybereme záložku Report Attributes a sekci Column Attributes – tedy místo, kde už jsme jenou přejmenovávali názvy sloupců. Tentokrát ale rozklineme tužku/pastelku před sloupcem Edit:

Výborné! A nyní uděláme ze sloupce Edit klikací link odkazující na stránku číslo 3. Po kliknutí najdeme sekci Column Link a vyplníme jí takto:

  • Link:  text přípaně si vybrat nějakou ikonku [icon 4], která se hodí k editaci
  • Target: Page In Application – linkujeme v rámci aplikace
  • Page: 3 – cílová stránka
  • Item: P3_ID_WORKOUT – zkrytý primární klíč, kterému chceme předat honotu ze sloupce ID_WORKOUT

Hotovo! Hotovo! Nyní by tabulka s reportem mohla vypat nějak takto:

A po kliknutí na nové tlačítko by se měla otevřít stránka 3 s editovaným zkušebním záznamem:

Tak a to by mohlo být pro tento díl vše ;) Co příště ještě úplně nevím těch možností jak to vést je hodně. Ale pokusím se o něco kratšího, nějaké vylepšení nebo tak ;)

 Posted by at 13:45