Nette Database: roadmap, myslenky

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

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
+
0
-

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
+
0
-

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 | 1822
+
0
-
  • 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
+
0
-

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 | 1822
+
0
-
  • 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 | 7790
+
0
-

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?

paranoiq
Člen | 392
+
0
-

„staci znat pouze zdrojovou tabulku“ – zdrojových tabulek může být víc (JOIN, UNION), nebo nemusí být žádná (CALL). vždy budou případy, kdy výsledek query nebude možné předávat jako ActiveRow

Honza Marek
Člen | 1664
+
0
-
$tableSelection->order('column desc');

Nefunguje s malým desc schválně nebo je to bug?

llook
Člen | 407
+
0
-

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.

hrach
Člen | 1822
+
0
-

já věděl, že chci ještě něco navrhnout, a to delimiting… respektive navrhuji zrušit ten na „uživatelském vstupu“. Dělá to pak takhle akorát víc neplechy, než užitku…

David Grudl
Nette Core | 7790
+
0
-

Delimiting je v pohodě, spíš bych změnil order() na orderBy() a orderByDesc().

hrach
Člen | 1822
+
0
-

V pohodě není, datazy na AS jsou tu každý druhý den. Navíc nefunguje pro funkce, … např. order('DATE(created_time)') a to žádné metody nevyřeší. OrderByDesc je imo blbost. S přejmenováním order na orderby nemam problem.

hrach
Člen | 1822
+
0
-

@Marax: davno vyresene uplne jinak. Mrkni na testy. ref(‚author‘, ‚illustrator_id‘), related(‚books.illustrator_id‘)

llook
Člen | 407
+
0
-

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
+
0
-

insertUpdate method – replace

Bacha na REPLACE, v mysql mi dělal nějaký bordel v indexech, spíše bych se mu vyhnul.

hrach
Člen | 1822
+
0
-
  • @**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
+
0
-

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 | 1822
+
0
-

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.

Marax
Člen | 28
+
0
-

hrach napsal(a):

@Marax: davno vyresene uplne jinak. Mrkni na testy. ref(‚author‘, ‚illustrator_id‘), related(‚books.illustrator_id‘)

Dík. Někdo by fakt měl udělat lepší dokumentaci k Database…

llook
Člen | 407
+
0
-

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.

paranoiq
Člen | 392
+
0
-

MySQL mi právě vynadalo za klíčové slovo LINES… WTF? escapovat vše! není v možnostech normálního člověka znát a vyhýbat se všemu

hrach
Člen | 1822
+
0
-

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

Editoval hrach (10. 2. 2012 12:24)

Nox
Člen | 378
+
0
-

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 | 1822
+
0
-

@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 | 7790
+
0
-

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 | 1822
+
0
-

@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 | 1029
+
0
-

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 | 1822
+
0
-

@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
+
0
-

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
+
0
-

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 | 7790
+
0
-

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 | 1822
+
0
-

jsem zvedavej, kolik mesicu to budeme jeste tryDelimite ladit.

Nicmene ndb je treba ladit taky porad… :/

David Grudl
Nette Core | 7790
+
0
-

Zrovna dnes na školení mě NDB těžce vypeklo… Pošlu ti to majlem.

hrach
Člen | 1822
+
0
-

Jasny, posli :)

David Grudl
Nette Core | 7790
+
0
-

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
+
0
-

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 | 7790
+
0
-

Ř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.

hrach
Člen | 1822
+
0
-

Jak jsem, Davide, psal jinde, toto plati jen pro where, kde muzes substitvat otaznikem. V selectu proste aktualne nenapises neco jako ->select("CONCAT(sloupec, 'var')"), aniz bys pouzil parametry. To stejne plati pro group.

David Grudl
Nette Core | 7790
+
0
-

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
+
0
-

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í.