При сопровождении баз данных 1С разработчики часто сталкиваются с ситуацией, когда после обновления типовой конфигурации или платформы стабильно работавшее расширение внезапно начинает вызывать критические сбои. При этом типовой код без расширения отрабатывает штатно, а включение расширения приводит к ошибке выполнения запроса в режиме «1С:Предприятие».
Рассмотрим типовой текст ошибки, возникающий при выполнении запроса:
{(11, 23)}: Неверные параметры в операции сравнения.
Нельзя сравнивать поля неограниченной длины и поля несовместимых типов.
СведенияОФайлах.Файл >В(&Файлы)
Проанализируем природу этого поведения, разберем причины его возникновения на уровне платформы и выясним, как правильно исправить ошибку без ущерба для производительности системы.
Посмотрим на исходный фрагмент условия в запросе, вызывающий ошибку:
ГДЕ
СведенияОФайлах.Файл В(&Файлы)
В типовых конфигурациях (например, в «1С:Управление нашей фирмой» при работе с подсистемой присоединенных файлов библиотеки стандартных подсистем) реквизит Файл имеет составной тип или ссылается на ОпределяемыйТип. Когда мы заимствуем определяемый тип или составной реквизит в расширение, платформа фиксирует статичный «снимок» метаданных на момент заимствования.
Выясним цепочку событий, приводящую к сбою:
&Файлы, в который попадают ссылки новых типов, добавленных обновлением.В (&Файлы) сопоставляет типы из переданного массива с типами реквизита СведенияОФайлах.Файл, известными в контексте расширения.Разберем по шагам правильное архитектурное решение. Главная задача — предоставить контексту расширения актуальную информацию о типах данных, присутствующих в основной конфигурации.
ОпределяемыйТип (или реквизит составного типа), на который ссылается поле запроса.&Файлы. Если объект не заимствован, платформа не сможет корректно построить соединение на уровне СУБД.Часто разработчики пытаются обойти проблему добавлением обращения через точку к реквизиту Ссылка:
ГДЕ
СведенияОФайлах.Файл.Ссылка В(&Файлы)
Разберем, почему так делать крайне не рекомендуется. Обращение через точку к составному типу вынуждает СУБД генерировать множественные LEFT JOIN ко всем физическим таблицам, входящим в состав типа. Это приводит к блокировкам, падению производительности и отключению индексов.
Если требуется изменить сам запрос без перезаимствования всех метаданных, рассмотрим безопасные альтернативы.
Вариант с явным приведением типа через ВЫРАЗИТЬ:
Если в конкретном контексте тип объектов заранее известен, используем оператор ВЫРАЗИТЬ:
ГДЕ
ВЫРАЗИТЬ(СведенияОФайлах.Файл КАК Справочник.НоменклатураПрисоединенныеФайлы) В(&Файлы)
Вариант с передачей параметров во временную таблицу:
Вместо передачи массива в условие ГДЕ ... В(...) загрузим список файлов во временную таблицу и выполним соединение:
ВЫБРАТЬ
ТВ_Файлы.Ссылка КАК Файл
ПОМЕСТИТЬ ВТ_ФильтрФайлов
ИЗ
&ТаблицаФайлов КАК ТВ_Файлы
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
СведенияОФайлах.Файл КАК Файл,
СведенияОФайлах.Размер КАК Размер
ИЗ
РегистрСведений.СведенияОФайлах КАК СведенияОФайлах
ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_ФильтрФайлов КАК ВТ_ФильтрФайлов
ПО СведенияОФайлах.Файл = ВТ_ФильтрФайлов.Файл
При соединении таблиц оптимизатор СУБД сравнивает физические поля ссылок и не требует строгого совпадения списков типов на этапе компиляции текста запроса транслятором 1С.
Проанализируем ситуацию, когда состав типов проверен, но ошибка сохраняется. При смене версий платформы (например, при переходе между релизами ветки 8.3) внутренние идентификаторы типов в кэше сервера могут не обновиться.
snccntx* в каталоге данных сервера).