Oznámení
Asociativní deklarace proměnných
před 10 lety
- kosoj
- Člen | 3
Ahoj,
na základě diskuze http://forum.php7.org/…oading-issue jsem se rozhodl
vyzkoušet Nette a zkusit migrovat jeden projekt na Nette. A když se řekne
Nette, tak se ozve dibi.
Tady jsem narazil na 2 problémy. Prvním z nich je chybějící podpora pro „case-sensitive“ aliasy sloupců.
Pokud použiju
SELECT t.code AS „typeCode“
, tak to DibiTranslator#translate patrně detekuje jako řetězec / hodnotu a zkonvertuje na
SELECT t.code AS ‚typeCode‘
, což vyvolá výjimku DibiDriverException
ERROR: syntax error at or near „‚typeCode‘“ LINE 2: SELECT t.code AS
‚typeCode‘, ^
Case-sensitive aliasy (podporují DB PostgreSQL, ORACLE patrně i další) používám pro automatické mapování výsledku dotazu (řádku) na cílový objekt. Možná by šlo použít nějakou značku k tomu, aby to DibiTranslator ignoroval.
Více ale postrádám možnost asociativní deklarace proměnných.
Něco takového:
<?php
$sql = 'SELECT *
FROM public.reservation r
WHERE r.status = %i[status]
AND (
((r.date_from BETWEEN %d[dateFrom] AND %d[dateTo])
OR (r.date_to BETWEEN %d[dateFrom] AND %d[dateTo])
) OR (r.date_from < %d[dateFrom] AND r.date_to > %d[dateTo])
)';
$parameters = array('status' => 1, 'dateFrom' => '2009-05-10', 'dateTo' => '2009-05-16');
// nebo nejak takhle s tim, ze by se v SQL neuvadel typ
/* $parameters = array(
array('property' => 'status', 'value' => 1, 'type' => Dibi::FIELD_INTEGER),
array('property' => 'dateFrom', 'value' => '2009-05-10', 'type' => Dibi::FIELD_DATE) ...
);*/
$result = dibi::query($sql, $parameters);
?>
Standardním zápisem bych muset do parametrů uvést 7 hodnot (4 duplicitní). Pokud bych SQL dotaz upravil/přeuspořádal (definice SQL dotazů mám v samostatném XML souboru), tak bych musel kontrolovat pořadí těchto hodnot. Nebo bych si mohl vytvořit pre-parser, který ten SQL dotaz upraví pro dibi. To už ale postrádá tu elegantnost.
Setkal jste se někdo s touto potřebou, případně jak tyto případy řešíte? Možná jsem něco přehlédl.
před 10 lety
- kosoj
- Člen | 3
Tak jsem si napsal ten pre-parser a je po problému.
před 10 lety
- David Grudl
- Nette Core | 6806
kosoj napsal(a):
SELECT t.code AS „typeCode“
, tak to DibiTranslator#translate patrně detekuje jako řetězec / hodnotu a zkonvertuje na
SELECT t.code AS ‚typeCode‘
Tím že dibi vzniklo primárně pro databáze MySQL, SQLite a ODBC, tak jako
case-sensitive uzavírání používá buď zpětné lomítka `typeCode` nebo
závorky [typecode]
. A řetězce se uzavírají do jednoduchých
nebo dvojitých uvozovek.
Nicmémě pokud je driver PostgreSQL, tak se to automaticky převede na
"typecode"
.
Více ale postrádám možnost asociativní deklarace proměnných.
Tohle skutečně dibi nepoužívá. Totiž duplicitní hodnoty se v SQL objevují spíš zřídka (ale uznávám, že váš příklad je dobrou ukázkou opaku), takže preferovaná cesta je
dibi::query('SELECT *
FROM public.reservation r
WHERE r.status = %i',$status,'
AND (
((r.date_from BETWEEN %d',$dateFrom,' AND %d',$dateTo,')
OR (r.date_to BETWEEN %d',$dateFrom,' AND %d',$dateTo,')
) OR (r.date_from < %d',$dateFrom,' AND r.date_to > %d',$dateTo,')
)');
Hlavní přednost je totiž v tom, že netřeba vymýšlet nové identifikátory, jako je dateFrom, dateTo atd a lze použít přímo lokální proměnné.
Také lze dotaz skládat ještě komplexněji:
$sql = array('
SELECT *
FROM public.reservation r
WHERE %and', array(
'r.status' = $status,
('%or', array(
array('r.date_from BETWEEN %d AND %d', $dateFrom, $dateTo),
array('r.date_to BETWEEN %d AND %d', $dateFrom, $dateTo),
array('r.date_from < %d AND r.date_to > %d', $dateFrom, $dateTo)
)
);
(píšu to z hlavy, možná jsou tam chyby)
před 10 lety
- kosoj
- Člen | 3
Na to podmíněné skládání SQL dotazu jsem narazil na stránce Dibi Quick Start, nicméně, jak jsem uvedl, tak SQL příkazy mám zvlášť v definičních XML souborech, takže tam se to použít nedá.
Ale děkuji za upřesnění.
S tím case-sensitive si nejsem jistý, jestli si rozumíme. Vím, že PostgreSQL oproti standardu převádí klíčová slova na malá písmena, nicméně pomocí dojitých uvozovek lze tomuto převodu zabránit, viz. http://www.postgresql.org/…lexical.html kapitola 4.1.1.
Příklad
<?php
$result = pg_query($conn, 'SELECT now() AS "currentSysdate"');
$row = pg_fetch_array($result, null, PGSQL_ASSOC);
echo 'currentSysdate='.$row['currentSysdate']; // jmeno sloupce je case-sensitive
?>
Tohle se mi ale v současné době při migraci na Nette/Dibi zdá jako nepodstatná malichernost.
před 10 lety
- David Grudl
- Nette Core | 6806
Myslím že si rozumíme, zkuste ty zpětné lomítka `typeCode` nebo závorky [typecode]