DBI :: sql_type_cast: DBIstcf_DISCARD_STRING - вопрос - PullRequest
1 голос
/ 12 марта 2011

Я надеялся, что DBI::sql_type_cast с флагом DBIstcf_DISCARD_STRING изменит $ sv с '4.8g' до 4.8.

(DBIstcf_DISCARD_STRING: «Если этот флаг указан, то когда драйвер успешно преобразует связанный скалярный perl в нестроковый тип, строковая часть скаляра будет отброшена.»)

Что означает возвращаемое значение sv could not be case and DBIstcf_STRICT was not used?

#!/usr/bin/env perl
use warnings;
use 5.012;
use DBI qw(:sql_types);

my $dsn = "DBI:Proxy:hostname=horst;port=2000;dsn=DBI:ODBC:db1.mdb";
my $dbh = DBI->connect( $dsn, undef, undef, { RaiseError => 1, PrintError => 0 } )
or die $DBI::errstr;

my $sv = '4.8g';
my $sql_type = SQL_DOUBLE;
my $flags = DBIstcf_DISCARD_STRING;

my $sts = DBI::sql_type_cast( $sv, $sql_type, $flags );

say $sts; # 1 (sv could not be case and DBIstcf_STRICT was not used)

say $sv;


# Argument "4.8b" isn't numeric in subroutine entry at ./perl6.pl line 14.
# 1
# 4.8b

Ответы [ 3 ]

5 голосов
/ 12 марта 2011
  1. Документация содержит опечатку - описание для $sts == 1 должно быть "sv not be cast " - то есть приведение к SQL_DOUBLE wasnЭто невозможно для значения, которое вы указали, и поэтому ничего не было сделано.

  2. DBIstcf_DISCARD_STRING означает нечто отличное от того, что вы хотите.Во внутренних терминах Perl это означает, что если вы передадите SV с POK и NOK и PV-частью "1.23" и NV-частью 1.23, вы получите SV с !POK и NOK и NV-частью1.23 - то есть сохраненная строковая часть скаляра будет недействительной, оставляя числовую часть нетронутой, поэтому любая будущая попытка использовать скаляр в качестве строки приведет к его преобразованию из числа в строку,Но обратите внимание, что это говорит о том, что это произойдет только , если приведение успешно , а приведение к SQL_DOUBLE не удачно, если значение не является допустимым числом для начала.«4.8g» не проходит тест.

  3. Вы можете очистить строковую часть значения почти так же эффективно, как DBI самостоятельно, просто выполнив$sv = 0 + $sv;, который очистит POK и произведет реконверсию в строку таким же образом.Разница между этим и тем, что делает DBI, заключается в том, что он на самом деле не очищает PV так, как DBI, а только помечает его как недействительный.Чтобы заставить значение очищаться немедленно так же, как DBI, вам нужно сделать что-то вроде

    $sv = do { my $tmp = 0 + $sv; undef $sv; $tmp };

    , но если у вас нет действительно хорошего объясненияа зачем тебе это нужно, так и не используй.:)

1 голос
/ 12 марта 2011

После прочтения документации и кода в DBI.xs (реализация в sql_type_cast_svpv) возвращаемое значение 1 означает, что «значение не может быть преобразовано корректно, и DBIstcf_STRICT не использовался'.

Принимая ключевую часть этой функции, в вашем случае:

case SQL_DOUBLE:
    sv_2nv(sv);
    /* SvNOK should be set but won't if sv is not numeric (in which
     * case perl would have warn'd already if -w or warnings are in effect)
     */
    cast_ok = SvNOK(sv);
    break;

....

if (cast_ok) {

    if (flags & DBIstcf_DISCARD_STRING
    && SvNIOK(sv)  /* we set a numeric value */
    && SvPVX(sv)   /* we have a buffer to discard */
    ) {
        SvOOK_off(sv);
        if (SvLEN(sv))
            Safefree(SvPVX(sv));
        SvPOK_off(sv);
        SvPV_set(sv, NULL);
        SvLEN_set(sv, 0);
        SvCUR_set(sv, 0);
    }
}

if (cast_ok)
    return 2;

SvNOK должен быть установлен для вас.Не углубляясь в sv_2nv, суть проблемы заключается в том, что «4.8g» не является числовым типом, поскольку числовой флаг в скалярном значении не установлен (это то, что проверяет SvNOK).

Мое предложение, используйте регулярное выражение, чтобы убрать этот ввод перед вызовом sql_type_cast.

0 голосов
/ 14 марта 2011

Опечатка в документации теперь исправлена ​​в стволе Subversion.

Вот краткое объяснение, почему был добавлен sql_type_cast.

Хотя ничто не мешает вам использовать sql_type_cast, это былоспециально добавлено для драйверов (DBD) для приведения данных, возвращаемых из базы данных.Первоначальная проблема, которую он решил, состояла в том, что целые числа в основном связаны как строки, поэтому, когда данные возвращаются из базы данных, устанавливается скалярный pv.Некоторые модули, такие как JSON :: XS, умны и смотрят на pv, чтобы решить, является ли скаляр числом не так.Без sql_type_cast JSON :: XS преобразовывал скаляр, содержащий 1, но с pv, установленным на «1» вместо более короткого 1 в преобразованиях JSON.

Насколько мне известно, только DBD :: Oracle делает это прямо сейчасхотя это в TODO для DBD :: ODBC.

...