Escapovani SQL pro Oracle
- ventil
- Člen | 3
S Nette teprve začínám, ale po shlédnutí instruktážních videí a pročtení dokumentace jsem se pustil do přepracovávání jednoho z mých projektů. Rozčarován jsem byl hned na začátku, když mi jeden modul nechtěl pomocí dibi načíst jednoduchý SQL dotaz.
Po zkoušení různých syntaxí:
dibi::query('SELECT * FROM [table] WHERE [id] = %i', $id);
dibi::query('SELECT * FROM `table` WHERE `id`=%i', $id);
dibi::select(*)->from('table')->where('id = %d', $id);
byla výsledkem vždy stejná výjimka: „ORA-00942: table or view does not
exist“. V debugu jsem si všiml, že Nette vždy vyprodukuje dotaz ve tvaru:
"SELECT * FROM "table" WHERE "id" ... "
, což jsem nechtěl.
Pátraje po tom, kde se tam ty uvozovky neustále berou jsem se dostal až k
drivers/oracle.php
k funkci escape($value, $type)
,
kde je následující:
...
case dibi::IDENTIFIER:
// @see http://download.oracle.com/docs/cd/B10500_01/server.920/a96540/sql_elements9a.htm
$value = str_replace('"', '""', $value);
return '"' . str_replace('.', '"."', $value) . '"';
...
Na uvedeném odkazu je specifikace, že pokud se identifikátor uvede do
uvozovek, pak je case-sensitive, jinak je case-insensitive. Takže jinými slovy
mohou identifikátory "table"
, "Table"
,
"TABLE"
apod. představovat naprosto odlišné objekty v DB. Ve
svém okolí neznám žádného databázistu, který by tuto zhýralost
využíval.
Jelikož mám spoustu skriptů napsaných čitelnou formou á la
"SELECT * FROM albums WHERE interpret LIKE 'Jackson%'"
, chci se
pozeptat (než si oracle.php přepíšu sám). Co k tomu vedlo, že jsi se
rozhodl dávat identifikátory Oracle do uvozovek namísto jejich běžné formy
(která je CI) ??
Popřípadě je možno v oficiálním releasu upravit ony
str_replace
funkce, tak aby uvozovky (u názvů identifikátorů
objektů) nepoužívaly ?
Pokud bych chtěl využívat dibi musel bych vše přepisovat do této nepěkné formy:
dibi::query('SELECT * FROM [TABLE] WHERE [ID] = %i', $id);
dibi::query('SELECT * FROM `TABLE` WHERE `ID`=%i', $id);
dibi::select(*)->from('TABLE')->where('ID = %d', $id);
Prostě vše psát velkými písmeny, což je pro mě dost nezvyk :-)
Díky moc za odpověď…
Editoval ventil (6. 8. 2009 1:30)
- Petr Motejlek
- Člen | 293
Takže jsem to testoval — všem doporučuji používat uvozovky při definici názvů tabulek a sloupců (nebo cokoliv, co vaše DB používá jako identifikátor, nejlíp použít dibi už pro CREATE TABLE). Např. ten Oracle je docela zajímavě case sensitive – když použiju při CREATE TABLE v názvu tabulky něco bez uvozovek, uloží si to oracle jako case insensitive identifikátor — jako takový k němu lze dojít buď použitím uvozovek a uvedení identifikátoru ve velkých písmenech (např. „MOJE_TABULKA“), nebo bez uvozovek (a pak Oracle udělá automaticky upper case a uvozovky si dodá).
To, co výše popisuji, bohužel není na všech DB stejné, dokonce se to i (jako např. u MySQL) může na různých platformách chovat různě. Proto všem doporučuju používat identifikátory tam, kde se mají používat a nespoléhat se na DB, že jí všechno dojde ;).
- ventil
- Člen | 3
Omlouvám se za nevhodné zařazení do fóra (dibi by asi vážně bylo vhodnější :-).
Podíval jsem se ještě na jeden zdroj: http://www.amler.biz/…racle-mssql/ a opravdu se to chová tak jak popisoval Petr Motejlek. Ach jo…
Díky tomu, že jsem SQL nikdy neuvozoval, nesetkal jsem se s tímto
problémem. Díval jsem se na tu revision 147 a opravdu netuším jak dál.
Opravit spoustu SQL skriptů a přepsat vše na velká písmena aby mi to
schroustalo dibi, nebo si udělat vlastní verzi oracle.php
a tento
quoted identifiers security fix si tam zrušit ?
Editoval ventil (6. 8. 2009 12:07)
- PetrP
- Člen | 587
ventil napsal(a):
Opravit spoustu SQL skriptů a přepsat vše na velká písmena aby mi to schroustalo dibi, nebo si udělat vlastní verzi
oracle.php
a tento quoted identifiers security fix si tam zrušit ?
Nebo si v tom vlastnim driveru prevadet nazvy tabulek na velky pismena, je to nic moc, ale asi lepší než uvozovky zrusit.
- Petr Motejlek
- Člen | 293
To převádění na upper case už ve vlastním driveru zní asi nejlíp – nebo použij namísto např. [id] ⇒ [ID] – to ti bude fungovat, i když nebudeš měnit DB schéma.
Pro příště a pro všechny — používejte Dibi i pro CREATE příkazy (nebo si ručně „ouvozovkujte“ identifikátory).
- ventil
- Člen | 3
Nakonec jsem tedy zvolil variantu UpperCase (vlastní
drivers/oracleuc.php
s třídou DibiOracleUCDriver
),
tak abych u nových projektů (kde budu datový model teprve tvořit)
používal originální třídu.
Až se někdy dostanu k případné změně (aktualizaci) datového modelu
této aplikace, pak už si dám na identifikátory v
CREATE TABLE ...
či u
CREATE OR REPLACE VIEW ...
bacha.
Díky všem za rady.