Oznámení
Postgre – dotaz s hranatými závorkami
před 5 lety
- revoke
- Člen | 35
Potřebuji vytvořit tento dotaz:
i.pocet_noci && '{3,5}'::SMALLINT[] AND i.strava && '{0,1,4,5}'::SMALLINT[]
Zkoušel jsem několik způsobů zápisu, nejnadějnější se zdál být asi ten nejméně hezký:
... i.pocet_noci && %sql", "'{".implode(',', $nights)."}'::SMALLINT[]", ' AND i.strava && %sql", "'{".implode(',', $food)."}'::SMALLINT[]", ,'...
Který funguje, pokud je v dotazu jen jedna podmínka. V případě dvou se z dotazu stane toto:
i.pocet_noci && '{3,5}'::SMALLINT"] AND i"."strava && '{0,1,4,5}'::SMALLINT["
Čili vnější hranaté závorky přeložil za uvozvky. Existuje nějaký
způsob, jak escapovat hranaté závorky, aby se dalo zapsat column::INT[] ?
Díky za radu.
před 5 lety
- Milo
- Nette Core | 1119
Dibi si s PostgreSQL poli moc nerozumí. Můžeš zkusit moji třídu PgsqlArray. S dibi ji používám takhle:
$a1 = Milo\Utils\PgsqlArray::toSql([3, 5]) . '::SMALLINT[]';
$a2 = Milo\Utils\PgsqlArray::toSql([0, 1, 4, 5]) . '::SMALLINT[]';
'i.pocet_noci && %SQL', $a1, 'AND i.strava && %SQL', $a2
Na implode()
pozor. Musíš escapovat každou položku pole
v kontextu pole a v kontextu řetězce.
před 5 lety
- revoke
- Člen | 35
Zkusil jsem, ale při použití dvou polí se to chová stejně špatně. S escapováním máš samozřejmě pravdu a ta tvá třída se na to hodí. Díky.
A k řešení problému: použitím odpovídajících si datových typů jsem si mohl dovolit vypustit z dotazu ::SMALLINT[]… což je a zároveň i není řešení ;-)
před 5 lety
- Milo
- Nette Core | 1119
Co myslíš tím, že se to chová špatně při použití dvou polí?
před 5 lety
- revoke
- Člen | 35
Kód:
WHERE i.id_jazyk = %i', $this->jazykId(), '
%if ', !empty($params->stay), ' AND i.pocet_noci && %SQL', PgsqlArray::toSql($params->stay).'::SMALLINT[]', ' %end
%if ', !empty($params->food), ' AND i.strava && %SQL', PgsqlArray::toSql($params->food).'::SMALLINT[]', ' %end
%if ', $fullsearch, ' ORDER BY i.id_produkt %end
(předpokládám, že co je před tím a za tím už nemá vliv…)
Dibi vytvoří takovýto dotaz:
WHERE i.id_jazyk = 1
AND i.pocet_noci && E'{5,7}'::SMALLINT"]
AND i"."strava && E'{1,5}'::SMALLINT["
ORDER BY i.id_hlavni_produkt
Editoval revoke (3. 2. 2015 9:33)
před 5 lety
- Milo
- Nette Core | 1119
Divné. Následující mi funguje:
$db->test('
WHERE
i.id_jazyk = %i', 111, '
%if', TRUE, 'AND i.pocet_noci && %SQL', "'{1,2,3}'::SMALLINT[]", '%end
%if', TRUE, 'AND i.strava && %SQL', "'{4,5,6}'::SMALLINT[]", '%end
%if', TRUE, 'ORDER BY i.id_produkt %end
');
EDIT:
Teď mě napadlo… nepředáváš to někde dál přes modifikátor
%sql
(malé písmena)? Ten se ještě zpracovává. Cokoliv ale
vyleze z DibiTranslator je už finálně escapované a mělo by se předávat
přes %SQL
.
Editoval Milo (4. 2. 2015 14:56)
před 5 lety
- revoke
- Člen | 35
Tou poznámkou jsi to vyřešil!
Pravděpodobně jsem to celé začal řešit kvůli jiné chybě, ale při dumpu
dotazu jsem se upnul k řetězci, který mi vrátil dvakrát
escapovaný dotaz:
\dibi::test(\dibi::$sql); ... opraveno na ... \dibi::test('%SQL', \dibi::$sql);
Mockrát díky!