5 мая 2011 г.

Value exceeds the range for valid dates

Придешь на работу с наилучшими намерениями, а в результате битый день носишся вокруг костра и стучишь в бубен. Получили мы доисторическую клиентскую базу Гедымина, еще на Yaffil-e. Внешне она не выглядела поврежденной: gfix не сообщал об ошибках, и архивирование-восстановление проходило без проблем. Но, в процессе апгрейда под Firebird 2.5, конвертер слетал напрочь.

Каких только действий не предпринималось. Перекомпилировали процедуры и триггеры, перерегистрировали внешние функции, перепробовали разные сборки серверов, удаляли подозрительные метаданные — все безрезультатно. Когда попробовали вручную перевести базу под Firebird 2.0, в процессе восстановления из архива наконец-то появилось более-менее осмысленное сообщение: "value exceeds the range for valid dates gds_$receive failed". Каким-то образом, поле типа дата содержало значение, которое Yaffil считал допустимым, а Firebird категорически отказывался принимать.

Предпринятая сходу попытка переприсвоить все поля типа дата запросами вида:
update gd_document set documentdate = documentdate
привела к уходу сервера "в себя". Стало ясно, что сначала надо определить проблемную таблицу, затем найти в ней нужные строки и работать с ними. С помощью запроса ниже был сформирован скрипт:
select
  'select max( ' || r.rdb$field_name || 
  ') from ' || r.rdb$relation_name || ';'
from
  rdb$relation_fields r
    join rdb$fields f on 
      f.rdb$field_name = r.rdb$field_source
where
  f.rdb$field_type = 13
order by
  r.rdb$relation_name
При его выполнении в IBExpert на таблицах с некорректными данными появляется сообщение "Invalid data cast". В нашем случае неверная дата находилась в поле documentdate где-то в таблице gd_document. Далее, с помощью прокрутки результата запроса:
select id, documentdate from gd_document order by id
выходим на запись, соседнюю с проблемной. Сама плохая запись не может быть прочитана — кидает ошибку. Убираем из запроса поле documentdate и определяем id нужной нам записи. Затем, или удаляем ее, или присваиваем полю корректное значение.

1 мая 2011 г.