[megoldva] Postgresql, quote_literal, pg_escape_literal, like

Lehet valahogy ötvözni PostgreSQL-ben a felhasználói input levédését és a like '%...%' kulcsszót?
Ezt ugyan szintaktikailag elfogadja a psql, csak nem azt adja, amire számítok: select * from t1 where c1 like '%'||quote_literal('the')||'%';

Szerk; egy nulladik megoldás ez: '%'||substr(quote_literal('the'),2,char_length('the'))||'%';
Egy fokkal szebb PHP-ből az előkészítés:
$inp = pg_escape_literal('%' . mb_convert_case($mb, MB_CASE_LOWER) . '%');
$where='lower(c1) like ' . $inp;

Lehet, hogy rossz nyomon vagyok, és a szabad szavas keresést csak bonyolultabban lehet megoldani, pl. így: http://rachbelaid.com/postgres-full-text-search-is-good-enough/ - https://www.postgresql.org/docs/9.1/static/textsearch-controls.html (to_tsvector)...

Hozzászólások

Csak tipp, de te konnyebben ki tudod probalni:
select * from t1 where c1 like ('%'||quote_literal('the')||'%');

vagy:
select * from t1 where c1 like concat('%',quote_literal('the'),'%');

A tied mivel ter vissza? Miben rossz?

--
If you get a good wife, you'll become happy; if you get a bad one, you'll become a philosopher. -Socrates

Igazad van!!! Merthogy nem azt adja, amit szeretnék; a kezdő/záró aposztrófot is visszaadja: %'the'%
Akkor azt a két aposztrófot kell valahogy substringgel leszedni és kész. :-)
Úgyhogy ez pl. megoldja a kérdést: '%'||substr(quote_literal('the'),2,char_length('the'))||'%';
- de lehet, hogy van frappánsabb aposztróf-elhagyás is, mondjuk a trim – bár az macerás az aposztróffal körülzárt aposztróf levédése miatt.

Miért kell a quote_literal? Ha a 'the' helyett valami felhasználói input van, akkor azt feladás _előtt_ kell escape-lned (vagy még jobb: prepared statement-et használni).

(szerk.: ja, és full-text searchre meg tényleg jó a tsvector-os megoldás, ott még indexed is lesz hozzá :) )

BlackY
--
"en is amikor bejovok dolgozni, nem egy pc-t [..] kapcsolok be, hanem a mainframe-et..." (sj)

Ha még nem vagy nagyon benne a projektben, akkor használj PDO-t: http://php.net/manual/en/pdo.prepared-statements.php
Ha már meg van a projekt és pg_*, akkor pg_escape_literal http://php.net/manual/en/function.pg-escape-literal.php

szerk.: a PDO Prepared statement oldalon a 6-os példa spec. pont az, amit keresel

BlackY
--
"en is amikor bejovok dolgozni, nem egy pc-t [..] kapcsolok be, hanem a mainframe-et..." (sj)

substr(strtolower(pg_escape_literal($inp)),1,-1);

Neee...

Egyrészt nem akarod lecsapni róla a string határoló jeleket (btw, nem tudhatod, hogy egy sima ' lesz-e, lehet E'lorem\tipsum' formájú, U&'d\0061t\+000061' formájú, dollar-quoted ($$lorem ipsum$$) stb.). Azért kéred a pg_escape_literal()-t, hogy tegye oda, hogy ott legyen :) Inkább a pg_escape_literal-nak adj kapásból olyat, amiben ott vannak a % jelek (nem fogja őket escape-lni)

Másrészt az strtolower és a substr vagy multi-byte safe vagy nem (ha be van töltve az mb_* _és_ engedélyezve van, akkor felülcsapja ezeket a függvényeket, de erre nem érdemes építeni).


$inp = pg_escape_literal('%' . mb_convert_case($mb, MB_CASE_LOWER) . '%');
$where='lower(c1) like ' . $inp;

(harmadrészt _tényleg_ érdemes a full-text indexelést használni ilyen kereséseknél, kis odafigyeléssel és jó indexeléssel [a pg doksijában szépen le van írva] retek jól működik)

BlackY
--
"en is amikor bejovok dolgozni, nem egy pc-t [..] kapcsolok be, hanem a mainframe-et..." (sj)

Van igazság abban, amit írsz; főleg azzal győztél meg, hogy a pg_escape_literal tényleg direkt teszi oda az aposztrófokat, és inkább előtte kell bevarázsolni a százalékjeleket.

Ez csak egy apró kis projekt, nem akarom még magam beleártani egy komolyabb indexeléses műsorba.