From c084ec9942a20640dc729a76d7076059742fe6be Mon Sep 17 00:00:00 2001 From: levon444 Date: Thu, 8 May 2025 09:01:23 +0400 Subject: [PATCH 1/9] =?UTF-8?q?=D0=9E=D0=BF=D0=B8=D1=81=D0=B0=D0=BD=D1=8B?= =?UTF-8?q?=20=D1=82=D0=B5=D1=81=D1=82=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../LogicalOrInJoinQuerySectionDiagnostic.bsl | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 src/test/resources/diagnostics/LogicalOrInJoinQuerySectionDiagnostic.bsl diff --git a/src/test/resources/diagnostics/LogicalOrInJoinQuerySectionDiagnostic.bsl b/src/test/resources/diagnostics/LogicalOrInJoinQuerySectionDiagnostic.bsl new file mode 100644 index 00000000000..21b123d1c7c --- /dev/null +++ b/src/test/resources/diagnostics/LogicalOrInJoinQuerySectionDiagnostic.bsl @@ -0,0 +1,39 @@ +Процедура ПолучиттьРеализациюТовара() + + Запрос = Новый Запрос; + Запрос.Текст = + "ВЫБРАТЬ + | РеализацияТоваровУслугТовары.Ссылка КАК Ссылка, + | РеализацияТоваровУслугТовары.Сумма > 0 + | ИЛИ РеализацияТоваровУслугТовары.СуммаСНДС > 0 КАК НенулеваяСумма + |ИЗ + | Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТоваровУслугТовары + | ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК СправочникНоменклатура + | ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ВидыНоменклатуры КАК ВидыНоменклатуры //Тест работы на вложенном соединении + | ПО СправочникНоменклатура.ВидНоменклатуры = ВидыНоменклатуры.Ссылка + | И (СправочникНоменклатура.СрокГодности > 1 + | ИЛИ СправочникНоменклатура.СрокГодности < 10) + | И (СправочникНоменклатура.СрокГодности > 1 + | ИЛИ ВидыНоменклатуры.ЗапрещенаПродажаЧерезПатент = ИСТИНА) //Ошибка + | ПО РеализацияТоваровУслугТовары.Номенклатура = СправочникНоменклатура.Ссылка + | И (СправочникНоменклатура.КодПоКВПД = ""1122"" + | ИЛИ СправочникНоменклатура.КодПоКВПД = ""1133"") + | И (СправочникНоменклатура.Артикул = ""0011"" + | ИЛИ СправочникНоменклатура.КодТРУ = ""0111"") //Ошибка + | И (СправочникНоменклатура.Артикул = ""0022"" + | ИЛИ СправочникНоменклатура.КодТРУ = ""0222"" + | ИЛИ СправочникНоменклатура.КодПоКВПД = ""2233"") //Ошибка (2 срабатывания) + | И (СправочникНоменклатура.КодПоКВПД = ""1122"" + | ИЛИ СправочникНоменклатура.КодПоКВПД = ""1133"" + | ИЛИ СправочникНоменклатура.КодТРУ = ""0222"")"; //Ошибка (2 срабатывания) + + РезультатЗапроса = Запрос.Выполнить(); + +КонецПроцедуры + +//Диагностика должна зафиксировать ошибку +// при использовании оператора "ИЛИ" в условии над различными полями таблицы. +// Если оператор "ИЛИ" в условии над одним полем, то ошибка не фиксируется, +// так как планировщик запросов имеет возможность преобразовывать такое условие в IN, тем самым оптимизируя. + +//Итоговое количество срабатываний - 6. \ No newline at end of file From 528ccec2cc08b7ead481630f3b228e845de588c4 Mon Sep 17 00:00:00 2001 From: levon444 Date: Thu, 8 May 2025 09:02:26 +0400 Subject: [PATCH 2/9] =?UTF-8?q?=D0=9E=D0=BF=D0=B8=D1=81=D0=B0=D0=BD=D1=8B?= =?UTF-8?q?=20=D1=81=D0=B2=D0=BE=D0=B9=D1=81=D1=82=D0=B2=D0=B0=20=D0=B4?= =?UTF-8?q?=D0=B8=D0=B0=D0=B3=D0=BD=D0=BE=D1=81=D1=82=D0=B8=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../LogicalOrInJoinQuerySectionDiagnostic_en.properties | 2 ++ .../LogicalOrInJoinQuerySectionDiagnostic_ru.properties | 2 ++ 2 files changed, 4 insertions(+) create mode 100644 src/main/resources/com/github/_1c_syntax/bsl/languageserver/diagnostics/LogicalOrInJoinQuerySectionDiagnostic_en.properties create mode 100644 src/main/resources/com/github/_1c_syntax/bsl/languageserver/diagnostics/LogicalOrInJoinQuerySectionDiagnostic_ru.properties diff --git a/src/main/resources/com/github/_1c_syntax/bsl/languageserver/diagnostics/LogicalOrInJoinQuerySectionDiagnostic_en.properties b/src/main/resources/com/github/_1c_syntax/bsl/languageserver/diagnostics/LogicalOrInJoinQuerySectionDiagnostic_en.properties new file mode 100644 index 00000000000..c027d94262c --- /dev/null +++ b/src/main/resources/com/github/_1c_syntax/bsl/languageserver/diagnostics/LogicalOrInJoinQuerySectionDiagnostic_en.properties @@ -0,0 +1,2 @@ +diagnosticMessage='OR' operator is detected in JOIN condition +diagnosticName=Logical 'OR' in 'JOIN' query section diff --git a/src/main/resources/com/github/_1c_syntax/bsl/languageserver/diagnostics/LogicalOrInJoinQuerySectionDiagnostic_ru.properties b/src/main/resources/com/github/_1c_syntax/bsl/languageserver/diagnostics/LogicalOrInJoinQuerySectionDiagnostic_ru.properties new file mode 100644 index 00000000000..f480525f4a2 --- /dev/null +++ b/src/main/resources/com/github/_1c_syntax/bsl/languageserver/diagnostics/LogicalOrInJoinQuerySectionDiagnostic_ru.properties @@ -0,0 +1,2 @@ +diagnosticMessage=Обнаружен оператор 'ИЛИ' в условии соединения +diagnosticName=Логическое 'ИЛИ' в соединениях запроса From 39366c860dc661ae87a48f167d72b3a63cc218ed Mon Sep 17 00:00:00 2001 From: levon444 Date: Tue, 13 May 2025 19:12:38 +0400 Subject: [PATCH 3/9] =?UTF-8?q?=D0=94=D0=BE=D0=BF=D0=BE=D0=BB=D0=BD=D0=B8?= =?UTF-8?q?=D0=BB=20=D1=82=D0=B5=D1=81=D1=82=20=D0=B4=D0=BE=D0=BF=D0=BE?= =?UTF-8?q?=D0=BB=D0=BD=D0=B8=D1=82=D0=B5=D0=BB=D1=8C=D0=BD=D1=8B=D0=BC=20?= =?UTF-8?q?=D1=81=D0=BE=D0=B5=D0=B4=D0=B8=D0=BD=D0=B5=D0=BD=D0=B8=D0=B5?= =?UTF-8?q?=D0=BC=20=D0=BD=D0=B0=20=D0=B0=D0=BD=D0=B0=D0=BB=D0=BE=D0=B3?= =?UTF-8?q?=D0=B8=D1=87=D0=BD=D0=BE=D0=BC=20=D0=BE=D1=81=D0=BD=D0=BE=D0=B2?= =?UTF-8?q?=D0=BD=D0=BE=D0=BC=D1=83=20=D1=83=D1=80=D0=BE=D0=B2=D0=BD=D0=B5?= =?UTF-8?q?=20=D0=B2=D0=BB=D0=BE=D0=B6=D0=B5=D0=BD=D0=BD=D0=BE=D1=81=D1=82?= =?UTF-8?q?=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../diagnostics/LogicalOrInJoinQuerySectionDiagnostic.bsl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/test/resources/diagnostics/LogicalOrInJoinQuerySectionDiagnostic.bsl b/src/test/resources/diagnostics/LogicalOrInJoinQuerySectionDiagnostic.bsl index 21b123d1c7c..4032a8cee20 100644 --- a/src/test/resources/diagnostics/LogicalOrInJoinQuerySectionDiagnostic.bsl +++ b/src/test/resources/diagnostics/LogicalOrInJoinQuerySectionDiagnostic.bsl @@ -8,6 +8,9 @@ | ИЛИ РеализацияТоваровУслугТовары.СуммаСНДС > 0 КАК НенулеваяСумма |ИЗ | Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТоваровУслугТовары + | ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг + | ПО РеализацияТоваровУслугТовары.Ссылка = РеализацияТоваровУслуг.Ссылка + | И (РеализацияТоваровУслугТовары.Сумма > 0 ИЛИ РеализацияТоваровУслугТовары.СуммаНДС > 0 ИЛИ РеализацияТоваровУслугТовары.СуммаСНДС > 0) //Ошибка (2 срабатывания) | ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК СправочникНоменклатура | ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ВидыНоменклатуры КАК ВидыНоменклатуры //Тест работы на вложенном соединении | ПО СправочникНоменклатура.ВидНоменклатуры = ВидыНоменклатуры.Ссылка @@ -36,4 +39,4 @@ // Если оператор "ИЛИ" в условии над одним полем, то ошибка не фиксируется, // так как планировщик запросов имеет возможность преобразовывать такое условие в IN, тем самым оптимизируя. -//Итоговое количество срабатываний - 6. \ No newline at end of file +//Итоговое количество срабатываний - 8. \ No newline at end of file From 6abf8b7f2cbf3ac4ab2e7b10f3bbc3cb7e2eeb49 Mon Sep 17 00:00:00 2001 From: levon444 Date: Tue, 13 May 2025 19:15:46 +0400 Subject: [PATCH 4/9] =?UTF-8?q?=D0=9E=D0=BF=D0=B8=D1=81=D0=B0=D0=BD=D1=8B?= =?UTF-8?q?=20=D1=81=D0=B2=D0=BE=D0=B9=D1=81=D1=82=D0=B2=D0=B0=20=D0=B4?= =?UTF-8?q?=D0=B8=D0=B0=D0=B3=D0=BD=D0=BE=D1=81=D1=82=D0=B8=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/diagnostics/LogicalOrInJoinQuerySection.md | 16 ++++++++++++++++ .../diagnostics/LogicalOrInJoinQuerySection.md | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 docs/diagnostics/LogicalOrInJoinQuerySection.md create mode 100644 docs/en/diagnostics/LogicalOrInJoinQuerySection.md diff --git a/docs/diagnostics/LogicalOrInJoinQuerySection.md b/docs/diagnostics/LogicalOrInJoinQuerySection.md new file mode 100644 index 00000000000..d4bbc61b9bd --- /dev/null +++ b/docs/diagnostics/LogicalOrInJoinQuerySection.md @@ -0,0 +1,16 @@ +# (LogicalOrInJoinQuerySection) + + +## Описание диагностики + + +## Примеры + + +## Источники + + diff --git a/docs/en/diagnostics/LogicalOrInJoinQuerySection.md b/docs/en/diagnostics/LogicalOrInJoinQuerySection.md new file mode 100644 index 00000000000..c37c9e58afa --- /dev/null +++ b/docs/en/diagnostics/LogicalOrInJoinQuerySection.md @@ -0,0 +1,16 @@ +# Logical 'OR' in 'JOIN' query section (LogicalOrInJoinQuerySection) + + +## Description + + +## Examples + + +## Sources + + From eff50984e7d6185629a46198f22371c51a4365e1 Mon Sep 17 00:00:00 2001 From: levon444 Date: Tue, 13 May 2025 19:17:17 +0400 Subject: [PATCH 5/9] =?UTF-8?q?=D0=9E=D0=BF=D0=B8=D1=81=D0=B0=D0=BD=D0=B0?= =?UTF-8?q?=20=D0=BB=D0=BE=D0=B3=D0=B8=D0=BA=D0=B0=20=D0=B4=D0=B8=D0=B0?= =?UTF-8?q?=D0=B3=D0=BD=D0=BE=D1=81=D1=82=D0=B8=D0=BA=D0=B8=20=D0=B8=20?= =?UTF-8?q?=D0=BA=D0=BB=D0=B0=D1=81=D1=81=20=D1=82=D0=B5=D1=81=D1=82=D0=B8?= =?UTF-8?q?=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...LogicalOrInJoinQuerySectionDiagnostic.java | 54 +++++++++++++++++++ ...calOrInJoinQuerySectionDiagnosticTest.java | 33 ++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/LogicalOrInJoinQuerySectionDiagnostic.java create mode 100644 src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/LogicalOrInJoinQuerySectionDiagnosticTest.java diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/LogicalOrInJoinQuerySectionDiagnostic.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/LogicalOrInJoinQuerySectionDiagnostic.java new file mode 100644 index 00000000000..8269776bd7b --- /dev/null +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/LogicalOrInJoinQuerySectionDiagnostic.java @@ -0,0 +1,54 @@ +package com.github._1c_syntax.bsl.languageserver.diagnostics; + +import com.github._1c_syntax.bsl.languageserver.diagnostics.metadata.DiagnosticMetadata; +import com.github._1c_syntax.bsl.languageserver.diagnostics.metadata.DiagnosticSeverity; +import com.github._1c_syntax.bsl.languageserver.diagnostics.metadata.DiagnosticTag; +import com.github._1c_syntax.bsl.languageserver.diagnostics.metadata.DiagnosticType; +import com.github._1c_syntax.bsl.languageserver.utils.Trees; +import com.github._1c_syntax.bsl.parser.SDBLParser; +import org.antlr.v4.runtime.tree.ParseTree; + +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +@DiagnosticMetadata( + type = DiagnosticType.CODE_SMELL, + severity = DiagnosticSeverity.INFO, + minutesToFix = 1, + tags = { + DiagnosticTag.SQL, + DiagnosticTag.PERFORMANCE, + DiagnosticTag.UNPREDICTABLE + } + +) +public class LogicalOrInJoinQuerySectionDiagnostic extends AbstractSDBLVisitorDiagnostic { + + @Override + public ParseTree visitQuery(SDBLParser.QueryContext ctx) { + Trees.findAllRuleNodes(ctx, SDBLParser.RULE_joinPart). + forEach(jpt -> processJoinPart((SDBLParser.JoinPartContext) jpt)); + return ctx; + } + + private void processJoinPart(SDBLParser.JoinPartContext ctx) { + + ctx.condition.condidions.stream().map(SDBLParser.PredicateContext::logicalExpression) + .filter(Objects::nonNull) + .filter(this::isMultipleFieldsExpression) + .forEach( + exp -> Trees.findAllTokenNodes(exp, SDBLParser.OR) + .forEach(diagnosticStorage::addDiagnostic)); + + } + + private boolean isMultipleFieldsExpression(SDBLParser.LogicalExpressionContext exp){ + + Set expFields = Trees.findAllRuleNodes(exp, SDBLParser.RULE_column).stream() + .map(ParseTree::getText) + .collect(Collectors.toSet()); + return expFields.size() > 1; + } + +} diff --git a/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/LogicalOrInJoinQuerySectionDiagnosticTest.java b/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/LogicalOrInJoinQuerySectionDiagnosticTest.java new file mode 100644 index 00000000000..4e5b908fdc7 --- /dev/null +++ b/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/LogicalOrInJoinQuerySectionDiagnosticTest.java @@ -0,0 +1,33 @@ +package com.github._1c_syntax.bsl.languageserver.diagnostics; + +import org.eclipse.lsp4j.Diagnostic; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static com.github._1c_syntax.bsl.languageserver.util.Assertions.assertThat; + +class LogicalOrInJoinQuerySectionDiagnosticTest extends AbstractDiagnosticTest { + LogicalOrInJoinQuerySectionDiagnosticTest() { + super(LogicalOrInJoinQuerySectionDiagnostic.class); + } + + @Test + void test() { + + List diagnostics = getDiagnostics(); + + assertThat(diagnostics).hasSize(8); + + assertThat(diagnostics, true) + .hasRange(12, 62, 12, 65) + .hasRange(12, 108, 12, 111) + .hasRange(24, 14, 24, 17) + .hasRange(26, 14, 26, 17) + .hasRange(27, 14, 27, 17) + .hasRange(29, 14, 29, 17) + .hasRange(30, 14, 30, 17) + .hasRange(19, 15, 19, 18); + + } +} From 0c06880448d06262dc166af95d0fc88ecf01cc1a Mon Sep 17 00:00:00 2001 From: levon444 Date: Wed, 14 May 2025 16:20:56 +0400 Subject: [PATCH 6/9] =?UTF-8?q?=D0=9C=D0=BE=D0=B4=D1=83=D0=BB=D1=8C=20?= =?UTF-8?q?=D0=B4=D0=B8=D0=B0=D0=B3=D0=BD=D0=BE=D1=81=D1=82=D0=B8=D0=BA?= =?UTF-8?q?=D0=B8=20=D0=B4=D0=BE=D0=BF=D0=BE=D0=BB=D0=BD=D0=B5=D0=BD=20?= =?UTF-8?q?=D0=BA=D0=BE=D0=BC=D0=BC=D0=B5=D0=BD=D0=B0=D1=80=D0=B8=D1=8F?= =?UTF-8?q?=D0=BC=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../LogicalOrInJoinQuerySectionDiagnostic.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/LogicalOrInJoinQuerySectionDiagnostic.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/LogicalOrInJoinQuerySectionDiagnostic.java index 8269776bd7b..9e3ffb4ca92 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/LogicalOrInJoinQuerySectionDiagnostic.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/LogicalOrInJoinQuerySectionDiagnostic.java @@ -27,16 +27,23 @@ public class LogicalOrInJoinQuerySectionDiagnostic extends AbstractSDBLVisitorDi @Override public ParseTree visitQuery(SDBLParser.QueryContext ctx) { + //При посещении запроса сразу отбираем контексты соединений, которые в цикле обрабатываем отдельным методом. Trees.findAllRuleNodes(ctx, SDBLParser.RULE_joinPart). forEach(jpt -> processJoinPart((SDBLParser.JoinPartContext) jpt)); + return ctx; } private void processJoinPart(SDBLParser.JoinPartContext ctx) { + //Инициализируем поток для коллекции условий соединения, каждое условие преобразуем в логическое выражение. ctx.condition.condidions.stream().map(SDBLParser.PredicateContext::logicalExpression) + //фильтрация null отсекает условия, не содержащие составных логических конструкций. .filter(Objects::nonNull) + //Каждое условие дополнительно отбирается по наличию более чем одного различных полей. .filter(this::isMultipleFieldsExpression) + //По оставшимся условиям проводится цикл с поиском операторов "ИЛИ" + // и вложенным циклом фиксации ошибки диагностики для каждого оператора .forEach( exp -> Trees.findAllTokenNodes(exp, SDBLParser.OR) .forEach(diagnosticStorage::addDiagnostic)); @@ -45,6 +52,9 @@ private void processJoinPart(SDBLParser.JoinPartContext ctx) { private boolean isMultipleFieldsExpression(SDBLParser.LogicalExpressionContext exp){ + //От контекста логического выражения спускаемся до контекста колонки, + // далее поток текстового представления колонок собираем в Set. + //По наличию в Set более чем одного элемента проверяем использование различных полей в условии Set expFields = Trees.findAllRuleNodes(exp, SDBLParser.RULE_column).stream() .map(ParseTree::getText) .collect(Collectors.toSet()); From 365050ce2aa0b33e6f5b507ea124cfbd84fd3ba1 Mon Sep 17 00:00:00 2001 From: levon444 Date: Wed, 14 May 2025 16:21:58 +0400 Subject: [PATCH 7/9] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=BE=20=D0=BE=D0=BF=D0=B8=D1=81=D0=B0=D0=BD=D0=B8=D0=B5?= =?UTF-8?q?=20=D0=B4=D0=B8=D0=B0=D0=B3=D0=BD=D0=BE=D1=81=D1=82=D0=B8=D0=BA?= =?UTF-8?q?=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../LogicalOrInJoinQuerySection.md | 78 +++++++++++++++++-- .../LogicalOrInJoinQuerySection.md | 72 ++++++++++++++++- 2 files changed, 140 insertions(+), 10 deletions(-) diff --git a/docs/diagnostics/LogicalOrInJoinQuerySection.md b/docs/diagnostics/LogicalOrInJoinQuerySection.md index d4bbc61b9bd..17f76067c35 100644 --- a/docs/diagnostics/LogicalOrInJoinQuerySection.md +++ b/docs/diagnostics/LogicalOrInJoinQuerySection.md @@ -2,15 +2,77 @@ ## Описание диагностики - +Диагностика выявляет использование оператора `ИЛИ` в условиях соединений таблиц. +Присутствие операторов `ИЛИ` в условиях соединений может привести к тому, что СУБД не сможет использовать +индексы таблиц и будет выполнять сканирование, что увеличит время работы запроса и вероятность возникновения блокировок. + +Ошибка может быть решена "разнесением" предикатов условия с `ИЛИ` на разные пакеты запросов с объединением + +ВАЖНО: +Диагностика контролирует наличие предикатов в условии `ИЛИ`, над различными полями, так как использование оператора `ИЛИ` +над вариантами одного поля при выполнении запроса на стороне SQL автоматически преобразуется в условие IN. ## Примеры - +1) Ошибка не будет зафиксирована при использовании `ИЛИ` над вариантами одного поля -## Источники - - +ВЫБРАТЬ * +ИЗ +ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг +ПО РеализацияТоваровУслугТовары.Ссылка = РеализацияТоваровУслуг.Ссылка + И РеализацияТоваровУслугТовары.СуммаНДС > 0 + +ОБЪЕДИНИТЬ ВСЕ + +ВЫБРАТЬ * +ИЗ +ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг +ПО РеализацияТоваровУслугТовары.Ссылка = РеализацияТоваровУслуг.Ссылка + И РеализацияТоваровУслугТовары.СуммаСНДС > 0 +``` + +3) Диагностика также отработает для вложенных соединений с использованием `ИЛИ` в условиях. + +```bsl +Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТоваровУслугТовары +ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг +ПО РеализацияТоваровУслугТовары.Ссылка = РеализацияТоваровУслуг.Ссылка +ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК СправочникНоменклатура + ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ВидыНоменклатуры КАК ВидыНоменклатуры //Тест работы на вложенном соединении + ПО СправочникНоменклатура.ВидНоменклатуры = ВидыНоменклатуры.Ссылка + И (СправочникНоменклатура.СрокГодности > 1 + ИЛИ ВидыНоменклатуры.ЗапрещенаПродажаЧерезПатент = ИСТИНА) + +``` +Рекомендуется исправление аналогично п.2 заменой вложенного соединения на соединение с созданием промежуточной временной таблицы + +## Источники +- [Стандарт - Эффективные условия запросов, п.2](https://its.1c.ru/db/v8std/content/658/hdoc) +- [Использование логического ИЛИ в условиях - Типичные причины неоптимальной работы запросов и методы оптимизации](https://its.1c.ru/db/content/metod8dev/src/developers/scalability/standards/i8105842.htm#or) diff --git a/docs/en/diagnostics/LogicalOrInJoinQuerySection.md b/docs/en/diagnostics/LogicalOrInJoinQuerySection.md index c37c9e58afa..bed53c8c2f9 100644 --- a/docs/en/diagnostics/LogicalOrInJoinQuerySection.md +++ b/docs/en/diagnostics/LogicalOrInJoinQuerySection.md @@ -2,11 +2,79 @@ ## Description - + +Diagnostics reveals the use of the `OR` operator in the conditions of table joins. + +The presence of the `OR` operators in connection conditions may cause the DBMS to be unable to use +table indexes and perform scans, which will increase query running time and the likelihood of locks. + +The error can be solved by "spreading" the predicates of the condition with `OR` into different query packages with combining + +IMPORTANT: +Diagnostics monitors the presence of predicates in the condition `OR`, over various fields, since the use of the operator `OR` +When executing a query on the SQL side, the control over the variants of one field is automatically converted to the IN condition. ## Examples - +1) The error will not be fixed when using `OR` over variants of a single field. + +```bsl +LEFT JOIN Catalog.NomenclatureTypes КАК NomenclatureTypes + ON CatalogNomenclature.NomenclatureType = NomenclatureTypes.Reference + AND (CatalogNomenclature.ExpirationDate > 1 + OR CatalogNomenclature.ExpirationDate < 10) +``` + +2) When using the `OR` operator over various fields, the error will be fixed for each occurrence of the operator. + +```bsl +INNER JOIN Document.GoodsServicesSaling КАК GoodsServicesSaling +ON GoodsServicesSalingGoods.Reference = GoodsServicesSaling.Reference + AND (GoodsServicesSalingGoods.Amount > 0 + OR GoodsServicesSalingGoods.AmountVAT > 0 + OR GoodsServicesSalingGoods.AmountWithVAT > 0) + +``` + +It is proposed to correct such constructions by placing requests in separate packages with combining: + +```bsl +SELECT * +FROM +INNER JOIN Document.GoodsServicesSaling КАК GoodsServicesSaling +ON GoodsServicesSalingGoods.Reference = GoodsServicesSaling.Reference + AND GoodsServicesSalingGoods.Amount > 0 + +UNION ALL + +SELECT * +FROM +INNER JOIN Document.GoodsServicesSaling КАК GoodsServicesSaling +ON GoodsServicesSalingGoods.Reference = GoodsServicesSaling.Reference + AND GoodsServicesSalingGoods.AmountVAT > 0 + +UNION ALL + +SELECT * +FROM +INNER JOIN Document.GoodsServicesSaling КАК GoodsServicesSaling +ON GoodsServicesSalingGoods.Reference = GoodsServicesSaling.Reference + AND GoodsServicesSalingGoods.AmountWithVAT > 0 +``` + +3) Diagnostics will also work for nested connections using `OR` in conditions. +```bsl +Document.GoodsServicesSaling.Goods КАК GoodsServicesSalingGoods +INNER JOIN Document.GoodsServicesSaling КАК GoodsServicesSaling +ON GoodsServicesSalingGoods.Reference = GoodsServicesSaling.Reference +LEFT JOIN Catalog.Nomenclature КАК CatalogNomenclature + LEFT JOIN Catalog.NomenclatureTypes КАК NomenclatureTypes + ON CatalogNomenclature.NomenclatureType = NomenclatureTypes.Reference + AND (CatalogNomenclature.ExpirationDate > 1 + OR NomenclatureTypes.SaleThroughAPatentIsProhibited = TRUE) + +``` +A fix similar to paragraph 2 is recommended by replacing the nested connection with a connection with the creation of an intermediate temporary table. ## Sources ## Описание диагностики diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/LogicalOrInJoinQuerySectionDiagnostic.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/LogicalOrInJoinQuerySectionDiagnostic.java index 9e3ffb4ca92..4cd00be75c8 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/LogicalOrInJoinQuerySectionDiagnostic.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/LogicalOrInJoinQuerySectionDiagnostic.java @@ -1,3 +1,24 @@ +/* + * This file is a part of BSL Language Server. + * + * Copyright (c) 2018-2025 + * Alexey Sosnoviy , Nikita Fedkin and contributors + * + * SPDX-License-Identifier: LGPL-3.0-or-later + * + * BSL Language Server is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * BSL Language Server is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with BSL Language Server. + */ package com.github._1c_syntax.bsl.languageserver.diagnostics; import com.github._1c_syntax.bsl.languageserver.diagnostics.metadata.DiagnosticMetadata; diff --git a/src/main/resources/com/github/_1c_syntax/bsl/languageserver/configuration/parameters-schema.json b/src/main/resources/com/github/_1c_syntax/bsl/languageserver/configuration/parameters-schema.json index 3a20edf4672..d6642b35ecf 100644 --- a/src/main/resources/com/github/_1c_syntax/bsl/languageserver/configuration/parameters-schema.json +++ b/src/main/resources/com/github/_1c_syntax/bsl/languageserver/configuration/parameters-schema.json @@ -1070,6 +1070,16 @@ }, "$id": "#/definitions/LineLength" }, + "LogicalOrInJoinQuerySection": { + "description": "Logical 'OR' in 'JOIN' query section", + "default": true, + "type": [ + "boolean", + "object" + ], + "title": "Logical 'OR' in 'JOIN' query section", + "$id": "#/definitions/LogicalOrInJoinQuerySection" + }, "LogicalOrInTheWhereSectionOfQuery": { "description": "Using a logical \"OR\" in the \"WHERE\" section of a query", "default": true, diff --git a/src/main/resources/com/github/_1c_syntax/bsl/languageserver/configuration/schema.json b/src/main/resources/com/github/_1c_syntax/bsl/languageserver/configuration/schema.json index 8bcf9df256f..81c3e8681b8 100644 --- a/src/main/resources/com/github/_1c_syntax/bsl/languageserver/configuration/schema.json +++ b/src/main/resources/com/github/_1c_syntax/bsl/languageserver/configuration/schema.json @@ -266,6 +266,9 @@ "LineLength": { "$ref": "parameters-schema.json#/definitions/LineLength" }, + "LogicalOrInJoinQuerySection": { + "$ref": "parameters-schema.json#/definitions/LogicalOrInJoinQuerySection" + }, "LogicalOrInTheWhereSectionOfQuery": { "$ref": "parameters-schema.json#/definitions/LogicalOrInTheWhereSectionOfQuery" }, diff --git a/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/LogicalOrInJoinQuerySectionDiagnosticTest.java b/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/LogicalOrInJoinQuerySectionDiagnosticTest.java index 4e5b908fdc7..99ac5efe514 100644 --- a/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/LogicalOrInJoinQuerySectionDiagnosticTest.java +++ b/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/LogicalOrInJoinQuerySectionDiagnosticTest.java @@ -1,3 +1,24 @@ +/* + * This file is a part of BSL Language Server. + * + * Copyright (c) 2018-2025 + * Alexey Sosnoviy , Nikita Fedkin and contributors + * + * SPDX-License-Identifier: LGPL-3.0-or-later + * + * BSL Language Server is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * BSL Language Server is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with BSL Language Server. + */ package com.github._1c_syntax.bsl.languageserver.diagnostics; import org.eclipse.lsp4j.Diagnostic; From d499d84f5c849a01609c9d40a26fe3737358e961 Mon Sep 17 00:00:00 2001 From: levon444 Date: Thu, 15 May 2025 12:41:33 +0400 Subject: [PATCH 9/9] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D1=8B=20=D1=81=D1=81=D1=8B=D0=BB=D0=BA=D0=B8=20=D0=BD?= =?UTF-8?q?=D0=B0=20=D0=B8=D1=81=D1=82=D0=BE=D1=87=D0=BD=D0=B8=D0=BA=20?= =?UTF-8?q?=D0=B2=20=D0=B0=D0=BD=D0=B3=D0=BB=D0=B8=D0=B9=D1=81=D0=BA=D0=BE?= =?UTF-8?q?=D0=B9=20=D0=B2=D0=B5=D1=80=D1=81=D0=B8=D0=B8=20=D0=BE=D0=BF?= =?UTF-8?q?=D0=B8=D1=81=D0=B0=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/diagnostics/LogicalOrInJoinQuerySection.md | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/docs/en/diagnostics/LogicalOrInJoinQuerySection.md b/docs/en/diagnostics/LogicalOrInJoinQuerySection.md index bed53c8c2f9..3876aa449c0 100644 --- a/docs/en/diagnostics/LogicalOrInJoinQuerySection.md +++ b/docs/en/diagnostics/LogicalOrInJoinQuerySection.md @@ -76,9 +76,5 @@ LEFT JOIN Catalog.Nomenclature КАК CatalogNomenclature ``` A fix similar to paragraph 2 is recommended by replacing the nested connection with a connection with the creation of an intermediate temporary table. ## Sources - - +- [Standard: Effective Query Conditions, Clause 2 (RU)](https://its.1c.ru/db/v8std/content/658/hdoc) +- [Typical Causes of Suboptimal Query Performance and Optimization Techniques: Using Logical OR in Conditions (RU)](https://its.1c.ru/db/content/metod8dev/src/developers/scalability/standards/i8105842.htm#or)