NOT IN NULL vrací prázdný výsledek

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Lavka
Člen | 8
+
0
-

Dobrý den,
narazil jsem na problém ohledně používání IS NOT v Nette/Database. Přesněji jde o to že když dotaz vrátí IS NOT NULL tak se vrátí prázdný výsledek.

...
->where("id NOT",$this->connection->table("share")....)
...

to jsem vyřešil tím že jsem dotaz z tabulky share položil dřív a pak ho projel:

$notShow = "0";
foreach($result as $note) {
	$notShow .= ",".$note->task_id;
}

Toto řešení fungovalo do té doby, než jsem začal ajaxovat aplikaci a tento dotaz se vykonal dřív než proběhlo volání handlu. A tak se vrátilo ajaxem to samé co předtím. Kód pro vykreslení seznamu mám v komponentě, takže dotaz předávám jako parametr při jeho volání, z toho důvodu bych potřeboval celý tento kód umístit do toho dotazu, který předávám do komponenty a provádí se až při renderování šablony.

petr.pavel
Člen | 535
+
0
-

To není chyba Nette Database. NOT IN (NULL) prostě vrací false, IN (NULL) (bez negace) taky. Tak se chová MySQL.

Jestli ti dobře rozumím, chtěl bys, aby $this->connection->table(„share“) vracelo $vysledek, který by pak v kontextu where("id NOT", $vysledek) vždycky vrátil true. A to dost dobře nejde, protože žádná taková univerzální hodnota neexistuje. NDB nemůže vědět, v jakém kontextu to voláš, aby třeba někdy vrátilo 0 a někdy null.

Řešením je vyčlenit poddotaz:

...
$shares = $this->connection->table("share")....;

if ($shares) {
  ...->where("id NOT",$shares);
}
...
nanuqcz
Člen | 822
+
0
-

Není to hezké řešení, ale tyhle problémy s NDB řeším tak, že mu „vnutím“ vlastní SQL dotaz:

// Získat všechny články, které neobsahují žádné komentáře označené jako spam
$db->table('article')
	->where('
		article.id NOT IN (
			SELECT `article_id` FROM `article_post` WHERE `article_id` = `article`.`id` AND `spam` = 1
		)');

Možná někdo poradí hezčí řešení, každopádně tohle funguje :-)

Editoval nanuqcz (9. 3. 2013 13:56)

duke
Člen | 650
+
0
-

petr.pavel napsal(a):

To není chyba Nette Database. NOT IN (NULL) prostě vrací false, IN (NULL) (bez negace) taky. Tak se chová MySQL.

Chyba Nette Database to rozhodně je. Chybou je právě to, že Nette Database interně používá výraz IN (NULL), který není ekvivalentní k IN (). Potíž je v tom, že zápis IN () se v SQL použít nedá.

Už se to řešilo na githubu zde a zde.

Zatím jsme došli k tomu, že nejlepším řešením je upravit Nette\Database tak, aby nahrazovala:

(expr) IN ()

výrazem

(expr) IS NULL AND FALSE

a

(expr) NOT IN ()

výrazem

(expr) IS NULL OR TRUE

Bude to vracet hodnoty, které jsou očekávané, a přitom se zachová jak syntaktická kontrola výrazu expr, tak jeho případný vedlejší efekt.