tiny ‘n’ smart
database layer

Odkazy: dibi | API reference

Oznámení

Omlouváme se, provoz fóra byl ukončen

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]