Каждый разработчик 1С рано или поздно сталкивается с ситуацией, когда абсолютно верный с виду запрос, исправно работавший долгое время, внезапно перестает возвращать данные. Особенно часто это происходит при фильтрации по периоду с использованием оператора МЕЖДУ. Вроде бы параметры заполнены, документы в базе есть, но на выходе мы получаем пустой результат.
В этой статье мы подробно разберем реальный кейс с форума, проведем детальную диагностику и выясним, почему оператор МЕЖДУ может «отказываться» работать. Мы изучим скрытые механизмы платформы 1С:Предприятие, особенности работы внешних консолей запросов («Запросников») и разберем неочевидные ошибки разработчиков, которые невозможно заметить с первого взгляда.
Рассмотрим сценарий: у нас есть запрос к табличной части документа ПоступлениеТоваровУслуг. Запрос выбирает номенклатуру и серию за определенный период. В системе компоновки данных (СКД) или во внешней консоли запросов код выглядит следующим образом:
ВЫБРАТЬ РАЗЛИЧНЫЕ
ПоступлениеТоваровУслугТовары.Номенклатура,
ПоступлениеТоваровУслугТовары.СерияНоменклатуры КАК СерияНоменклатуры
ИЗ
Документ.ПоступлениеТоваровУслуг.Товары КАК ПоступлениеТоваровУслугТовары
ГДЕ
ПоступлениеТоваровУслугТовары.Ссылка.Проведен = ИСТИНА
И ПоступлениеТоваровУслугТовары.Ссылка.Дата МЕЖДУ &ДатаНачСЭВ И &ДатаКон
При выполнении этого запроса с параметрами &ДатаНачСЭВ (значение 01.10.2017 00:00:01) и &ДатаКон (значение 31.12.2018 23:59:59) результат оказывается пустым. Однако, если мы полностью удалим строку с условием МЕЖДУ, консоль выведет множество документов за указанный 2018 год. Проведенные документы точно существуют в базе данных.
Проведем серию экспериментов, чтобы локализовать проблему, как это сделал автор темы:
ДАТАВРЕМЯ, запрос начинает корректно выбирать данные:
И ПоступлениеТоваровУслугТовары.Ссылка.Дата МЕЖДУ ДАТАВРЕМЯ(2017, 10, 1, 0, 0, 1) И ДАТАВРЕМЯ(2019, 6, 30, 23, 59, 59)
&ДатаНачСЭВ в &ДатаНач или &ДатаНачСЭВ1, запрос внезапно начинает работать без каких-либо других изменений!
Выясним, какие технические факторы приводят к такому поведению и как их избежать.
Это одна из самых коварных ошибок, с которой сталкиваются даже опытные программисты. В названии параметра &ДатаНачСЭВ присутствуют буквы «С» и «В». В стандартных шрифтах платформы 1С (как в конфигураторе, так и в режиме предприятия) начертание русских букв «С» и «В» абсолютно идентично латинским символам «C» (эс) и «B» (би).
Проанализируем, как это происходит на практике:
&ДатаНачCЭB, где буквы «C» и «B» — латинские).ДатаНачСЭВ).&ДатаНачCЭB (с латиницей) и &ДатаНачСЭВ (на кириллице) — это два абсолютно разных, не связанных между собой идентификатора.В результате СУБД получает запрос, в котором один из параметров (например, дата начала) не инициализирован (равен NULL или пустой дате 01.01.0001). Любая проверка даты документа на вхождение в диапазон между пустой датой и заполненной датой окончания может завершиться неудачей или вернуть непредсказуемый результат в зависимости от СУБД.
Когда разработчик переименовал параметр в более простой &ДатаНач или добавил единицу &ДатаНачСЭВ1, он заново набрал имя на клавиатуре в одной раскладке. Символы в коде запроса и в настройках консоли совпали, и ошибка исчезла.
Большинство консолей запросов («Запросников») обладают механизмами сохранения истории и настроек. Они кэшируют структуру параметров, их типы и значения в файлы настроек пользователя, системное хранилище или реестр. Это сделано для удобства, чтобы при перезапуске обработки не вводить тестовые данные заново.
Однако в этом механизме кроется проблема:
Если при первом запуске запроса параметр &ДатаНачСЭВ был определен с неверным типом данных (например, как Строка, Неопределено или пустая ссылка) либо произошел сбой сериализации настроек, консоль запросов может «намертво» закэшировать этот некорректный тип.
При последующих запусках разработчик интерактивно выбирает правильную дату в календаре консоли, но из-за программной ошибки в механизме чтения кэша обработки в сам запрос передается «битое» значение или неверный тип данных. Переименование параметра в &ДатаНачСЭВ1 заставляет консоль создать новую, «чистую» запись в кэше настроек, благодаря чему тип данных определяется корректно.
Обратим внимание на деталь в сообщении автора темы: &ДатаНачСЭВ 01.10.2017 00.00.01. Здесь в значении времени в качестве разделителей использованы точки вместо стандартных двоеточий.
Для платформы 1С легитимным и единственным разделителем времени при текстовом вводе или парсинге является двоеточие (например, 00:00:01). Если разработчик вводит время вручную в поле ввода консоли с точками, платформа не может распознать строку как полноценный тип Дата. В зависимости от реализации конкретной консоли запросов, это значение может либо вообще не передаться в запрос, либо преобразоваться в пустую дату 01.01.0001 00:00:00.
При использовании стандартного интерактивного календаря платформа формирует системный тип Дата автоматически, минуя подобные ошибки ручного ввода.
Автор упомянул, что отчет изначально был разработан на Системе компоновки данных (СКД), но отладка производилась в «Запроснике». Важно понимать разницу в их работе:
Чтобы сэкономить время при отладке запросов и не сталкиваться с «мистическим» поведением оператора МЕЖДУ, рекомендуем соблюдать следующие правила:
&НачалоПериода, &КонецПериода). Избегайте использования в именах параметров букв, имеющих одинаковое начертание в русском и английском алфавитах (С, В, А, Е, К, М, Н, О, Р, Т, Х).Дата, а не Строка или Неопределено.Соблюдение этих простых правил убережет вас от потери времени на поиск невидимых синтаксических ошибок и сделает разработку в среде 1С более комфортной и предсказуемой.