При формировании регламентированной отчетности (например, бухгалтерского баланса), выполнении сложных отчетов или запуске запросов в клиент-серверном режиме разработчики и администраторы могут столкнуться с аварийным завершением работы программы. Платформа 1С выдает невосстановимую ошибку с требованием перезапустить сеанс, а в технологическом журнале или консоли запросов фиксируется исключение вида: Неверные параметры "VALUETYPE".
Примечательно, что при выгрузке базы в файл выгрузки (.dt) и разворачивании в файловом варианте этот же отчет или запрос отрабатывает абсолютно корректно и без замечаний. Разберем по шагам, почему возникает данная проблема, в чем заключается специфика работы транслятора запросов и как надежно устранить сбой.
Внутреннее системное имя VALUETYPE жестко связано с функцией языка запросов 1С ТИПЗНАЧЕНИЯ(). При выполнении запроса в клиент-серверном режиме платформа транслирует внутренний язык запросов (SDBL) в инструкции конкретной СУБД (например, MS SQL Server или PostgreSQL).
В базе данных поля составного типа (такие как реквизит Субконто в регистрах бухгалтерии, реквизит Владелец в подчиненных справочниках или составные реквизиты документов) хранятся в виде нескольких служебных колонок: разделителя типа (_TYPE) и ссылки/значения (_RTRef, _RRRef). Когда в запросе применяется конструкция вида:
ВЫБРАТЬ РАЗЛИЧНЫЕ
ТИПЗНАЧЕНИЯ(ХозрасчетныйОстаткиИОбороты.Субконто2) КАК ТипДокумента
ИЗ
РегистрБухгалтерии.Хозрасчетный.ОстаткиИОбороты(...) КАК ХозрасчетныйОстаткиИОбороты
транслятор платформы пытается преобразовать вызов ТИПЗНАЧЕНИЯ в бинарные операции и условия сопоставления типов на стороне SQL. В некоторых релизах платформы (в частности, в ветке 8.3.8, например 8.3.8.2322) механизм трансляции содержит ошибку, если поле составного типа в строках таблицы содержит значения NULL, Неопределено либо ссылки на удаленные метаданные. Аналогичное падение происходит даже на простых выборках по справочникам:
ВЫБРАТЬ РАЗЛИЧНЫЕ
ТИПЗНАЧЕНИЯ(Владелец)
ИЗ
Справочник.БанковскиеСчета
Файловая СУБД 1С использует собственный встроенный движок работы с таблицами, поэтому ошибка там не проявляется, что часто вводит разработчиков в заблуждение.
Рассмотрим подробнее способы обхода и устранения этой проблемы.
В подавляющем большинстве случаев разработчики вызывают ТИПЗНАЧЕНИЯ() для того, чтобы в дальнейшем сравнить результат с известным типом данных (например, ТИП(Документ.СчетФактураВыданный)). Использование оператора ССЫЛКА является предпочтительным и правильным стандартом разработки 1С.
Оператор ССЫЛКА напрямую проверяет код типа таблицы на уровне SQL-запроса без вычисления сложной функции типизации и не вызывает ошибку VALUETYPE. Перепишем проблемный фрагмент с использованием конструкции ВЫБОР КОГДА ... ТОГДА:
ВЫБРАТЬ
ВЫБОР
КОГДА ХозрасчетныйОстаткиИОбороты.Субконто2 ССЫЛКА Документ.СчетФактураВыданный
ТОГДА "Счет-фактура выданный"
КОГДА ХозрасчетныйОстаткиИОбороты.Субконто2 ССЫЛКА Документ.АвансовыйОтчет
ТОГДА "Авансовый отчет"
ИНАЧЕ "Прочий документ"
КОНЕЦ КАК ВидДокумента
ИЗ
РегистрБухгалтерии.Хозрасчетный.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, , , Счет В (&Счета), , ) КАК ХозрасчетныйОстаткиИОбороты
Если нам необходимо однозначно указать платформе, к какому типу данных должно быть приведено составное поле, используем оператор ВЫРАЗИТЬ(). Это снимает неоднозначность для транслятора SDBL:
ВЫБРАТЬ РАЗЛИЧНЫЕ
ТИПЗНАЧЕНИЯ(ВЫРАЗИТЬ(ХозрасчетныйОстаткиИОбороты.Субконто2 КАК Документ.СчетФактураВыданный)) КАК ТипДокумента
ИЗ
РегистрБухгалтерии.Хозрасчетный.ОстаткиИОбороты(...) КАК ХозрасчетныйОстаткиИОбороты
При таком подходе все несовпадающие типы автоматически превращаются в NULL, а сам вызов типизации не приводит к аварийному завершению сеанса.
Если в запросе требуется лишь получить список уникальных типов для дальнейшей обработки программным кодом (как это нередко реализовано в типовых отчетах и балансах), эффективнее перенести определение типа из SQL в код платформы.
Проанализируем практический пример. В запросе выбираем сами ссылки без вызова системной функции:
ВЫБРАТЬ РАЗЛИЧНЫЕ
ХозрасчетныйОстаткиИОбороты.Субконто2 КАК ДокументСсылка
ИЗ
РегистрБухгалтерии.Хозрасчетный.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, Период, , Счет В (&СчетаПоНДСАвансов), &СубконтоКонтрагентыСФВыданные, Организация = &Организация) КАК ХозрасчетныйОстаткиИОбороты
ГДЕ
ХозрасчетныйОстаткиИОбороты.Субконто2 <> НЕОПРЕДЕЛЕНО
И НЕ ХозрасчетныйОстаткиИОбороты.Субконто2 ЕСТЬ NULL
Затем в цикле обхода результата запроса определяем тип через стандартную функцию встроенного языка ТипЗнч():
ТаблицаТипов = Новый Массив;
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Если ЗначениеЗаполнено(Выборка.ДокументСсылка) Тогда
ТекущийТип = ТипЗнч(Выборка.ДокументСсылка);
Если ТаблицаТипов.Найти(ТекущийТип) = Неопределено Тогда
ТаблицаТипов.Добавить(ТекущийТип);
КонецЕсли;
КонецЕсли;
КонецЦикла;
Встроенный язык платформы корректно обрабатывает пустые ссылки, Неопределено и битые ссылки (объекты не найдены) без вызова критических ошибок.
Поскольку ошибка провоцируется некорректными записями, проанализируем состояние таблиц, задействованных в проблемном запросе:
БанковскиеСчета):
ВЫБРАТЬ
Ссылка,
Владелец
ИЗ
Справочник.БанковскиеСчета
ГДЕ
Владелец ЕСТЬ NULL
ИЛИ Владелец = НЕОПРЕДЕЛЕНО
Ошибка формирования кода VALUETYPE на уровне ядра платформы была официально зарегистрирована и исправлена разработчиками фирмы «1С». В версиях 8.3.9 и более новых механизм трансляции SDBL был полностью переработан.
Если в рабочей базе используется проблемный релиз (например, 8.3.8.2322), наиболее надежным и системным решением без изменения типовых конфигураций и внешних отчетов является плановое обновление технологической платформы 1С до актуального стабильного релиза.