Булевы значения в MySQL, Perl DBI и JSON - PullRequest
3 голосов
/ 20 июля 2011

Рассмотрим простую таблицу mysql со столбцами id (целое число) и flag (логическое значение). Пользовательский интерфейс, написанный на JavaScript, взаимодействует с бэкэндом CGI через JSON как для получения данных из таблицы, так и для их обновления.

Теперь при отправке данных {id: 5, flag: true} на сервер я, конечно, использую from_json, чтобы получить хеш perl (ref). Тогда

my $sth = $dbh->prepare('UPDATE my_table SET flag = ? WHERE id = ?);
$sth->execute($data->{flag}, $data->{id});

всегда приводит к вставке ложного значения. Я полагаю, что это происходит из-за магического поведения JSON :: true и JSON :: false, которые преобразуются в 'true' и 'false', соответственно (но нумеруются до 1 и 0). По-видимому, оператор execute обеспечивает строковый контекст, а не числовой контекст, поэтому сервер MySQL получает строку, не содержащую чисел, что затем приводит к вставке значения 0. Сейчас я исправляю это, поставив ? 1 : 0 после $data->{flag}.

В другом направлении происходит обратное: согласно документу DBI «Большинство данных возвращается в скрипт Perl в виде строк.», Поэтому, когда я нажимаю на результат запроса SELECT с помощью to_json, значения принимаются пользовательским интерфейсом в виде строк JavaScript «0» и «1», которые являются истинными в JavaScript. Так что сейчас я делаю $_->{flag} += 0 foreach (@result) перед применением to_json.

Вопрос: В какой точке цепи я должен вставить эти «хаки»? В конце JavaScript я мог, например, убедиться, что вместо значений true и false были отправлены значения 1 и 0, а флаги перечитаны как числа. Есть ли что-то, что я могу сказать DBI, чтобы он возвращал числовые столбцы как (скаляры, которые JSON будет рассматривать как) числа?

1 Ответ

3 голосов
/ 20 июля 2011

Был там и сделал это. Первоначально я добавил 0 к числам в JSON, который мы декодировали в Perl, но это было утомительно и отнимало много времени, потому что мне приходилось обходить большую структуру, добавляя 0 ко всем числам. Затем я помог Тиму Бансу добавить sql_type_cast в DBI, чтобы несколько незначительных изменений в DBD :: Oracle могли использовать его для возврата чисел вместо строк (они все еще являются скалярами Perl, но с некоторыми внутренними изменениями - см. Ниже) .

Проблема, с которой я столкнулся, заключалась в том, что я использовал JSON :: XS, и он просматривает скаляры в encode_json, чтобы увидеть, установлен ли pv или iv, чтобы определить, следует ли создавать «0» или 0 в кодированном JSON. Sql_type_cast и новый атрибут DBIstcf_DISCARD_STRING в DBI означают, что теперь я связываю числовые столбцы как $ s-> bind_col (1, \ my $ col, {TYPE => SQL_INTEGER, DiscardString => 1}) и sql_type_cast удалит скалярный pv, если он выглядит следующим образом число. Проблема в том, что DBD нужно изменить, чтобы использовать sql_type_cast. DBD :: Oracle изменен, и я просто изменил DBD :: ODBC в 1.31, чтобы сделать это.

Возможно, вы могли бы изменить DBD :: mysql таким же образом или убедить кого-то другого (я не использую mysql).

См. здесь для подробного обсуждения реализации DiscardString и т. Д.

Вы можете найти тест в DBD :: ODBC с именем sql_type_cast.t, который проверяет работу DiscardString без использования JSON :: что угодно.

ОБНОВЛЕНО: еще одна ссылка на обсуждение dbi-dev

...