Почему в расширении возникает ошибка несовместимости типов в запросе после обновления конфигурации?

Программист 1С v8.3 (Управляемые формы) 1С:Управление нашей фирмой IT и автоматизация бизнеса
← На главную

При сопровождении баз данных 1С разработчики часто сталкиваются с ситуацией, когда после обновления типовой конфигурации или платформы стабильно работавшее расширение внезапно начинает вызывать критические сбои. При этом типовой код без расширения отрабатывает штатно, а включение расширения приводит к ошибке выполнения запроса в режиме «1С:Предприятие».

Рассмотрим типовой текст ошибки, возникающий при выполнении запроса:


{(11, 23)}: Неверные параметры в операции сравнения. 
Нельзя сравнивать поля неограниченной длины и поля несовместимых типов.
СведенияОФайлах.Файл >В(&Файлы)

Проанализируем природу этого поведения, разберем причины его возникновения на уровне платформы и выясним, как правильно исправить ошибку без ущерба для производительности системы.

Механизм возникновения ошибки и поведение транслятора запросов

Посмотрим на исходный фрагмент условия в запросе, вызывающий ошибку:


ГДЕ
    СведенияОФайлах.Файл В(&Файлы)

В типовых конфигурациях (например, в «1С:Управление нашей фирмой» при работе с подсистемой присоединенных файлов библиотеки стандартных подсистем) реквизит Файл имеет составной тип или ссылается на ОпределяемыйТип. Когда мы заимствуем определяемый тип или составной реквизит в расширение, платформа фиксирует статичный «снимок» метаданных на момент заимствования.

Выясним цепочку событий, приводящую к сбою:

  1. При обновлении конфигурации вендор добавляет в состав определяемого типа новые справочники или меняет состав типов реквизита.
  2. В расширении состав заимствованного определяемого типа остается старым, так как платформа не синхронизирует состав заимствованных составных типов автоматически.
  3. В процедуре модуля формы или общего модуля формируется массив или список значений &Файлы, в который попадают ссылки новых типов, добавленных обновлением.
  4. Транслятор запросов 1С при разборе условия В (&Файлы) сопоставляет типы из переданного массива с типами реквизита СведенияОФайлах.Файл, известными в контексте расширения.
  5. Поскольку расширение не знает о новых типах или целевой справочник вовсе не заимствован, пересечение типов оказывается пустым. Платформа распознает операцию как сравнение полей несовместимых типов и аварийно завершает запрос.

Способ 1. Синхронизация и перезаимствование определяемого типа (Рекомендуемый)

Разберем по шагам правильное архитектурное решение. Главная задача — предоставить контексту расширения актуальную информацию о типах данных, присутствующих в основной конфигурации.

  1. Откроем расширение в конфигураторе и найдем заимствованный ОпределяемыйТип (или реквизит составного типа), на который ссылается поле запроса.
  2. Удалим данный определяемый тип из состава расширения.
  3. Заново заимствуем этот определяемый тип из уже обновленной основной конфигурации базы данных, чтобы расширение получило актуальный состав ссылочных типов.
  4. Если в расширении определяемый тип расширялся собственными объектами, повторно добавим их в состав типа.
  5. Проверим, заимствованы ли в расширение сами объекты метаданных (справочники, документы), типы которых входят в определяемый тип и передаются в параметре &Файлы. Если объект не заимствован, платформа не сможет корректно построить соединение на уровне СУБД.

Способ 2. Замена неявного соединения на конструкцию ВЫРАЗИТЬ или временную таблицу

Часто разработчики пытаются обойти проблему добавлением обращения через точку к реквизиту Ссылка:


ГДЕ
    СведенияОФайлах.Файл.Ссылка В(&Файлы)

Разберем, почему так делать крайне не рекомендуется. Обращение через точку к составному типу вынуждает СУБД генерировать множественные LEFT JOIN ко всем физическим таблицам, входящим в состав типа. Это приводит к блокировкам, падению производительности и отключению индексов.

Если требуется изменить сам запрос без перезаимствования всех метаданных, рассмотрим безопасные альтернативы.

Вариант с явным приведением типа через ВЫРАЗИТЬ:

Если в конкретном контексте тип объектов заранее известен, используем оператор ВЫРАЗИТЬ:


ГДЕ
    ВЫРАЗИТЬ(СведенияОФайлах.Файл КАК Справочник.НоменклатураПрисоединенныеФайлы) В(&Файлы)

Вариант с передачей параметров во временную таблицу:

Вместо передачи массива в условие ГДЕ ... В(...) загрузим список файлов во временную таблицу и выполним соединение:


ВЫБРАТЬ
    ТВ_Файлы.Ссылка КАК Файл
ПОМЕСТИТЬ ВТ_ФильтрФайлов
ИЗ
    &ТаблицаФайлов КАК ТВ_Файлы
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    СведенияОФайлах.Файл КАК Файл,
    СведенияОФайлах.Размер КАК Размер
ИЗ
    РегистрСведений.СведенияОФайлах КАК СведенияОФайлах
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_ФильтрФайлов КАК ВТ_ФильтрФайлов
        ПО СведенияОФайлах.Файл = ВТ_ФильтрФайлов.Файл

При соединении таблиц оптимизатор СУБД сравнивает физические поля ссылок и не требует строгого совпадения списков типов на этапе компиляции текста запроса транслятором 1С.

Способ 3. Очистка кэша метаданных платформы

Проанализируем ситуацию, когда состав типов проверен, но ошибка сохраняется. При смене версий платформы (например, при переходе между релизами ветки 8.3) внутренние идентификаторы типов в кэше сервера могут не обновиться.

  1. Остановим службу сервера «1С:Предприятие».
  2. Очистим каталоги серверного кэша и сеансовых данных кластера (папки snccntx* в каталоге данных сервера).
  3. Очистим локальный кэш пользователя на клиентских машинах.
  4. Запустим службу сервера и выполним повторную проверку работы функционала.
← На главную