Nette Database: roadmap, myslenky
- hrach
- Člen | 1838
Myšlenkový roadmap pro další ndb verzi:
- insertUpdate method – replace
- table prefix – otazka, jak zanest to nette\db\table a zaroven do bezneho dotazu
- union – pro nette\db\table
- setRowClass – nutne pro implementaci nejake nadstavby, IResource pro ACL, apod.
- obstrakce ActiveRow od Selectoru – pros by bezny vysledek query nemohl profitovat z vlastnosti ActiveRow?
- zruseni inner joinu –
$db->table('book')->where('author.id', NULL)
ted nefunguje jak ma…
Mate nejake pozadavky? Pripominky? Myslenky, kam by se ndb melo ubirat?
Editoval hrach (7. 2. 2012 15:17)
- OndrejSlamecka
- Člen | 41
Ad insertUpdate: Něco jako https://github.com/…pository.php#L100 ? (shameless selfpromo :- )
OT: Díky za práci co na Nette\Database děláš, je to super.
Editoval OndrejSlamecka (7. 2. 2012 20:59)
- paranoiq
- Člen | 392
přihodil bych: https://github.com/…d90582387337
preprocesor by měl zajišťovat i to prefixování
ad setRowClass – nemyslím, že nahrazovat AR je úplně nutné… :/
abstrakce ActiveRow od Selectoru – jo! jen si zatím nedovedu představit jak bude ActiveRow fungovat bez nadřazené Selection… či jak sestavit Selection z primitivního dotazu… to smrdí parsováním SQL
- hrach
- Člen | 1838
- OndrejSlamecka: hele, to sem netusil, ze uz nekdo neco takoveho zacal delat… jojo, k necemu takovemu smeruji, nicmene ne v ramci ndb, to bych nechal vyclenene zvlast;
- insert update sem mel na mysli to, co je v notorm nativne: https://github.com/…M/Result.php#L277
- row class:
- nemyslim uplne nahrazovat, jako spise dedit
- activeRow nepotrebuje selection, predstav si neco jako
$db->query('select * from users ... slozite veci, jiony, groupy,...)->setRow('AtiveRow', 'users');
- není třeba žádné parsování, najednou bude se moci volat na
resultu
$user->related('book')->...
- dalsi vec k cemu je treba rowClass je ACL a vytvoreni entity.
class CommentEntity extends ActiveRow implements IResource, IHasOwner
{
public function getResourceName() {
return 'comment';
}
public function getOwner()
{
return $this->author_id;
}
}
$acl->allow('member', 'comment', 'edit', null, function(Permission $acl, $role, $resource, $privilege) {
if ($acl->getQueriedResource() instanceof IHasOwner) {
if ($acl->getQueriedResource()->getOwner() === $user->id)
return TRUE;
}
// ...
});
$comments = $article->related('comments')->setRowClass('CommentEntity'); // mohla by zajistovat taky nejaka automatika
foreach ($comments as $comment) {
echo $comment->text;
if ($acl->isAllowed($comment, 'edit'))
// link na editaci...
}
Editoval hrach (8. 2. 2012 0:15)
- paranoiq
- Člen | 392
ad „nemyslim uplne nahrazovat, jako spise dedit“: to je právě ten problém. i když jde o ActiveRecord, vyšší vrstva by měla ActiveRow spíš obalovat než dědit. nacpat všechno od získávání dat přes entitu až po přístup (který má být beztak až v service vrstvě) do jedné třídy není good practice
jak chceš volat $user->related(‚book‘)->, když nevíš, jaký je výchozí bod? musíš rozparsovat to SQL, abys zjistil jaká je $user vlastně tabulka (v metadatech z PDO může být třeba alias). a joiny, uniony, call atp. to dál komplikují
- hrach
- Člen | 1838
- ad kompozice misto dedeni – az mi ukazes vhodnou kompozici, ktera vyresi vyse zmineny priklad, rad se poucim a implementuji. Nic nemam proti kompozici, jen proste je to vysnena vec, ktera v praxi implementaci spis ztezuje
- ad related – staci znat pouze zdrojovou tabulku, primarni klic se dohleda, vic neni treba; jmeno tabulky predavam v setRowClass. edit: ukazka toho volani pretaka ve FF mimo stranku, mozna sis proto nevsiml.. kdovi jak se to zobrazuje jinde. zalomim to.
Editoval hrach (8. 2. 2012 0:14)
- David Grudl
- Nette Core | 8218
hrach napsal(a):
- insertUpdate method – replace
To rozhodně chybí.
- table prefix – otazka, jak zanest to nette\db\table a zaroven do bezneho dotazu
Nerušil jsi tuhle substituce?
- setRowClass – nutne pro implementaci nejake nadstavby, IResource pro ACL, apod.
Tudy určitě ne. Mohlo by to být užitečné, ale lidi by toho zneužívaly třeba na IResource ;-) Takže lepší bude vymyslet use-case používající kompozici.
- obstrakce ActiveRow od Selectoru – pros by bezny vysledek query nemohl profitovat z vlastnosti ActiveRow?
To by v praxi bylo asi neřešitelné. Nebo jinak řečeno, k čemu by pak bylo Notorm?
- Honza Marek
- Člen | 1664
$tableSelection->order('column desc');
Nefunguje s malým desc schválně nebo je to bug?
- llook
- Člen | 407
Honza Marek napsal(a):
$tableSelection->order('column desc');
Nefunguje s malým desc schválně nebo je to bug?
Schválně, viz https://forum.nette.org/…pec-as-alias#…
Kdyby se identifikátory musely nějak obalovat (jako v SQL), tak by to vypadalo hnusně. Proto NetteDB používá konvenci, že co je samými velkými, to je keyword, vše ostatní jsou identifikátory. Zdá se mi, že se na tom dost lidí zasekne, mělo by se to v dokumentaci nějak výrazněji zmínit.
- David Grudl
- Nette Core | 8218
Delimiting je v pohodě, spíš bych změnil order() na orderBy() a orderByDesc().
- llook
- Člen | 407
To, že nefunguje uvnitř funkcí, bych pokládal za bug, ale jinak mi tahle
konvence vyhovuje. Rozhodně víc, než kdybych musel psát něco jako
->where('[something] > 1')->order('[order]')
.
Problém to dělá akorát všem začátečníkům, když se s tím poprvé setkají. Proto bych byl spíš pro zvýraznění v dokumentaci, aby to věděli předem.
- Filip Procházka
- Moderator | 4668
insertUpdate method – replace
Bacha na REPLACE, v mysql mi dělal nějaký bordel v indexech, spíše bych se mu vyhnul.
- hrach
- Člen | 1838
- @**llook** a proč bys proboha musel psát [something]??? Kvůli
lepšímu spaní? Když pominu, že je blbost používat názvy
sloupců/tabulek, které jsou klíčovými slovy, tak si myslím, že se jedná
natolik o okrajový případ, že ruční vepsání
->order('`order`')
ničemu nevadí.
- @**HosipLan**: kdyz se podivas na odkazovany notorm, tak zjistis, ze zadyn replace se nepouziva; nebylo by to ani kompatibilni pro ostatni db…
- llook
- Člen | 407
Já si nemyslím, že jde o okrajový problém. Těch klíčových slov je strašně moc (viz), programátor si je nemůže všechny pamatovat a často jde o běžná anglická slova, která jako název sloupce můžou dávat smysl.
Pokud mám sloupec s pořadím, tak je blbost mu dávat jiný název, než order. Podobně často může být blbost nazvat sloupec jinak, než třeba default, key, interval, group, on, regexp apod.
- hrach
- Člen | 1838
Denne pisu desitky sql dotazu v konzoli a prakticky nikdy jdem neptreboval escapovat. order je jako nazev sloupce spatne, proste stejne jako pri programovani, dam si pozor pri psani sql dotazu. Alternativy k order jsou priority, position, atp. Nazvy sloupcu, jako default, key, interval, group, on, regexp jsou uz uplny fail. Projdi si notorm forum a rekni, jestli si nekdo stezoval. Nikdo nikdy. Je to umele vytvorene predstava, ze escapovat se musim naprosto vsechno. (Nemluvim o uzivateleskem vstupu.)
A co opravdu bytostne nesnasim, je proste to, ze mysql neni na klicova slova case sensitive a nejakej framework me k tomu z vlastni „neschopnosti“ nuti.
- llook
- Člen | 407
Devět z deseti péhápkařů neescapuje, tak to přece musí být správně!
Další slova zavádí každá nová verze. MySQL 5.0 zavádí mimo jiné LABEL, CONDITION, RELEASE, verze 5.6 už i slova jako PAGE, LEVEL, PASSWORD, SUBJECT, VALUE a spoustu dalších. Kde bereš jistotu, že se v některé příští verzi neobjeví třeba i ta tvoje PRIORITY nebo POSITION? A vážně si myslíš, že je blbost pojmenovat sloupec s heslem „password“ a úroveň značit jako „level“?
Jestli se Nette začne ubírat tím směrem, že escapování je blbost, tak fajn, ošetřím si to sám. Ale nepřijde mi to jako správný směr, už kvůli dopředné kompatibilitě. V případě SQL se s escapováním jen těžko podaří sestavit příkaz, který by na novější verzi nefungoval.
- hrach
- Člen | 1838
Bordelni mysql jsou opravdu silne argumenty… :(
Nicmene, nenavrhuji kompletne odstranit escapovani, navrhuji vypnout „podezrele parsovani“, ktere je nedokonale a k nicemu. Tedy v bodech:
- pokud pouzivas cache a ndb si zapamatuje, ktere sloupce selectovat,
samozrejme je vybere pomoci
`
(zpetny apostrof) - pokud ndb dela join, opet jeho sql vytvori pomoci
`
- uživatelská data
- oapostrofoval bych pouze ktere projdou regularem
^[a-z0-9_]+$i
; tzn. melo by to ve vysledku oapostrofovat->order('order')
- pokud neprojde regularem a BUDE se jednat o KLICOVE SLOVO, uz to budu muset
udelat sam, tedy
order('
`order
` DESC')
order('DATE(
`time
`)')
select('
`order
` as position')
- pokud to nebude klicove slovo, udelam
order('position DESC')
a jsem naprosto v klidu- bude vetsina pripadu
- oapostrofoval bych pouze ktere projdou regularem
Editoval hrach (10. 2. 2012 12:24)
- Nox
- Člen | 378
U té 3b (která na rozdíl od 3c je nějakým řešením, souhlasím
s předchozími příspěvky) je ale potřeba nějak zpřístupnit
driver->delimit (jinak při změně driveru bude potřeba přepsat všechny
db identifikátory v aplikaci) anebo aplikovat delimit na všechny přijaté
...
(jestli to tam už je, tak se omlouvám, nenašel jsem)
- hrach
- Člen | 1838
@Nox: trochu blbost, ndb neni jen nette\database\table, ale taky normalni $connection->query, ktery zadnou takovouto funkcionalitu nenabizi. Escapovat tam musis rucne, escapovani narozdil od dibi neni prevadeno mezi drivery. A pozor, ted to nejdulezitejsi: kdo jste kdy menili databazi na projektu? A pozor, vy co ste tu meli cest – opravdu chcete tvrdit, ze escapovani bylo to nejmensi? versus triggery, auto increment, limit, offset, view, triggery, ktere proste funguji mezi databazemi rozdilne…
- David Grudl
- Nette Core | 8218
Jednoduché pravidlo, že se escapují všechny alfanumerické identifikátory krom slov velkými písmeny je podle mého daleko snazší na pochopení a používání. Stačí ho zdůraznit v dokumentaci a pro dotazy mít rychlý link na FAQ.
Navíc je tu argument dopředné kompatibility. Pokud někomu selže
order desc
, selže mu hned a princip po první chybě pochopí.
Ale pokud někomu náhle a nečekaně po upgrade na novější MySQL selže
position DESC
, čeká ho peklo.
- hrach
- Člen | 1838
@DavidGrudl: s takovou logiku navrhuji poustet tryDelimite na vysledek $connection->query. Ted to funguje, po upgradu mysql bude peklo.
Je to proste něuvěřitelnej oser psát „as“ velkými. Už se to i mně několikrát stalo, prostě mám v hlavě fixovaný non case sensitive, takže to při prvním bušení dám malým. Ano, hned vím, kde je chyba a opravím to, ale je to prostě klacek pod nohy. Pokud se ti nelíbí moje řešení, ok, ale pak požaduji toto:
- vyjimku pro klicove slovo AS, ktere se proste nebude ani jako male escapovat
- opravu chyby, kdy se neescapuje
DATE(time)
- Tharos
- Člen | 1030
Já teda možná málo vidím do kontextu diskuze, ale proč se s
AS
vůbec psát? Je to klíčové slovo, které se snad nejsnáze
ze všech dá vynechat (něco jako ASC
).
Mám na mysli něco ve smyslu:
SELECT name jmeno, surname prijmeni FROM person ORDER BY age
namísto datlování:
SELECT name AS jmeno, surname AS prijmeni FROM person ORDER BY age ASC
- hrach
- Člen | 1838
@Tharos: mas svatou pravdu, je to jenom o rychlejsim pochopeni. Pokud mam vycet hodnot na select a mezi nekterymi mam carku, a nekde ne, tak se na prvni pohled tezko identifikuje, jestli to neni chyba.
Dobry, upravuji sve vyhruzky, chci uz jenom bod 2:
- opravit delimite, abych fungoval na
DATE(time)
- Honza Marek
- Člen | 1664
David Grudl napsal(a):
Navíc je tu argument dopředné kompatibility. Pokud někomu selže
order desc
, selže mu hned a princip po první chybě pochopí.
Nevim. Už jsem měl otevřenej github formulář s issues, ale pak mě napadlo, že desc nějakým způsobem fungovat musí, protože už to určitě někdo někdy potřeboval.
- paranoiq
- Člen | 392
pro mě jsou velká písmena v klíčových slovech užitečný coding standard. většina IDE neumí zvýrazňovat SQL kód ve stringu (natož u útržků) a velikost je tak jediný záchytný bod při čtení kódu. za „všechno malými“ bych vraždil
uvažuji o rozšíření SQL preprocesoru o volitelné escapování všeho (aby to bylo dostupně i u query() apod.)
- David Grudl
- Nette Core | 8218
hrach napsal(a):
- vyjimku pro klicove slovo AS, ktere se proste nebude ani jako male escapovat
Výjimky jsou obecně špatné, ale zrovna AS je nepovinné, takže bude jednodušší ho vynechat.
- opravu chyby, kdy se neescapuje
DATE(time)
To je jasné, to je bug.
- hrach
- Člen | 1838
jsem zvedavej, kolik mesicu to budeme jeste tryDelimite ladit.
Nicmene ndb je treba ladit taky porad… :/
- David Grudl
- Nette Core | 8218
Tak jsem to konečně dal dohromady https://github.com/…e/issues/591 – problém je v množných číslech v názvech tabulek.
- llook
- Člen | 407
Koukal jsem na to tryDelimite a za největší problém považuji řetězce.
Řetězec ohraničený apostrofy v SQL totiž také může obsahovat apostrof,
zapsaný dvojitě ('D''oh'
).
Kdyby se dal napsat regexp typu „cokoli, co neobsahuje apostrof, ale může obsahovat dva apostrofy“, tak by to dost usnadnilo, ale nejsem si jistý, jestli ten rozsypaný čaj zápis takového pravidla umožňuje.
Pokusil jsem se implementovat něco na způsob Context-Aware Escaping™, ale oproti původním třem řádkům kódu je to trochu overkill, takže to ani nebudu pullrequestovat: https://github.com/…391cb08806b2 (+ testy)
Berte to teda spíš jako námět, jakým směrem by se také mohlo ubírat konečné řešení (až se zase někdo ozve, že se mu tryDelimite chová neočekávaně).
- David Grudl
- Nette Core | 8218
Řetězec ohraničený apostrofy by dle mého neměl v tryDelimite() co dělat, od toho je tu otazník a předávání parametrů. Skutečně bych tlačil uživatele do tohoto řešení, protože řetězce zavání SQL injection.
- David Grudl
- Nette Core | 8218
llook napsal(a):
Další slova zavádí každá nová verze. MySQL 5.0 zavádí mimo jiné LABEL, CONDITION, RELEASE, verze 5.6 už i slova jako PAGE, LEVEL, PASSWORD, SUBJECT, VALUE a spoustu dalších.
Ve verzi 5.6 jsem žádné z těchto slov nenašel.
- llook
- Člen | 407
David Grudl napsal(a):
llook napsal(a):
Další slova zavádí každá nová verze. MySQL 5.0 zavádí mimo jiné LABEL, CONDITION, RELEASE, verze 5.6 už i slova jako PAGE, LEVEL, PASSWORD, SUBJECT, VALUE a spoustu dalších.
Ve verzi 5.6 jsem žádné z těchto slov nenašel.
To je divný, dal bych krk za to, že to tam ještě před měsícem bylo. Nedaří se mi najít starší verze souborů dokumentace, tak teď nevím, jestli blbě čtu, nebo co. Jediné, co jsem našel, že všechna ta slova jsou v tabulce symbolů, tak je možné, že je někdo hloupě překlopil do dokumentace a mezitím to někdo další opravil…
Každopádně na nosné myšlence, že mezi SQL slova se může kdykoli dostat cokoli, to nic nemění.