При интеграции «1С:Предприятия» с внешними базами данных через механизм Внешних источников данных (ВИД) разработчики часто сталкиваются со специфическим поведением платформы. Одной из наиболее загадочных и неприятных является ошибка: Внутренняя ошибка языка запросов "Некорректные параметры получения части результата". Она возникает внезапно — при попытке пользователя отсортировать данные в динамическом списке, просто кликнув по заголовку колонки.
В этой статье мы подробно разберем технические причины возникновения этой проблемы, проанализируем поведение СУБД PostgreSQL и платформы 1С, а также рассмотрим несколько эффективных способов решения — от простых настроек в конфигураторе до создания SQL-представлений.
Для того чтобы понять природу ошибки, давайте заглянем под капот механизмов платформы 1С. Когда на управляемой форме открывается динамический список, система никогда не считывает всю внешнюю таблицу целиком. Это было бы крайне неэффективно с точки зрения производительности и расхода оперативной памяти.
Вместо этого платформа использует механизм постраничной выборки (пейджинга). Данные запрашиваются небольшими порциями (пакетами, обычно по 45 строк). Чтобы при прокрутке списка или изменении сортировки платформа знала, какую именно «следующую порцию» данных нужно отобразить, транслятор запросов 1С (SDBL) формирует сложный SQL-запрос. В секцию WHERE этого запроса динамически добавляются условия сравнения значений текущих полей со значениями последней строки предыдущей страницы.
Ситуация резко усложняется, если для поля, по которому происходит сортировка (например, ключевого идентификатора IDКотлетоса), в настройках внешнего источника данных включено свойство «Разрешить NULL». В реляционных базах данных значение NULL не поддается стандартному сравнению (операции типа «больше» или «меньше» с NULL всегда возвращают ложь или неопределенность). Чтобы обойти это ограничение и гарантировать предсказуемую сортировку на любых СУБД, платформа 1С автоматически генерирует в запросе вспомогательное синтетическое поле:
ВЫБОР
КОГДА Котлеты.IDКотлетоса ЕСТЬ NULL
ТОГДА 0
ИНАЧЕ 1
КОНЕЦ КАК IDКотлетосаПолеУпорядочивания1
Затем это синтетическое поле используется в блоке ORDER BY и в сложных логических конструкциях секции WHERE для определения границ страниц данных.
Суть проблемы и баг платформы: При работе с внешними источниками данных через ODBC-драйвер для PostgreSQL транслятор запросов SDBL в некоторых версиях платформы 1С (включая ветку 8.3.15) некорректно строит условия для выборки части результата, когда в них участвуют подобные синтетические поля. Происходит внутренний сбой парсера 1С еще до отправки запроса в СУБД. Именно поэтому один и тот же запрос, выполненный вручную в PgAdmin или в обычной консоли запросов 1С, отрабатывает без ошибок, но аварийно завершается внутри динамического списка.
Давайте рассмотрим детальные шаги и альтернативные способы исправления этой ошибки.
Если поле, по которому происходит сортировка (или ключевое поле таблицы), на уровне самой СУБД PostgreSQL гарантированно не содержит пустых значений (имеет ограничение NOT NULL или является первичным ключом PRIMARY KEY), то самым простым и эффективным решением будет убрать соответствующий флаг в метаданных 1С.
Выполним следующие шаги:
ВнешниеИсточникиДанных и найдем наш источник.Котлеты) и перейдем на вкладку Поля.IDКотлетоса).Результат: Платформа 1С поймет, что поле гарантированно заполнено. При генерации запроса для динамического списка отпадет необходимость создавать синтетическое поле упорядочивания IDКотлетосаПолеУпорядочивания1. Запрос станет простым, линейным и будет транслироваться без ошибок.
Предупреждение: Будьте осторожны! Если в реальной таблице PostgreSQL в этом поле все-таки окажется значение NULL, то при попытке прочитать такую запись 1С выдаст ошибку приведения типов в рантайме.
Что делать, если поле в базе данных PostgreSQL действительно может содержать NULL, и мы не имеем права отключать флаг "Разрешить NULL" напрямую, чтобы не нарушить стабильность чтения данных? В такой ситуации лучшим решением будет создание «обертки» над таблицей на стороне СУБД.
Мы можем создать представление (View) в PostgreSQL, которое будет на лету заменять все значения NULL на дефолтные значения (например, на 0 для числовых полей или на пустую строку для текстовых) с помощью стандартной SQL-функции COALESCE.
Рассмотрим пример SQL-скрипта для СУБД:
CREATE VIEW v_kotlety AS
SELECT
COALESCE(id_kotletosa, 0) AS id_kotletosa,
id_instrumenta,
nazvanie
FROM kotlety;
После создания представления в PostgreSQL выполним настройки в 1С:
v_kotlety во внешний источник данных 1С вместо исходной физической таблицы.id_kotletosa в свойствах поля ВИД снимем флаг Разрешить NULL (ведь функция COALESCE гарантирует отсутствие NULL).Этот способ является максимально надежным и профессиональным, так как он полностью сохраняет целостность данных и обходит баг транслятора 1С.
Если у нас нет прав на изменение структуры таблиц или создание представлений в сторонней базе данных PostgreSQL, мы можем решить проблему локально — прямо в интерфейсе разработчика 1С, изменив настройки динамического списка.
Разберем этот процесс по шагам:
ЕСТЬNULL.Посмотрим на пример текста запроса, который должен получиться:
ВЫБРАТЬ
ЕСТЬNULL(Котлеты.IDКотлетоса, 0) КАК IDКотлетоса,
Котлеты.IDИнструмента КАК IDИнструмента,
Инструменты.Наименование КАК НаименованиеИнструмента
ИЗ
ВнешнийИсточникДанных.ЕнотЖаритКотлеты.Таблица.Котлеты КАК Котлеты
ЛЕВОЕ СОЕДИНЕНИЕ ВнешнийИсточникДанных.ЕнотЖаритКотлеты.Таблица.Инструменты КАК Инструменты
ПО Котлеты.IDИнструмента = Инструменты.id
Благодаря явному использованию функции ЕСТЬNULL(Котлеты.IDКотлетоса, 0), платформа 1С при сортировке по колонке IDКотлетоса будет строить корректные и простые условия для получения страниц данных, избегая падения системы.
Поскольку данная проблема носит исключительно платформенный характер (ошибка транслятора SDBL), разработчикам рекомендуется своевременно обновлять технологическую платформу «1С:Предприятие». В современных релизах (начиная с веток 8.3.18, 8.3.20 и выше) взаимодействие с внешними источниками через ODBC-драйверы СУБД PostgreSQL было существенно оптимизировано, и многие проблемы трансляции были устранены.
Также не лишним будет проверить версию используемого драйвера psqlODBC на сервере 1С. Рекомендуется использовать официальный стабильный PostgreSQL Unicode ODBC драйвер актуальной версии и следить, чтобы в настройках DSN (Data Source Name) не были активны параметры преобразования типов данных, которые могут вводить в заблуждение метаданные 1С.