Does Perl C-API have an utf8-aware sv_insert variant?
03:50 26 Dec 2024

I am having some trouble with DBD-Oracle, when an SQL-statement has some problem and DBD-oracle inserts marker <*> at the error-offset via sv_insert.

With setting NLS_LANG=.AL32UTF8, the error-offset coming from Oracle should be interpreted in unicode-characters but sv_insert works in byte mode.

So I'd like to know if there is some sv_insert_utf8 variant hidden somewhere. Or perhaps some sv_substr_utf8 function would do as well.

Edit: the usage of sv_insert can be seen here: https://github.com/perl5-dbi/DBD-Oracle/blob/master/oci8.c#L943

Meantime I've hacked a half-finished solution:

if (nls_charset==al32utf8) { /*  */
    parse_error_offset= sv_pos_u2b_flags(sqlsv, parse_error_offset, NULL, SV_GMAGIC|SV_CONST_RETURN);
}

Demonstration of the problem in YaSql-Fx:

> select 'arvizturo tukorfurogep' from duale;
select 'arvizturo tukorfurogep' from duale
                                     *

ORA-00942: table or view does not exist (DBD ERROR: error possibly near <*> indicator at char 37 in 'select 'arvizturo tukorfurogep' from <*>duale')

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

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

In the second example the <*> marker has been inserted into an utf8 sequence, resulting \xFFFD<*>\xFFFD

Edit: This version seems working

{
    D_imp_dbh_from_sth;
    int utf8_is_implied = CSFORM_IMPLIES_UTF8(imp_dbh, SQLCS_IMPLICIT);
    if (utf8_is_implied) {
        parse_error_offset= sv_pos_u2b_flags(sqlsv, parse_error_offset, NULL, SV_GMAGIC|SV_CONS
    }
}

https://github.com/lzsiga/DBD-Oracle/commit/3aaf6d206cf5d4b3b40ac87660774e004040d152

Edit: Bad news: actually, the server returns byte-offset, interpreted according to NLS_CHARACTERSET. Which is not known by DBD-Oracle. But if it were known, conversion between NLS_LANG and NLS_CHARACTERSET might be non-trivial (just think of UTFE(872)).

perl xs