Podivnosti s referencemi do jedné tabulky (postgresql)
- jik
- Člen | 149
Zdravím,
na systému opensuse 13.1, apache 2.4.6, php 5.4.20, postgresql 9.2.4, nette
2.0.14. Podobně i opensuse 12.3 s příslušnými verzemi. Mám tabulku, do
které se odkazuji z několika jiných tabulek (v současné době aplikace
má celkem >20 tabulek s řadou relací mezi nimi, ale problém mám
s relacemi do této jediné tabulky):
CREATE TABLE process (
id SMALLINT PRIMARY KEY,
role_acc SMALLINT,
role_fin SMALLINT,
icon VARCHAR(10), -- toto je nazev ikony k zobrazeni
nazev VARCHAR(40)
);
Tabulku používám v šablonách k zobrazování položky nazev, nebo ikony, typicky:
<span class=\"icon {$pozemek->process->icon}\"></span>
{$lv->process->nazev}
Problém mám s tím, že v případě této tabulky se mi čas od času
(ne vždy, ale občas to jakoby zjankovatí a pak nepomáhá ani smazat cache)
stane, že to na těchto polích hlásí „Trying to get property of
non-object“, ačkoliv, jak jsem mnohokrát prověřoval, příslušné hodnoty
process_id zcela určitě nejsou mimo tabulku process. Jindy se to zase zklidní
a jede bez problémů, jak má. Pokud namísto ikon,nebo názvů zobrazím jen
process_id, jsou všude regulérní hodnoty.
Dnes jsem si všiml, že v apačím logu jsou zprávy typu:
AH00052: child pid 3385 exit signal Segmentation fault (11)
Není to nějká kolize jmen? Podobné chyby se mi dříve objevovaly častěji
a vesměs jsem je řešil mazáním cache, ale s nějakou letní verzí Nette
(~2.0.10 nebo 12) se to ‚zklidnilo‘ – s touto jedinou výjimkou. Dnes
po opětných problémech jsem nasadil 2.0.14 a nic se nezměnilo.
- jik
- Člen | 149
hrach napsal(a):
Pises, ze smazani chache nepomuze. Co tedy pomuze?
To kdybych věděl. Prostě po nějaké době se to umoudří. Dnes večer to zase začalo blbnout, uvidíme … (dnes jsem již rezignoval a zítra zkusím na druhé mašině s opensuse 12.3).
Jo, jednu věc jsem si uvědomil: stává se mi to (naštěstí) pouze na počítačích, na kterých aplikaci vyvíjím. Když už to začne chodit a přenesu to na server, tak to nezlobí. Alespoň na to nepatuji. Ale při vývoji se mi to stalo již povícekrát, jednu dobu jsem to „řešil“ nahrazením kontrukce
$lv->process->icon
za konstrukci
$lv->ref('process','process_id')->icon
ale dnes to tímto způsobem nešlo.
Editoval jik (4. 1. 2014 23:29)
- jik
- Člen | 149
Tak dneska vše běželo zcela bez problémů. Ráno na notebooku bez chyby a teď jsem se vrátil na stolní počítač – ale napřed jsem provedl vacuum databáze … tak mě napadá, jestli by se nemohlo jednat o nějaký problém s časovou sousledností – že nějaká operace nad db se provede opožděně a php již pokračuje s tím, že data prostě nejsou? Databáze má celkem okolo 150 tisíc záznamů, postupně se vyvíjí a doplňuje – a jedno z posledních doplnění bylo právě to, že jsem vytvořil tabulku process a v několika tabulkách původně obsahujících položku
process smallint
nejprve doplnil položku
alter table ... add column process_id smallint referencess process
Nakonec jsem odstranil položku process
alter table ... drop column process
A od té doby čas od času s tím mám potíže. Jediné, co mě napadá, že databáze během vývoje není zcela konsolidovaná a některé operace zvládne poněkud opožděně, na což php nečeká. Jeví se mi to jako blbost, ale nic jiného mě nenapadá.
- jik
- Člen | 149
Tak se chybička vrátila. Mám situaci, která je zatím zcela opakovatelná. Je to na Nette 2.1.2 a mám „kolečko“ mezi 2 presentery:
- NemovityPresenter a v něm Default – zobrazuje sestavu záznamů z tabulek pozemek a stavba (zjednodušeně):
protected function startup() { //pouze nastaveni promennych
}
public function actionDefault($id) {
...
$this->a_pozemky = $this->s_pozemek->getPozemkyLv($id)->where("process_id < {$konstanta}");
}
public function renderDefault($id) {
foreach ($this->a_pozemky as $o_pozemek) {
$pozemek = new StdClass;
$pozemek->id = $o_pozemek->id;
... - data potrebna do sestavy
$pozemek->icon = $o_pozemek->process->icon; // zde se zjevuje chyba "Trying to get property of non-object"
$pozemky[] = $pozemek;
unset($pozemek);
}
$this->setView('defaultrep');
$this->template->form = $this['defaultrepForm'];
}
- PozemkovyPresenter a v něm Edit – zobrazuje 1 záznam z tabulky pozemků (zjednodušeně):
public function actionEdit($id) {
$o_pozemek = $this->s_pozemek->getPozemek($id);
... data potrebna do sestavy
$this["editpozForm"]->setDefaults($this->o_pozemek); // nastavení výchozích hodnot
}
public function renderEdit($id) {
...
$this->template->form = $this['editpozForm'];
$this->setView('edit');}
}
public function editpozFormSubmitted(Form $form) {
//uprava a kontrola dat
//ukladani
//aktualizace souvisejicich dat
$this->redirect('Nemovity:', $lv_id);
}
Tabulky:
CREATE TABLE process (
id SMALLINT PRIMARY KEY,
icon VARCHAR(10),
...
);
CREATE TABLE pozemek (
id SERIAL PRIMARY KEY,
lv_id INTEGER NOT NULL REFERENCES lv,
cislo INTEGER,
podlomeni INTEGER,
rada SMALLINT,
...
process_id SMALLINT REFERENCES process DEFAULT 0,
...
);
Problém je v tom, že po návratu z PozemkovyPresenter pravidelně zhavaruje v NemovityPresenter, když má přečíst jméno ikony. Pokud však před uložení smažu cache, vše projde, jak má. Stejně tak vše je v pořádku, pokud do této sestavy vstupuji odjinud. Kromě uvedeného PozemkovyPresenter je zde i analogický StavebniPresenter s úplně stejnou chybou: otevřu stavbu, uložím a zhavaruje na analogickém místě, kde se načítá ikona stavby.