Mě na SQL přijde revoluční právě ten deklarativní zápis. Pošleš engine algoritmus, a on ti vyplivne výsledky. Něco podobné je možné pozorovat u LINQ, nebo GraphQL. Díky tomu se opravdu můžu oprostit od detailů práce s databází (na druhou stranu mi přijde zase škoda vzdát se pokročilejších možností) aniž by to začalo být brutálně neefektivní.
Nechápu, co tenhle odstavec měl vyjadřovat. Jestli "oprostit od detailů práce z databází" znamená, že s databází komunikuju pomocí SQL, tak to nemá s ORM nic společného. Jestli to má znamenat, že díky deklarativnímu SQL se můžu oprostit od detailů použitím ORM, tak to není pravda.
Naopak. Díky deklarativnímu SQL se můžu oprostit od detailu uložení dat. Stejně tak nějak musím u inteligentního ORM psát deklarativně a poněkud obecně.
Například u toho LINQ je to pěkně vidět. Nemůžu napsat
sum = 0
foreach a = collection_of_a()
if test(a) then
b = collection_of_b(a.b_id)
if test(b) then
sum += b.val
return sum
ale musím napsat:
src.iters.filter(\a -> ...).b.iters.filter(\b -> ...).sum()
To aby ten LINQ "pochopil" co má udělat.
I když kdo ví, třeba by zvládl i ten tvůj zápis. Zase tak dobře to neznám.
V některých svých hračkách, co jsem dělal jsem měl specializovaný DSLko, kterým jsem se dotazoval na objekty, a pokoušel jsem se to mé pseudoORM přinutit, aby generovalo SQLka, která bych napsal stejně. Celkem to šlo.
U DSL specializovaného pro nějakou konkrétní aplikaci jsem ochoten věřit, že to může generovat rozumné SQL. Ale pak to asi nebude obecně použitelné ORM.
Bylo to obecné DSL pro získávání obecných dat z ORM. Ale mělo to svá specifika a určitě i omezení.
Nebo jiný způsobem. Nette/Database to dělá tak, že dokáže zoptimalizovat i ten tvůj kód. Při prvním průchodu to provede všechny dotazy, to si nakešuje, a při dalších už to načítá hromadně. Mě ten způsob není moc sympatický, ale funguje to.
I když pominu, že ten první průchod může trvat nechutně dlouho, tak jestli při dalších průchodech už nekomunikuje s databází a čte z keše, tak to bude mít minimálně dvě další nevýhody: 1. Keš může být hodně velká; 2. Bude to fungovat správně, jen když se data v databázi nebudou měnit.
Nekešují se data, ale schema. Špatně jsem to popsal. Nejlépe osvětlí ukázka:
foreach ($users(10) as $user) {
echo $user->title;
foreach ($user->articles(10) as $article) {
echo $article->title;
foreach ($article->discuss(5) as $discuss) {
echo $discuss->title;
}
}
}
Při prvním průchodu to vytvoří 51 dotazů, při druhém už jen tři, protože si odvodí, že ty articles a discuss může sloučit.
Možná, že ten tvůj příklad už by byl moc, možná by to zvládl. Ruku do ohně bych za to nedal.
$sum = 0
foreach ($base->where(test_a) as $a) {
foreach ($a->where(test_b) as $b) {
$sum += $b->val;
}
}
return $sum;