При работе с кодом в конфигурациях 1С, особенно в сложных модулях, можно столкнуться с поведением языка запросов, которое на первый взгляд кажется нелогичным или даже магическим. Одна из таких ситуаций — обращение в пакетном запросе к таблице, которая, казалось бы, нигде не создается и не описывается. Давайте разберем реальный пример из конфигурации на базе «1С:Бухгалтерия 3.0» и выясним, в чем тут секрет.
Представим, что мы анализируем модуль менеджера документа и видим пакетный запрос, состоящий из нескольких частей. В одной из них мы встречаем такой код:
|ВЫБРАТЬ
| Реквизиты.Дата КАК Период,
| Реквизиты.Ссылка КАК Регистратор,
| ...
|ИЗ
| Документ.ПриходныйКассовыйОрдер КАК Реквизиты
|ГДЕ
| Реквизиты.Ссылка = &Ссылка
|;
|
|ВЫБРАТЬ
| 1 КАК НомерСтроки,
| Реквизиты.СчетУчетаРасчетовСКонтрагентом КАК СчетКт,
| ...
| Реквизиты.ПодразделениеОрганизации КАК ПодразделениеДт,
| Реквизиты.СуммаДокумента КАК ВалютнаяСумма
|ИЗ
| <strong>Реквизиты КАК Реквизиты</strong>
Первый запрос в пакете вполне понятен: он выбирает данные из документа ПриходныйКассовыйОрдер. Но второй запрос вызывает недоумение. В секции ИЗ используется источник Реквизиты. Это не физическая таблица базы данных и не временная таблица, созданная с помощью инструкции ПОМЕСТИТЬ в этом же пакете. Как же платформа "понимает", откуда брать данные? Кажется, что это ошибка, но код работает. Выясним причину.
Секрет кроется в использовании специального объекта платформы — Менеджера временных таблиц. Это объект, который предназначен для управления жизненным циклом временных таблиц (ВТ) в рамках одного серверного вызова.
Перед выполнением запроса в коде обычно присутствует такая инициализация:
Запрос = Новый Запрос;
МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
Запрос.МенеджерВременныхТаблиц = МенеджерВременныхТаблиц;
Когда мы присваиваем менеджер свойству запроса, все временные таблицы, созданные с помощью инструкции ПОМЕСТИТЬ, будут управляться этим менеджером. Главная особенность в том, что МВТ и созданные в нем таблицы "живут" на протяжении всего серверного вызова, а не только в рамках одного объекта Запрос или одного пакетного запроса.
Это означает, что если в одной функции был создан МВТ и в нем была создана временная таблица, то этот менеджер можно передать в другую функцию, и в ней эта временная таблица будет доступна для использования в новых запросах.
Зная о существовании МВТ, мы можем предположить, что временная таблица Реквизиты все-таки была создана, но не в том фрагменте кода, который мы анализируем. Вероятнее всего, это произошло раньше, в какой-то из предыдущих процедур, вызванных в рамках того же серверного вызова.
В нашем примере, как выяснилось в ходе анализа, перед формированием "загадочного" запроса вызывалась другая функция, например, ПодготовитьПараметрыРеквизитыДокумента, в которой и содержался "недостающий" фрагмент:
|ВЫБРАТЬ
| Реквизиты.Дата КАК Дата,
| Реквизиты.Ссылка КАК Ссылка,
| Реквизиты.ВидОперации КАК ВидОперации,
| ...
|<strong>ПОМЕСТИТЬ Реквизиты</strong>
|ИЗ
| Документ.ПриходныйКассовыйОрдер КАК Реквизиты
|ГДЕ
| Реквизиты.Ссылка = &Ссылка
Этот запрос выполняется первым. Он выбирает данные из документа и с помощью инструкции ПОМЕСТИТЬ Реквизиты создает временную таблицу с именем "Реквизиты" внутри Менеджера временных таблиц. После этого, в любом последующем запросе, использующем этот же МВТ, мы можем обращаться к таблице Реквизиты как к обычному источнику данных.
Таким образом, "магия" развеяна. Это стандартный и очень мощный механизм платформы 1С.
Давайте по шагам соберем всю цепочку действий, чтобы закрепить понимание механизма:
Запрос и объект МенеджерВременныхТаблиц, который присваивается свойству запроса.ПОМЕСТИТЬ ИмяТаблицы. Результат этого запроса сохраняется во временной таблице, которая теперь находится под управлением МВТ.Возникает логичный вопрос: что произойдет, если после создания временной таблицы другой пользователь изменит данные в исходной таблице (в нашем примере, в документе ПриходныйКассовыйОрдер)?
Данные во временной таблице не изменятся. МВТ обеспечивает полную изоляцию данных на уровне сеанса. Временная таблица — это "снимок" (snapshot) данных на момент выполнения запроса с инструкцией ПОМЕСТИТЬ. Любые последующие изменения в исходных физических таблицах, сделанные в других сеансах, никак не повлияют на уже созданную ВТ в текущем сеансе. Это гарантирует консистентность и предсказуемость расчетов на протяжении всего выполнения сложного алгоритма.
Если вы столкнулись с подобной "магией" и не можете понять, откуда в запросе взялась та или иная таблица, лучшим способом решения будет глобальный поиск по конфигурации. Просто поищите строку ПОМЕСТИТЬ ИмяТаблицы (например, ПОМЕСТИТЬ Реквизиты). Это поможет вам быстро найти место, где временная таблица была создана, и восстановить полную логику работы кода.