Ékezetes betűk -- voltam már boldogabb


YaSql> select 'árvíztűrő tüköfúrógép' from duale;

select 'árvíztűrő tüköfúrógép' from duale
ORA-00942: table or view does not exist (DBD ERROR: error possibly near <*> indicator at char 36 in
'select 'árvíztűrÅ� tüköfúrógÃ<*>©p' from duale')

Pedig azt hallottam, hogy az UTF8 bevezetése mindent megold.

Szerk:
https://stackoverflow.com/questions/79309127/does-perl-c-api-have-an-ut…
https://github.com/lzsiga/DBD-Oracle/commit/3aaf6d206cf5d4b3b40ac876607…

Hozzászólások

Hányas Orákulum?

Az UTF8 önmagában semmit nem old meg. Azt végig is kell vezetni a rendszeren.

https://lzsiga.users.sourceforge.net/ekezet.html

Azt még nem mondtam, hogy ezt én írtam, szóval a triviális gondokat már kezeltem volna.

Most azt kellene megnézni, hogy a DB-től jövő hibaüzeneten rajta van-e az 'is_utf8' jelző, meg az eredeti SQL-utasításon ugyanez. (Mindkettőre 'igen' válasz kellene.)

Jogos, megnéztem jobban. Érdekesség, hogy a hibapozíció számolását hasonlóan rontja el, csak ő az utasítás alá tesz egy csillagot, nem bele az utasításban.


SQL> select 'árvíztűrő tükörfúrógép' from duale;
select 'árvíztűrő tükörfúrógép' from duale
                             *
ERROR at line 1:
ORA-00942: table or view does not exist

SQL> select 'arvizturo tukorfurogep' from duale;
select 'arvizturo tukorfurogep' from duale
                                     *
ERROR at line 1:
ORA-00942: table or view does not exist

Szerkesztve: 2024. 12. 23., h – 12:47

Első ránézésre azt mondanám, hogy van egy DBI::errstr nevű változó, ami szerintem jobb lenne, ha UTF8-ban lenne. [Szerk: mármint abban van, csak nincs beállítva az 'is_utf8' jelzőbit rajta]
Lásd még ezt: https://metacpan.org/pod/DBI#set_err

Ahogy most érteni vélem, hogy a Perl source kétféle kódolásban lehet (mármint az interpreter szerint), az egyik az UTF-8 ('use utf8'), a másik a 'mitbánomén' ('no utf8').

Ha az utóbbit konvertálni akarjuk utf8-ra/-ról, azt csinálhatjuk úgy, hogy explicit megadjuk a használt kódolást (Encode modul), vagy a default-ra hagyatkozunk (utf8 modul), ami az ISO-8859-1.

Szerkesztve: 2024. 12. 22., v – 22:19

Ez valamit segített, de nem 100%


       my $err = $DBI::errstr;
+      _utf8_on($err);
       debugmsg(3, sprintf("line %d DBI::errstr='%s' is_utf8=%d", __LINE__, $err, is_utf8($err)));

Ezt sikerült vele:

ORA-00942: table or view does not exist (DBD ERROR: error possibly near <*> indicator at char 36 in 'select 'árvíztűrő tüköfúróg\xFFFD<*>\xFFFDp' from duale')

Vagyis bele akarta illeszteni a stringbe a <*> részt, és ügyesen kettévágott egy utf8 szekvenciát. (Ezt a DBD-Oracle csinálja, azon belül az oci8.c)

Van egy DBI->connect, azon belül attributes, azon belül ora_charset=>'AL32UTF8', ora_ncharset=>'AL32UTF8'

Lesz is belőle egy OCINlsEnvCreate(cset=873,ncset=873), ami titkos kód az AL32UTF8-ra (dbdcnx.c)

Szerkesztve: 2024. 12. 26., cs – 09:12

Most úgy tűnik, hogy lenne egy pont, amikor utf8-ra konvertál [szerk: illetve nem konvertál, csak ellenőriz, és ha valid utf8, akkor beállítja az is_utf8 jelzőt], csak sajnos ezt akkor tenné, amikor már belerakta a <*> stringet egy utf8-szekvencia közepébe. Pedig ebben a történetben mindenki csak segíteni akart...

Kicsit megszórtam debuggal, azt vélem látni belőle, hogy a sv_insert az insert-offset-et byte-ként értette, az Oracle viszont character-ben adta. Ezt abból vélem gondolni, hogy az error-offset ékezetmentes változatban is 37.

/-----
oci8.c:ora_sql_error:1001 before insert offset=37
DO_UTF8=1 len/bufsize=53 cur=51 ptr=0x20126e0
0               1                        2                            3
012345678   9   012   3   456   7   89   0    12   3   45   6   789   0   12   3   45   6   7
0                1                                      2                                      3
012345678       901       234       56        78       90       123       45       67       7890123456
select '\xc3\xa1rv\xc3\xadzt\xc5\xb1r\xc5\x91 t\xc3\xbck\xc3\xb6rf\xc3\xbar\xc3\xb3g\xc3\xa9p' from duale
\-----
/-----
oci8.c:ora_sql_error:1003 after insert offset=37
DO_UTF8=1 len/bufsize=80 cur=54 ptr=0x20126e0
select '\xc3\xa1rv\xc3\xadzt\xc5\xb1r\xc5\x91 t\xc3\xbck\xc3\xb6rf\xc3\xbar\xc3\xb3g\xc3<*>\xa9p' from duale
\-----
Szerkesztve: 2024. 12. 27., p – 21:17

Mikor már azt hittem, hogy kész vagyunk, hangyányi probléma akadt az OCIAttrGet(OCI_ATTR_PARSE_ERROR_OFFSET) művelettel: amit visszaad, az byte-ban értendő, mégpedig úgy, hogy a szerveroldali NLS_CHARACTERSET-be konvertálva milyen byte-offseten van az error. Az egyetlen kis probléma az, hogy mi kliensoldalon vagyunk, és nem tudjuk, hogy mi a szerveroldali NLS_CHARACTERSET.


# kliens(NLS_LANG) szerver(NLS_CHARACTERSET) offset értelmezése kliens-oldalon
1 EE8MSWIN1250     EE8ISO8859P2              pont jó
2 EE8MSWIN1250     AL32UTF8                  csökkentendő
3 AL32UTF8         EE8ISO8859P2              növelendő
4 AL32UTF8         AL32UTF8                  pont jó

A korábbi állapotban jó volt a 1-es és 4-es sor; miután hozzápiszkáltam, jó lett az 1-es és a 3-as. Ennél jobb eredményt csak akkor érnénk el, ha tudnánk az NLS_CHARACTERSET-et.

Off:szintaktikai bővítésen gondolkozom, hogy explicit megadhassuk a charset-et, hogy pl.:

YaSql> @test0021.sql
Processing file './test0021.sql' in 'UTF-8' encoding (from LC_CTYPE)

YaSql> @ISO-8859-2:test0021.sql
Processing file './test0021.sql' in 'ISO-8859-2' encoding (explicit)

YaSql> @UTF-8:test0021.sql
Processing file './test0021.sql' in 'UTF-8' encoding (explicit)