holubj / NiftyGrid

DataGrid for Nette Framework
34 stars 34 forks source link

NiftyGrid\NDataSource #1

Closed JanSuchanek closed 12 years ago

JanSuchanek commented 12 years ago
// Pokud je zadán pouze count berou se všechny sloupce, zkoušel jsem nette na 2.1-dev

   public function getSelectedRowsCount()
{
    return $this->data->count("*");
}
holubj commented 12 years ago

Na aktuální verzi Nette to funguje v pořádku. V dev verzi jsem to ještě nezkoušel. Projdu si to a dám vědět :)

JanSuchanek commented 12 years ago

Jasný, v obou to samozřejmě funguje ale když si dáš filtrovat podle nějakého parametru není v explain SELECT count(*) ale nette projde dvakrát to samé. Mohu ti poslat screen.

holubj commented 12 years ago

No bohužel to je takto zatim správně. Jde o to, že když se do gridu dá sloupec jako alias, tak se na něj musí používat podmínka HAVING (protože WHERE na aliasy nejde). Jenže COUNT nebere ohled na HAVING, takže to vrátí celkový počet záznamů. Asi mě ale už napadnul fix, tak to vyzkoušim :)

JanSuchanek commented 12 years ago

Aha, to mě nenapadlo.

JanSuchanek commented 12 years ago

SELECT product.id, product.name, manufacturer.name AS manufacturer_name FROM product LEFT JOIN manufacturer ON manufacturer.id = product.manufacturer_id

Pokud tabulka manufacturer bude obsahovat také name tak je problém jak je tedy správně pojmenovávat manufacturer_name? Nebo to právě řešíš tím HAVING?

holubj commented 12 years ago

V tomhle případě bych momentálně použil alias a na něj se automaticky použije ta podmínka HAVING. Ono by to celé šlo předělat, aby se používala jen podmínka WHERE (nemusely by se používat aliasy), ale muselo by se ke každému sloupci psát něco jako setColumnName('manufacturer.name'); Pak by ale nefungovaly zase agregační fce (např počet objednávak, který zákazník měl, apod..). A v tom je zase ten HAVING dobrej :). Zkusim to nějak opravit a podle toho se uvidí. To, že to teďkon vybírá všechny řádky, je docela velká chyba.

JanSuchanek commented 12 years ago

Tak kdyby to bylo jako fíčura, která by nebyla povinná tak by to bylo gut.

holubj commented 12 years ago

Bylo by řešením něco takového?

SELECT COUNT(*) AS count FROM ( SELECT product.id, product.name, manufacturer.name AS manufacturer_name FROM product LEFT JOIN manufacturer ON manufacturer.id = product.manufacturer_id WHERE product.name LIKE 'a%' HAVING manufacter_name LIKE 'b%' ) AS tab

Ty podmínky tam musí zůstat - tím pádem i ty sloupce. Už by se to ale spočítalo přímo v SQL a PHP by dostalo jen číslo.

JanSuchanek commented 12 years ago

Určitě jo, ale nejsem na tohle expert to by see mussel zeptat třeba Jakuba Vrány, nebo Davida.

Napadlo mě co dát možnost uživateli na ten count si připravit vlastní dotaz?

JanSuchanek commented 12 years ago

Vyzkouším to ať neplácám :)

holubj commented 12 years ago

No psát si vlastní dotaz mi přijde trochu zbytečné. Jak by sis to představoval? :)

JanSuchanek commented 12 years ago

Máš pravdu je to blbost. A co tedy aliasy tvořit automaticky?

holubj commented 12 years ago

Můžeš to trochu rozepsat? Nějak jsem to nepochopil.

JanSuchanek commented 12 years ago

Pochopil jsem to tak že při countu jsou problémy s aliasy a při normálním vypísu jsou aliasy potřeba nešlo by je pro count tam nepřidávat a pro výpis je tam přidat? Ale spíš tak plácám musím si tu variantu s setColumnName('manufacturer.name'); zkusit :)

holubj commented 12 years ago

No když tam pro count nebudou aliasy, tak tam nepůjdou dávat ani podmínky pro aliasy a špatně to spočítá. Ale to je jedno. Co jsem tak koukal po internetu, tak ten muj příklad, co jsem ukazoval, vypadá v pořádku a ona ani jiná možnost (na straně SQL) moc není. Otázka je, jak to zapsat v Nette\Database :) Zatim mě napadá, že by to šlo v Nette\Database\Connection přes query(), ale muselo by se to připojení předávat do NDataSource jako druhý parametr. Pokud nepřijdu na jiné řešení, tak to asi dopadne takto ;)

JanSuchanek commented 12 years ago

Ok

JanSuchanek commented 12 years ago

Ještě poslední dotaz a nedopadne pak podobně http://forum.dibiphp.com/cs/792-velky-problem-s-dibidatasource-a-mysql ?

holubj commented 12 years ago

Tak o tomhle jsem nevěděl, díky za info. To to ale hodně komplikuje, ještě to promyslim.

JanSuchanek commented 12 years ago

Co automaticky generovat view?

holubj commented 12 years ago

No teď je to asi nejpravděpodobnější řešení. Ale moc se mi to nelíbí :/

JanSuchanek commented 12 years ago

Tak mě napadá že tento problém ale museli řešit i v jiných FW. Zkusím něco najít :)

JanSuchanek commented 12 years ago

A co strikně nepoužívat aliasy?

holubj commented 12 years ago

No když si to shrnu, tak v současné době jsou tyto možnosti:

1) Aktuální stav - sloupce se počítaj na straně PHP - musej se všechny vybrat. Nejpomalejší. 2) Count ze selectu - nefungujou indexy. Pomalé. 3) Generovat pohledy - uživatel musí mit práva na tvorbu pohledů. Přijde mi to až moc zbytečné pro každý Grid generovat pohled. 4) Vynechat aliasy - ke každému sloupci se bude muset úvadět tabulkový název (table.column). Nepůjdou do Gridu dávat sloupce z agregačních fcí. Podmínky budou pouze přes WHERE. Mohly by tam nastat nějaké problémy, pokud by se vybíralo id ze dvou a více tabulek (asi by se to dalo vyřešit). Nejrychlejší.

Přes týden teď nebudu mít moc času, ale budu o tom přemýšlet. O víkendu bych už to dal nějak dohromady.

JanSuchanek commented 12 years ago

Mě se líbí 4). Podle mě ji používá i Doctrine 2, a přidje mi i nelogicke aby se v SQL vybírali dva sloupce name, ať na to myslí programátor pokud má MySQL problém 2).

JanSuchanek commented 12 years ago

Tzn. zachoval bych bod 1) a jen bych do metody getSelectedRowsCount() přidal $this->data->count(); přidal hvězdičku:

$this->data->count("*");

holubj commented 12 years ago

To by se ta metoda getSelectedRowsCount() zrušila uplně a použila by se getCount(). Odepisovat tabulky, které mají stejné názvy sloupců se mi moc nechce. V zavedeném projektu by se to už těžko měnilo. Udělal bych to tak, že sloupce by se vybíraly stejně jako doposud, ale pouze u duplicitních názvu by se použila ta pomocná metoda k sloupci setColumnName(nebo tak něco). To mi přijde jako celkem rozumné řešení a moc velký zásah do kódu Gridu to nebude.

JanSuchanek commented 12 years ago

Přesně a u těch tabulek s duplicitními názvy by se použil ten subselect na count, ono je to více méně problém spíš MySQL.

holubj commented 12 years ago

Ještě mě napadlo, že při vypisování sloupců v šabloně by to dělalo problém. Takže duplicitní sloupec by se musel vybrat jako alias (name AS tab_name) a ke sloupci pak přidat setColumnName(tab.name). V tomhle případě by se ten alias využíval jen pro výpis. Filtr by fungoval normálně přes WHERE. Pak by už neměl být žádný problém a tenhle víkend bych to dal dohromady. :)

JanSuchanek commented 12 years ago

Ok, mám ještě jeden postřeh k jQuery autocomplete, má smysl přidávat nějaký timeout, tak aby se neodesílal post při každém písmenku? :)

holubj commented 12 years ago

No jak se to vezme :) Když člověk píše průměrně/rychle, tak si myslim, že je to zbytečné načítat pro každé písmeno. Mně osobně to vyhovuje takhle, ale klidně se nechám přesvědčit. :)

holubj commented 12 years ago

Šlo by přidat možnost nastavit to v konfiguraci, ale prioritou je teď vyřešit NDataSource.

JanSuchanek commented 12 years ago

Omlouvám se za tento asi triviální dotaz. Při odeslání tlačítka Filter (vyhledávání v Gridu) následuje v ajaxu post a potom se vrací payload.redirect a proběhne v jquery get. Vím že upravuješ url. Jen by mě zajímalo jestli by nebylo lepší rovnou poslat get a rovnou invalidovat. Má tady smysl POST + GET ? Nebo je to jen kvuli tomu url?

holubj commented 12 years ago

Je to hlavně kvůli tomu, aby se nedal podvrhnout odkaz třeba na smazání všech článků, editaci záznamu... Ani nevim, jestli by to bez toho redirectu šlo, vzhledem k tomu, že nejdřív se volá metoda configure(je volána v metodě attached v komponenty) a až pak kontrola odeslaného formuláře. Jinak se omlouvám za ještě neupravenej NDataSource, ale měl jsem teď ještě hodně jiných věcí.

holubj commented 12 years ago

Opraveno.