bsl-language-server
bsl-language-server copied to clipboard
[NEW] Обращение через точку к полям ссылочных реквизитов временной таблицы
Описание проблемы, ошибки, которую надо диагностировать
Когда описывается временная таблица, правильно в ней описать все поля, которые понадобятся для работы в запросе. Очень часто люди во временной таблице описывают минимальное количество полей, а ко всем остальным обращаются через точку, в других запросах. Это приводит к следующим последствиям:
- В запросе замыливается его логика. Правильно получать данные блоками. Именовать эти блоки. Далее этими блоками необходимо оперировать. На деле же люди воспринимают выполнение запросов как выполнение кода, и данные получают не сразу, а по ходу.
- Последствиями пункта (1) являются следующие возможные неприятности:
- не корректно устанавливаются фильтры, выбираются избыточные данные;
- не правильно создаются индексы для временных таблиц;
- возможные неоптимальные планы запросов, из-за скрытых соединений в условиях соединения;
- возрастает нагрузка на сервер СУБД, т.к. данные получаются по ходу выполнения пакета запроса и происходят обращения к одним и тем же таблицам по несколько раз.
Ссылка на источник, подтверждающее нарушение либо обоснование наличия проблемы
Нет.
Параметры диагностики
Тип Статья на русском
- [ ] :ant: Ошибка
- [ ] :cop: Уязвимость
- [x] :guardsman: Потенциальная уязвимость
- [ ] :poop: Качество кода
- [ ] :trollface: Другое
Важность Статья на русском
- [ ] :broken_heart: Блокирующая / Blocker
- [ ] :heart: Критическая / Critical
- [x] :yellow_heart: Важная / Major
- [ ] :blue_heart: Незначительная / Minor
- [ ] :green_heart: Информационная / Info
- [ ] :revolving_hearts: Другое
Тэги Статья на русском
- [ ]
STANDARD
- "Нарушение стандартов 1С" - [ ]
LOCKINOS
- "Не будет работать в другой ОС" - [ ]
SQL
- "Проблема с запросом" - [x]
PERFORMANCE
- "Проблема производительности" - [ ]
BRAINOVERLOAD
- "Непонятный код" - [x]
BADPRACTICE
- "Плохая практика программирования" - [ ]
CLUMSY
- "Излишние действия" - [ ]
DESIGN
- "Ошибка в проектировании" - [ ]
SUSPICIOUS
- "Подозрительный код" - [ ]
UNPREDICTABLE
- "Непредсказуемо работающий код" - [ ]
DEPRECATED
- "Устаревшая функциональность" - [ ]
ERROR
- "Ошибочная конструкция" - [ ]
LOCALIZE
- "Проблемы локализации"
Время на исправление (минут)
15
Дополнительная информация
Пример:
ВЫБРАТЬ
ЗаказКлиентаТовары.Ссылка КАК ЗаказКлиента,
ЗаказКлиентаТовары.Номенклатура КАК Номенклатура,
ЗаказКлиентаТовары.Характеристика КАК Характеристика,
ЗаказКлиентаТовары.Цена КАК Цена,
ЗаказКлиентаТовары.Упаковка КАК Упаковка
ПОМЕСТИТЬ ВТ_ТоварыЗаказов
ИЗ
Документ.ЗаказКлиента.Товары КАК ЗаказКлиентаТовары
ГДЕ
ЗаказКлиентаТовары.Ссылка В(&Заказы)
ИНДЕКСИРОВАТЬ ПО
Номенклатура,
Характеристика,
Упаковка
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ЦеныНоменклатурыСрезПоследних.Номенклатура КАК Номенклатура,
ЦеныНоменклатурыСрезПоследних.Характеристика КАК Характеристика,
ЦеныНоменклатурыСрезПоследних.Цена КАК Цена,
ЦеныНоменклатурыСрезПоследних.Валюта КАК Валюта,
ЦеныНоменклатурыСрезПоследних.Упаковка КАК Упаковка
ПОМЕСТИТЬ ВТ_МаксимальныеЦены
ИЗ
РегистрСведений.ЦеныНоменклатуры.СрезПоследних(
,
(Номенклатура, Характеристика) В
(ВЫБРАТЬ
ВТ_ТоварыЗаказов.Номенклатура КАК Номенклатура,
ВТ_ТоварыЗаказов.Характеристика КАК Характеристика
ИЗ
ВТ_ТоварыЗаказов КАК ВТ_ТоварыЗаказов)) КАК ЦеныНоменклатурыСрезПоследних
ГДЕ
ЦеныНоменклатурыСрезПоследних.ВидЦены = &МаксимальнаяЦена
ИНДЕКСИРОВАТЬ ПО
Номенклатура,
Характеристика,
Валюта,
Упаковка
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ВТ_ТоварыЗаказов.ЗаказКлиента КАК ЗаказКлиента,
ВТ_ТоварыЗаказов.ЗаказКлиента.Партнер КАК Партнер,
ВТ_ТоварыЗаказов.Номенклатура.ВидНоменклатуры КАК ВидНоменклатуры ,
ВТ_ТоварыЗаказов.Номенклатура КАК Номенклатура,
ВТ_ТоварыЗаказов.Характеристика КАК Характеристика,
ВТ_ТоварыЗаказов.Цена > ВТ_МаксимальныеЦены.Цена КАК ПревышенаМаксимальнаяЦена
ИЗ
ВТ_ТоварыЗаказов КАК ВТ_ТоварыЗаказов
ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_МаксимальныеЦены КАК ВТ_МаксимальныеЦены
ПО ВТ_ТоварыЗаказов.Номенклатура = ВТ_МаксимальныеЦены.Номенклатура
И ВТ_ТоварыЗаказов.Характеристика = ВТ_МаксимальныеЦены.Характеристика
И ВТ_ТоварыЗаказов.ЗаказКлиента.Валюта = ВТ_МаксимальныеЦены.Валюта
И ВТ_ТоварыЗаказов.Упаковка = ВТ_МаксимальныеЦены.Упаковка
ГДЕ
ВТ_ТоварыЗаказов.Номенклатура.ВидНоменклатуры = &ВидНоменклатуры
Проверка должна сообщить:
-
соединение "ВТ_ТоварыЗаказов.ЗаказКлиента.Валюта = ВТ_МаксимальныеЦены.Валюта" не корректно, т.к. поле "Валюта " необходимо получать во временной таблице "ВТ_ТоварыЗаказов".
Исправив эту ситуацию. можно сделать более эффективный индекс, включив в него валюту.
-
получение поля "ВТ_ТоварыЗаказов.ЗаказКлиента.Партнер" не корректно, его необходимо перенести во временную таблицу "ВТ_ТоварыЗаказов".
Выполнив это условие мы сократим число обращений к таблице "ЗаказКлиента" с 2х до 1го (с условием того, если Валюту мы уже получаем во временной таблице).
-
построен фильтр по вложенному полю из временной таблицы "ВТ_ТоварыЗаказов.Номенклатура.ВидНоменклатуры", необходимо перенести получение поля во временную таблицу "ВТ_ТоварыЗаказов", и проверить, что наложенный фильтр оптимальный
В данном случае сразу несколько ошибок
- фильтр не в корректном месте, в общем случае его оптимальней перенести во временную таблицу, это будет очевидней, если и поле "ВидНоменклатуры" мы будем получать во временной таблице
- Если запрос будет в СКД, а поле ВидНоменклатуры мы получим в конечном запросе, то при наложении фильтра на вид номенклатуры, мы получим опять же не оптимальный фильтр, поэтому нужно либо вообще вид номенклатуры не получать в запросе, тогда СКД его наложит автоматически в первую ВТ, либо поле "ВидНоменклатуры" получать во временной таблице "ВТ_ТоварыЗаказов", тогда СКД опять же его подхватит.
Нужен какой то формальный алгоритм на что реагировать и ругаться
Добавил пример
Дописал еще один случай в пример.
@agibalovsa почему вдруг потенциальная уязвимость? )
предлагаю качество кода
@artbear все же, как мне кажется, качество кода - это больше к его внешнему виду, к его оформлению. В данном же случае возможно падение производительности.
Можно вообще и то и другое ))
Предлагаю учесть важный момент - если временная таблица участвует в несколько подзапросах, она сначала может использоваться как фильтр, а уже далее доп.реквизиты будут получаться необходимые данные, которые не было нужды вычислять на этапе подготовки временной таблицы Пример
Выбрать Т.Ссылка, Т.ЕщеПоле, Т.ДругоеПоле
ИЗ ИсходнаяТаблица КАК Т
ПОМЕСТИТЬ Таблица
ГДЕ Условие;
Выбрать Фильтр.Ссылка КАК СсылкаФильтра
ИЗ Цены.ВиртТаблица((Поле1, Поле2) В (Выбрать * Из Таблица)) КАК Цены
ГДЕ Условие2;
Выбрать Т.ЕщеПоле.Наименование,
Т.ДругоеПоле.Реквизит.Наименование
ИЗ ИсходнаяТаблица КАК Т
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Цены КАК Цены
Условия соединения по полям таблицы
в этом случае правило выдаст ложный результат, что закономерно.
@artbear все же, как мне кажется, качество кода - это больше к его внешнему виду, к его оформлению. В данном же случае возможно падение производительности.
уязвимость - это к хакерам, а здесь просто недочет кода, проблемы с качеством, но не явная ошибка. Поэтому и я предлагаю убрать флаг про уязвимость и поставить флаг "качество кода"
@artbear
в этом случае правило выдаст ложный результат, что закономерно.
Интересно, заставил задуматься. В 3м запросе в итоге 4 соединения. Какое из них первое?... В смысле в плане запросов, что отыграет сначала, соединение по ценам или другие соединения.