nospor
2.09.2011, 12:29:40
Muszę wybrać nazwy tabel z dowolnego zapytania.
Interesuje mnie każda nazwa tabeli czy to jest w podzapytaniu czy w zapytaniu głównym w join czy w czym kolwiek innym
Tabele jak to tabele mogą mieć różne postacie
tabela
baza.tabela
`tabela`
`baza`.`tabela`
mogą być po FROM, po JOIN po FROM z przecinkami i kupa różnych kombinacji.
Męczę teraz to wyrażenie ale może ktoś już musiał kiedyś robić coś podobnego i może się wiedzą podzielić?
A może jakieś podpowiedzi? Zastanawiam się w ogóle, czy da się to jednym wyrażeniem pobrać, czy nie trzeba będzie zrobić ich więcej.
tolomei
2.09.2011, 12:44:21
luckyps
2.09.2011, 12:58:57
A może spróbować w ten sposób:
Wybrać z bazy danych nazwy wszystkich tabel i sprawdzić, które znajdują sie w zapytaniu...
Fifi209
2.09.2011, 13:49:46
A jeżeli w zapytaniu użyje aliasu?
luckyps
2.09.2011, 14:15:52
Cytat(Fifi209 @ 2.09.2011, 14:49:46 )

A jeżeli w zapytaniu użyje aliasu?
No i co z tego
gac3k
2.09.2011, 14:36:06
a w jakimś orm-ie, nie ma gotowego rozwiązania żeby je ewentualnie podpatrzeć i zaimplementować? Propel, Doctrine? Zdaje mi się że domyślny ORM Kohany też będzie pomocny.
nospor
5.09.2011, 13:22:18
Cytat
Wybrać z bazy danych nazwy wszystkich tabel i sprawdzić, które znajdują sie w zapytaniu...
A jeśli w zapytaniu będą takie tabele, których nie mam w bazie? Je też chcę wyłapać.
@tolomei dzięki za linka, przejrzę i dam znać co z tego wynikło.
Jakieś inne sugestie?
@tolomei pierwszy link radzi sobie nawet ładnie z prostymi zapytaniami. Niestety gdy pojawia się podzapytanie to się wywala
drugi link zaś nie zawiera wszystkich kodów. Niby autor wspomina, że udostępni całość gdzieś później ale nigdzie nie udało mi się całej paczki zlokalizować.
webdice
5.09.2011, 13:58:12
EDIT: Mała poprawka co do kodu na FB.
preg_match_all( '#(FROM|LEFT\sJOIN|RIGHT\sJOIN|INNER\sJOIN|CROSS\sJOIN|INTO)\s?(`?([^\s`]+)`?\.)?`?([^`\(\)\s]+)#i', $query, $result );
Nie wiem do czego to potrzebujesz, ale przyszło mi do głowy jeszcze jedno rozwiązanie. Mianowicie EXPLAIN, z tym że pokazuje aliasy zamiast nazw tabel.
EDIT: Jeszcze drobne poprawki, bo ludzie różnie zapisują zapytania.
nospor
5.09.2011, 18:34:11
$q = 'select * from `tab1`,tab2';
Najprostrze zapytanie i już nie działa na tym wyrażeniu. Obawiam się, że jednym wyrażeniem regularnym tego się nie uda zrobić.
Co do explain to nie mogę tego użyc bo:
1) explain działa tylko na tabelach, które są w bazie. Ja w zapytaniu mogę mieć tabele, których nie będzie.
2) docelowo operować będę na różnych bazach, nie tylko mysql
@nospor tylko tokenizowanie SQL'a, albo parę wyrażeń reg. Ciężko napisać wyrażenie które obejmie wszystkie warunki.
Ewentualnie możesz zobaczyć czy baza danych nie ma kwerendy która zwróci wszystkie tabele które zostały użyte w poprzedniej kwerendzie
Ewentualnie jeżeli to będzie na różnych typach baz danych to łap to w orm'ie (o ile chcesz użyć tego 'przy pisani aplikacji');
nospor
6.09.2011, 09:23:25
A czy jakiś spec od orm jest w stanie powiedzieć czy jest tam parsowanie podanego zapytania?
W tej chwili męczę analizę zapytania przez tokeny i się nie wyrobię w poznawanie jeszcze ORMa, a może ktoś zna odpowiedź na to pytanie?
destroyerr
6.09.2011, 10:32:10
Doctrine2 powinno Ci ułatwić robotę. Mógłbyś sobie nadpisać
Parser, tak żeby nie był związany z EntityManagerem, tzn. żeby nie szukał w nim Twoich tabel. Prostsze rozwiązanie to wykorzystanie
Lexera i wyciągnięcie wszystkiego samemu. Mały przykład:
use Doctrine\ORM\Query\Lexer;
$token = true;
$lexer = new Lexer('SELECT * FROM articles');
while($token)
{
$token = $lexer->moveNext();
switch($lexer->token['type'])
{
case Lexer::T_FROM:
do
{
$lexer->moveNext();
$tables[] = $lexer->token['value'];
if($lexer->isNextToken(Lexer::T_AS))
{
$lexer->moveNext();
}
//skip alias
$lexer->moveNext();
}
while($lexer->isNextToken(Lexer::T_COMMA) && $lexer->moveNext());
break;
}
}
nospor
8.09.2011, 09:24:13
Ostatecznie podzieliłem sql na tokeny a potem analizowałem to ustrojstwo. Żeby nie podzapytania to sprawa byłaby nawet banalna, niestety podzapytania trochę skomplikowały sprawę.
Jak dopracuję kod to może wstawię.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę
kliknij tutaj.