Van egy régi PHP kód, ami adatbázisból generál tartalmat.
A tartalom generálásához a következő feltételt használja: "WHERE statusz = 'Aktív'". Igen, ékezetes karakter van a feltételben. A PHP forráskód ISO-8852 kódolású, mint ahogy az adatbázisban is latin2 karakterkészlettel tárolódnak az adatok, latin2_hungarian_ci használatával. A generált HTML tartalom is ISO-8859-2 kódolású.
Minden tesztelésre használt böngészőnkben rendben lefut a kód, és helyes kódolású tartalmat generál.
De a naplóban ritkán GET kérelmek esetén megjelenik a következő hibaüzenet:
"PDOException: SQLSTATE[HY000]: General error: 1267 Illegal mix of collations (latin2_hungarian_ci,IMPLICIT) and (utf8_general_ci,COERCIBLE) for operation '=' ... "
Elképzelni sem tudom, hogy milyen kérelmeket küldhetnek ilyenkor a böngészők. A napló alapján az URL ugyanaz, mint a tesztelésre használt URL, tehát gondolom, valamilyen spéci header-t küldenek, vagy épp valamit nem küldenek ... nem tudom. Azt meg végképp nem, hogy ez hogyan befolyásolhatja a fixen lekódolt PHP-ból indított SQL kérés karakterkészletét.
Az SQL kérelemben nem szerepel semmilyen egyéb paraméter, amit a kérelem küldhetne.
Ha bárkinek van használható ötlete, örömmel olvasnám.
Hozzászólások
Nem megoldás a karakterkódolásra, de érdemes lehet átgondolni ezt a statusz mezőt, mondjuk egy int segítségével kódolni az értékeket. Ez nem csak ezt a problémát oldaná meg, hanem az a kellemetlen helyzet is elkerülhető, hogy hibás eredményt kaptok, ha "Aktív" és "Aktiv" vegyesen szerepel.
Debian - The "What?!" starts not!
http://nyizsa.blogspot.com
Sajnos egyelőre ez nem járható út. Ez egy élesben futó nagy rendszer, az adatszerkezeten nem tudok módosítani. Természetesen én is örülnék, ha a kód kicsit barátibb lenne, de most elsődleges feladat megtalálni a hiba okát, és megoldani.
A hiba valódi oka az el...ott adatszerkezet, tehát azt kell megjavítani. Vagy minimum a lekérdezést, ami az ékezetes mezővel operál átvakarni - mondjuk WHERE UPPER(statusz) LIKE 'AKT%'
Ami a hibaüzenetből nekem lejön, az az, hogy az egyik az multibyte, a másik meg nem, és ezekre nem vizsgálhatsz egyenlőséget, ami valahol jogos is... Hogy miért érkezik az "=" egyik oldalára multibyte-os string, na az jó kérdés...
Szerintem nem az a fő kérdés, hogy miért nem jó, hanem az, hogy hogyan lehetséges az, hogy ezer lekérésből 999 esetben jó, 1 esetben pedig nem? Mi lehet a különbség a kérelmek között, és hogyan hathatnak így a scriptre?
Mondjuk az, hogy máshol van a hiba, mint ahol gondolod?
Ebben a hibaüzenetben van PHP-sorszám is?
Szemfüles vagy! :) A php sorszám az '=' jel utáni ... helyén van. A hibaüzenet tartalmazza a konkrét SQL kódot is, amivel baja van, és az abban a php fájlban fordul elő egyedül, tehát elég jól beazonosíthatóan a PHP indítja el a hibás SQL kérést.
Off: Boldogult úrfikoromban magam is sok hibakeresésben vettem részt, és valahogy azt figyeltem meg, hogy mindig a konkrét információk (teljes hibaüzenet, programrészlet, táblaleírás stb) segítenek, nem pedig a helyzet igazságtalansága fölötti meditáció.
Hányszor éltem át én is azt, hogy órákon keresztüli sikertelen hibakeresés végén végül betűről betűre elolvastam a hibaüzenetet, és az vezetett nyomra ... :)
De megnyugtatlak, megnéztem a hibában jelzett sor, és ott nem volt más, mint a PHP kódban közvetlenül megadott SQL lekérdezés, ami a hibaüzenetben is szerepelt.
Ott lesz a megoldás tippre, egy rossz enkódolású karakterláncot ad át valami, és az hívódik meg.
Igen, én is ezt tippelem, csak ugye nem ez a kérdés, hanem az, hogy 1000-ből miért csak 1-szer rossz a fixen beírt karakterlánc kódolása, a többi 999 esetben miért nem rossz? Ugyanis mind ékezetes karakter, ami az SQL-ben szerepel, az ott van közvetlenül megadva a PHP kódban. Nem kívülről jön, nem más PHP fájlok include-jával kerül be, hanem abban a PHP fájlban van konstansként megadva.
az nem lehet, hogy az adatbazis mezo/tabla collation-je valtozik valami kulso hatasra a php-tol fuggetlenul? (script/job/trigger/stb)
Support Slackware: https://paypal.me/volkerdi
Köszönöm, ez egy olyan lehetőség, amire nem is gondoltam eddig.
Ha a hibaüzenet következetesen sorolja fel az illesztéseket, akkor az adatbázisbeli collation rendben van, és az = jobb oldalán lévő string konstanst illesztené utf-8 szerint. Ebből arra gondolok, hogy nem az adatbázissal lesz a gond. Ennek ellenére legalább egy új irány, amerre keresgélhetek.
Az a konstans az milyen encoding-gal íródott fájlban van...?
Az ilyen dolgokat nem a kőkorszakba való visszatéréssel kell elkerülni, hanem megfelelő input validációval, check constraintraintekkel, stb.
A böngésző nem áll kapcsolatban a mysql-szerverrel (vagy ki tudja, lassan a CPU mikrokódja is JavaScript), szóval inkább PHP-oldalon kellene nézelődni. Kezdetnek: ugye volt
set names 'latin2'
(vagymysqli_set_charset('latin2')
) ?Szerk: azt írja az internet, hogy az '=' nem feltétlenül '='-t jelent, más esetben is előfordulhat, hogy két mező egyezését vizsgálja a szerver, mondjuk egy "UNION" esetén (a duplaszűrés miatt).
Erre írtam, hogy minden általunk futtatott tesztben helyesen fut a kód. Ez egy fix url, még csak egyedi paramétereket sem kap.
Én is azt hittem, hogy a böngésző nem hat a szerveroldali szkript karakterkódolására, de ha ezerből 1-szer ilyen hibát ad úgy, hogy nincsenek kívülről jövő paraméterek, akkor mégsem tudok másra gondolni.
Amúgy PDO és nem mysqli, de igen, beállítottuk a mysql felé a karakterkészletet.
Konkrétan a csatlakozás parancs a következő:
em lehet hogy valamelyik tábla mégis más kódolású és némely lekérésnél van csak behivatkozva péládul joinnal?
(Sőt nem is táblánként, hanem mezőnként lehet különböző karakterkódolást/collationt beállítani.)
A web szerverről nem volt szó, annak is van default és vhost esetén is karakter kódolás beállítása. Olyat láttam régebben, hogy több vhost volt, és egyiken nem volt jól beállítva minden, hasonló hibát hozott.
Apache esetén .htaccess file a site rootban is tartalmazhat ilyet.
Másik ok, ami okozhatja: kézzel a Firefoxban például át tudom állítani az enkódolást menüből, és akkor a form azzal a karakterkészlettel küld adatokat. Ez is lehet.
Tippre állami projekt vagy a fejlesztő egyik első munkája ez. Én csak állami projektekben láttam hasonlókat, de hát valakinek azt is el kell készíteni.
Ha még nincs itt, eljön majd az, hogy indiai, filippínó juniorok írják a Magyarország.hu új verzióját, akik a vállalkozói lánc negyedik, ötödik szintjén lesznek csak. (ahol régen a legolcsóbb informatikus volt)
A webszerver apache, és a .htaccess fájlok nincsenek engedélyezve.
Az űrlap karakterkészletével már nekem is volt gondom, és ha ez egy POST kérelem lenne, vagy legalább egy GET FORM url, akkor ki is tudnám próbálnám, de itt nincs űrlap. Azonban ahogyan az űrlap elküldi a karakterkészletet, gondolom a böngésző is küldhet valamilyen accept header-t, amiben jelzi, hogy milyen karakterkészletben várná az url tartalmát, és amit a webszerver még a PHP futtatása előtt értelmez.
A PHP generál saját header-t a válaszhoz, amiben beállítja a karakterkódolást, tehát az Apache AddDefaultCharset értéke elvileg nem juthat érvényre. Azért a biztonság kedvéért most ezt is beállítottam, de logikusan ez nem lehet a megoldás.
[off]
Az állami tipp nem jött be. Meglepő módon ez egy élő piaci vállalkozás, ahol az eredeti tulaj anno a "legolcsóbb" megoldást választotta, egy önjelölt programozó személyében...
"egy önjelölt programozó" kontra ,,"legolcsóbb" megoldás'' - a kettő csak első látásra van pariban... Most például kiderült, hogy az "olcsó" megoldáshoz még kell x óra debug/fixálás, hogy rendesen működjön, illetve utána ennek - és a vélhetően szép számmal a kódban lévő hasonló "egyszerű megoldások"-nak - a kigyomlálása is szép és az időt bőségesen zabáló feladat lesz...
Egyrészt ez így van.
Másrészt azonban hiába dolgozom évtizedek óta PHP-val, mégsem tudom, mi állhat a jelenség mögött, így számomra mindenképp hasznos továbbtanulási lehetőség ez az eset. :)
[on]
akkor én klónoznám a rendszert és teszt környezetben próbálnám a hibát előhozni
ha valami oknál ott is előfordul, és nem tudni, mitől, akkor teljes mysql logolást kapcsolnék be, és ott látszódna, hogy mi után jön ez, akkor a kódban is megkereshető, hogy merre lehet
az élő rendszeren is növelném a logolást, hátha kiderül valami, access log, error log, bármi
megnézném a sémában vagy bárhol máshol, hogy hol van utf8_general_ci
honnan jön az "Aktív" szó? hány helyről? ott mi az enkódolás? minden esetben jó? ha megnyitod latin2 módolású editorral, mindenhol jól látszódik az "Aktív" szó? Lehet olyan is, hogy Latin2 kódolású fájlban utf-8-ként szerepel ez a szó, mert olyan editorral nyúltak hozző, ahol ez volt az encoding. Az is okoz hasonlót. Kb ezt fogod ott látni: "AktĂv". Ha pedig fordítva: "Akt"[xED]"v". Az [xED] egy nem megjeleníthető karakter.
[off]
Kb ugyanezek a személyek dolgoznak sokszor az állami projekteken is, mert más nem vállalja az adott áron/feltételekkel. Tehát a "személyt" kb eltaláltam, a megrendelőt nem.
Tesztelni azért nehéz teszt környezetben, mert semmilyen módon nem tudtuk még reprodukálni a hibát. Próbáltuk az access.log-ban a User-Agent alapján beazonosított böngészőkkel, de azokkal sem reprodukálható a hiba. Sőt, nem is csak egyféle böngészőben jön elő. Generálta már I-phone kliens, de Windows böngésző is.
Tehát tesztelném, ha tudnám...
Emiatt is nyitottam ezt a témát, már több ember több extrém esetbe ütközött már. Hátha valaki valamikor látott már hasonlót, vagy van ötlete, mi lehet az a környezeti paraméter, amivel érdemes lenne tesztelni. Elvégre a hiba nem lehet túl bonyolult. Valahogy egy GET kérést kell elindítani, hogy a PHP-ban foglalt string konstans karakterkódolása befolyásolható legyen.
Végül mi volt a megfejtés?
db-n belul egy tobb tablat is erinto query-ben az egyik tabla ikyen, a masik meg oyan kodolasu.(marmint kulonbozik a collartion isezaltal)
information _schema megmondja, hogy melyik
Gondolom a péklapát apróra van törve a kódot elkövető hátán...
Állami projekteknél, feltörekvő vállalkozóknál az ékezet használata hasonló módon teljesen megszokott, az a szint. Meg hogy egy óriás queryben hívnak le mindent, így nem tud működni a cache. Ezért egy lekérdezés másodpercek a sok left join meg hasonlók miatt. Meg nincsenek indexek, stb.
Alvállalkozó alvállakozójának alvállalkozójának az ismerőse készítette a kódot, aki még gimibe jár, de már készített több honlapot! :)
És gondolom a "select * from *" jellegű lekérdezés eredményét péhápéból szűri/rendezgeti...
Van az az use-case, amikor gyorsabb ;)
Sajnos nincs megfejtés azóta sem. Egyelőre együtt élünk a hibaüzenettel, mivel ritka. Valós ügyfél még nem jelezte, pedig reméltem, mert akkor lenne infó a kliens környezetről.
Amúgy nem állami szféra, hanem olcsóban dolgozó - valószínűleg önképzett - vállalkozó műve volt, aki azóta már eltűnt.
ezt nezted? miert nem?
https://hup.hu/comment/2885810#comment-2885810
Igen, és megvallom, nem is értettem, hogyan jön ide. Arról van szó, hogy teljesen azonos GET kérelmek néha hibát okoznak, néha nem. Ugyanarról a tábláról, ugyanarról a mezőről van szó.
(vagy valami ilyesmi)
De azért jól emlékszem, ugye, hogy végülis nem idézted be sem a teljes hibaüzenetet, sem a releváns programrészt?
Arra gondolok, hogy a probléma oka az lehet, a get nem feltétlen abból html outputból érkezik, amit várnál.
Hiba esetén loggolni kellene a felhasználói adatokat, mint pl https://www.php.net/manual/en/function.get-browser.php
Ez jó ötlet, nem ismertem. Az Apache logja alapján próbáltam a böngészőt beazonosítani, és valami összefüggésre rájönni, de sikertelenül. Ez lehet, hogy többet el fog árulni.
Tippjeim:
- valaki ezer éves böngészővel tolja, ami nem mainstream
- fixre vette valamelyik user az char kódolást
- egy bot nyomja a get-et
Ps.: A kódra ráférne egy refaktor
nem, ez nem jo otlet, teljesen fals. futtasd mar le azt a kurva INFORMATION_SCHEMA-s query-t!
Ha ez lenne a baj, akkor kb minden írás gond lenne. Nem?
a hibauzenet egyertelmuen azt sugallja, ezert kellene lefuttatni vegre.
Értem, de azt is írja, hogy nem mindig csinálja. Sőt! Nagyon ritkán.
jol van, en kiszalltam, oldjatok meg, have fun!
Megoldástól bármi nagyon messze van. Üvölt az egész a trógerságról. Ennek a mezőnek, bool, enum -nak kellene lennie, nem stringnek, valamint mindennek utf8-nak így 2023-ban.
Nem, ez egy speciális, ritkán használt tábla (és/vagy programrész), mondjuk áfabelföldi lemúrok esetére.
Haladt valamit mostanában? Még mindig nincs jobb gondolatom, mint hogy a táblák között van olyan ritkán használt nünüke, aminek a charset/collate értéke különbözik a többiétől.
mar az elejen ezt mondtam, de az OP lathatoan l*szarja
Az OP nem leszarja, hanem már elmondta, hogy olyan fix kérelmekről van szó, amik mindig ugyanazon a táblák ugyanazon mezőit használják. Nem tábladefiníciós problémáról van szó, mivel a kérelmek 99%-ában hibaüzenetek nélkül lefutnak ugyanazok a kérelmek, amik - és megint ismételem - ugyanazokból a táblákból ugyanazokat a mezőket használják.
Azért beidézhetné a derék OP a komplett SQL utasítást...
Off: közben fájlba gépeltem ezt is, hátha jól jön valamikor valakinek:
https://lzsiga.users.sourceforge.net/ekezet.html#Q0227
hmm jo kis gyujtemeny, boormarkoltam, 1x meg jol johet nekem is, bar azert ebbol sokat en is tudtam mar