nový SqlPreprocessor pro Nette\Database

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

současný SQL preprocesor v Nette\Database mi nevyhovuje a tak jsem napsal nový. každý ohlas je vítán, hlavně pokud jde o jiné databáze než MySQL. zatím nejsou testy

pokusná verze SQL procesoru je zde: https://gist.github.com/1277781 (zatím jako rozšíření)

otevřená issue tady: https://github.com/…e/issues/381


SqlPreprocessor

funkčnost SQL preprocesoru usnadňuje zápis a čtení přímo psaných dotazů a automatické generování dotazů u metod query(), exec()
fetch…()

má dva režimy:

  • režim ‚placeholder‘ (zpětně kompatibilní), ve kterém je prvním parametrem celý SQL dotaz a pozice argumentů je v něm označena znakem ?, stejně jako v PDO a současném Nette\Database
$db->exec("UPDATE x SET y = ? WHERE z = ?", $y, $z);
  • režim ‚alternate‘, ve kterém se útržky SQL dotazu střídají s argumenty. pozice argumentů není vyznačena nijak. není to totiž třeba. zápis kódu v tomto režimu je mnohem přehlednější, hlavně při větším množství parametrů. připomíná zápis z dibi, ale bez protivných modifikátorů
$db->exec("UPDATE x SET y = ", $y, "WHERE z = ", $z);

o který režim jde pozná podle toho, zda je ve statementu placeholder ?

zpracování polí

umí podle kontextu chytře rozeznávat jak naložit s argumentem typu pole. režimy zpracování jsou:

  • insert: pro INSERT a REPLACE (a multi-insert)
  • assoc: pro UPDATE a SET
  • where: pro použití za klauzulí WHERE a HAVING nebo za některým z logických operátorů. generuje trojice klíč, operátor (=, LIKE, IS NULL* a IN), hodnota, spojené operátorem AND
  • order: pro ORDER BY a GROUP BY. klíč je název sloupce, hodnota je směr řazení: FALSE a <= 0 je DESC
  • in: pro použití za IN, ANY, SOME, ALL. generuje seznam hodnot v závorce
  • pokud není rozpoznám žádný vhodný mód, vytvoří se seznam hodnot oddělený čárkou. např. pro: $db->exec("CALL fnc(?)", $arr);

*) zpracování typu bool:
databáze PostgreSQL a MySQL 5 a vyšší umí krom IS NULL také IS TRUE a IS FALSE – zde se přímo nabízí generovat toto porovnání. bylo by ale třeba stanovit lepší rozlišování podpory než je v poli ISupplementalDriver::$supports – podle verzí db

další

ošetřuje typ hodnoty (int) pro LIMIT, OFFSETTOP

nahrazuje substituce, jako současný preprocesor

PRO:
  • přehlednější kód díky nové syntaxi
  • lepší práce s poli než ve stávajícím řešení
PROTI:
  • další mezivrstva požírající kousek výkonu. preprocesor je trochu složitější než stávající
  • pro Selection/ActiveRow není až tak třeba. většinou se uplatní jen při použití Connection jako DBAL

SqlFragment

SqlFragment je obdoba SqlLiteral, ale krom samotného literálu mu lze předat i argumenty. lze tedy jednodušeji vytvářet správně naformátované a ošetřené útržky SQL kódu

neměl by funkčnost SqlFragment obstarávat přímo SqlLiteral? je nová třída třeba?

Editoval paranoiq (13. 12. 2011 13:13)

David Grudl
Nette Core | 8229
+
0
-

Z velké části je to implementováno, i když trošku jinak.

  1. místo dvou režimů je k dispozici jeden, který funguje podobně jako v dibi: vždy se jako placeholder používá otazník a za výrazem následuje tolik parametrů, kolik je ve výrazu otazníků. https://github.com/…f7b7797f0337
  2. doplnil jsem zpracování polí pro WHERE/HAVING a ORDER BY/GROUP BY. https://github.com/…5221fda581fb
  3. substituce jsme už dříve odstranili https://github.com/…97e653e02549
  4. jako SqlFragment funguje SqlLiteral https://github.com/…68b51e7e28ff