holubj / NiftyGrid

DataGrid for Nette Framework

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

NiftyGrid\NDataSource

JanSuchanek opened this issue · comments

// 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("*");
}

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 :)

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.

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 :)

Aha, to mě nenapadlo.

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?

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.

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

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.

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?

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

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

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

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

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 :)

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 ;)

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

Co automaticky generovat view?

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

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

A co strikně nepoužívat aliasy?

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.

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

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

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

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.

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.

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. :)

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? :)

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. :)

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

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?

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

Opraveno.