PostgreSQL bug s hledáním podle macaddr type a octet v uvozovkách

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

Ahoj ve spolek,

nevím zda se jedná o bug Nette či nikoliv, ale s největší pravděpodobností ano. O co jde.
Mám funkci v PGSQL, která hledá záznamy v tabulkách podle „macaddr“ type. Normálně to funguje přes query v SQL, ale v Nette vzniká problém.

Pokud ve vyhledávání použiji MAC 00:10:25:33:45:51, tak je to ok a projde to.
Pokud ve vyhledávání použiji MAC 00:10:25:3B:45:51, tak je to ok a projde to.
Pokud ve vyhledávání použiji MAC 00:10:25:B3:45:51, tak to vyhodí laděnku a chybu ve špatném syntaxu, kdy z nějakého divného důvodu se do dotazu cpou v adrese uvozovky tam, kde je na začátku octetu písmeno a pak adresa vypadá v dotazu takto:

00:10:25:"B3":45:51

Samozřejmě díky tomu to nefunguje.

Používám Nette 2.0.10.

Kdyby někdo věděl kde je problém, tak bych byl vděčný. Dík.

PS: udělal jsem si dump před odesláním query na backend Nette a tam je vše v pořádku, tedy chyba není třeba v přeformátování při odeslání formuláře

PPS: jo a ještě detail, funkce v PGSQL bere macaddr jako argument type text, nevim, ale třeba to pomůže, že i tam by mohl být zakopaný pes – musel být použit type text, protože EXECUTE nemíchá typy

Editoval heekon (3. 10. 2013 10:57)

hrach
Člen | 1844
+
0
-

No tak hlavne nam rekni, jaky dotaz to posila? A jak ho volas.

heekon
Člen | 28
+
0
-

hrach napsal(a):

No tak hlavne nam rekni, jaky dotaz to posila? A jak ho volas.

No, funkce může vypadat asi takto (resp. vypadá):

CREATE OR REPLACE FUNCTION getdevicebymac(macaddr text)
  RETURNS SETOF devicedata AS
$$
DECLARE
    tables record;
    devRow devicedata%ROWTYPE;
BEGIN
    FOR tables IN SELECT * FROM mactables LOOP
        EXECUTE 'SELECT * FROM ' || tables.table_name || ' WHERE mac = \'' || macaddr || '\'' INTO devRow;
        IF devRow.mac IS NOT NULL THEN
        RETURN NEXT devRow;
        END IF;
    END LOOP;
    RETURN;
END;
$$
  LANGUAGE plpgsql VOLATILE;

Volám pak dotaz:

$result = $this->connection->table("getdevicebymac('".$mac."')")->select('ip,vlan')->where(array("family(ip)" => 4))->limit(1)->fetch();

Laděnka vyhodí → pokud hledám mac e0:b2:4e:25:21:99:

SELECT "ip","vlan"
FROM getdevicebymac('"e0":"b2":4e:25:21:99')
WHERE (family("ip") = ?)
LIMIT 1

Asi může být problém i v PDO, že si upravuje dotaz dle typu argumentu, ale pak bych tedy potřeboval obejít tenhle zásah „shora“. Jak jsem uvedl, proměná $mac v query je v pořádku, když ji dumpnu ještě před provedením odeslání dotazu.

Editoval heekon (3. 10. 2013 11:22)

hrach
Člen | 1844
+
0
-

No, problem je, ze natvrdo busis spojeni stringu, misto toho, aby si pouzil placeholder. Smula je, ze ten u table() nepodporujeme. Funguje volani funkce s uvozovkami? Pokud ano, tak to je pro tebe mozny fix, pokud ne, tak ne.

Nicmene: pro dane pouziti, co delas, je NAPROSTO nevhodne pouzivat Selection, nevyuzivas ani predikci pouzitych sloupcu, ani relace k resultsetu (ani by neslo). Takze to volej klasicky

$this->connection->query(
	'SELECT "ip", "vlan" FROM getdevicebymac(?) WHERE (family("ip") = ?) LIMIT 1',
	$mac, 4
);
heekon
Člen | 28
+
0
-

hrach napsal(a):

No, problem je, ze natvrdo busis spojeni stringu, misto toho, aby si pouzil placeholder. Smula je, ze ten u table() nepodporujeme. Funguje volani funkce s uvozovkami? Pokud ano, tak to je pro tebe mozny fix, pokud ne, tak ne.

Nicmene: pro dane pouziti, co delas, je NAPROSTO nevhodne pouzivat Selection, nevyuzivas ani predikci pouzitych sloupcu, ani relace k resultsetu (ani by neslo). Takze to volej klasicky

$this->connection->query(
	'SELECT "ip", "vlan" FROM getdevicebymac(?) WHERE (family("ip") = ?) LIMIT 1',
	$mac, 4
);

ok, děkuju za vysvětlení