1
0
mirror of https://github.com/1C-Company/v8-code-style.git synced 2024-11-24 16:53:51 +02:00

Merge pull request #11 from 1C-Company/feature/1-mode-ql

#1 Перенос проверок запроса
This commit is contained in:
Dmitriy Marmyshev 2021-07-01 11:47:43 +03:00 committed by GitHub
commit c002972a76
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 477 additions and 12 deletions

View File

@ -0,0 +1,10 @@
# ql-temp-table-index
## Noncompliant Code Example
## Compliant Solution
## See

View File

@ -0,0 +1,10 @@
# ql-temp-table-index
## Неправильно
## Правильно
## См.

View File

@ -24,15 +24,19 @@
</category>
<check
category="com.e1c.v8codestyle.ql"
class="com.e1c.v8codestyle.ql.check.CamelCaseStringLiteral">
class="com.e1c.v8codestyle.internal.ql.ExecutableExtensionFactory:com.e1c.v8codestyle.ql.check.CamelCaseStringLiteral">
</check>
<check
category="com.e1c.v8codestyle.ql"
class="com.e1c.v8codestyle.ql.check.JoinToSubQuery">
class="com.e1c.v8codestyle.internal.ql.ExecutableExtensionFactory:com.e1c.v8codestyle.ql.check.JoinToSubQuery">
</check>
<check
category="com.e1c.v8codestyle.ql"
class="com.e1c.v8codestyle.ql.check.CastToMaxNumber">
class="com.e1c.v8codestyle.internal.ql.ExecutableExtensionFactory:com.e1c.v8codestyle.ql.check.CastToMaxNumber">
</check>
<check
category="com.e1c.v8codestyle.ql"
class="com.e1c.v8codestyle.internal.ql.ExecutableExtensionFactory:com.e1c.v8codestyle.ql.check.TempTableHasIndex">
</check>
</extension>

View File

@ -38,6 +38,9 @@ final class Messages
public static String JoinToSubQuery_description;
public static String JoinToSubQuery_Query_join_to_sub_query_not_allowed;
public static String JoinToSubQuery_title;
public static String TempTableHasIndex_description;
public static String TempTableHasIndex_New_temporary_table_should_have_indexes;
public static String TempTableHasIndex_title;
static
{
// initialize resource bundle

View File

@ -0,0 +1,74 @@
/*******************************************************************************
* Copyright (C) 2021, 1C-Soft LLC and others.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* 1C-Soft LLC - initial API and implementation
*******************************************************************************/
package com.e1c.v8codestyle.ql.check;
import static com._1c.g5.v8.dt.ql.model.QlPackage.Literals.ABSTRACT_QUERY_SCHEMA_TABLE__TABLE_NAME;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.emf.ecore.EObject;
import com._1c.g5.v8.dt.ql.model.AbstractQuerySchemaTable;
import com._1c.g5.v8.dt.ql.model.QuerySchemaSelectQuery;
import com.e1c.g5.v8.dt.check.CheckComplexity;
import com.e1c.g5.v8.dt.check.ICheckParameters;
import com.e1c.g5.v8.dt.check.settings.IssueSeverity;
import com.e1c.g5.v8.dt.check.settings.IssueType;
import com.e1c.g5.v8.dt.ql.check.QlBasicDelegateCheck;
/**
* The check of QL query that selection put into new temporary table should have some indexes.
* Usually it needs to index join fields with some other table, order fields, filter fields, grouping by fields.
* This check may be enhanced in the future.
*
* @author Dmitriy Marmyshev
*/
public class TempTableHasIndex
extends QlBasicDelegateCheck
{
private static final String CHECK_ID = "ql-temp-table-index"; //$NON-NLS-1$
@Override
public String getCheckId()
{
return CHECK_ID;
}
@Override
protected void configureCheck(CheckConfigurer builder)
{
builder.title(Messages.TempTableHasIndex_title)
.description(Messages.TempTableHasIndex_description)
.complexity(CheckComplexity.NORMAL)
.severity(IssueSeverity.MAJOR)
.issueType(IssueType.PERFORMANCE)
.delegate(QuerySchemaSelectQuery.class);
}
@Override
protected void checkQlObject(EObject object, QueryOwner owner, IQlResultAcceptor resultAceptor,
ICheckParameters parameters, IProgressMonitor monitor)
{
QuerySchemaSelectQuery selectQuery = (QuerySchemaSelectQuery)object;
if (selectQuery.getPlacementTable() == null)
return;
if (selectQuery.getIndexes() == null || selectQuery.getIndexes().isEmpty())
{
AbstractQuerySchemaTable table = selectQuery.getPlacementTable();
resultAceptor.addIssue(Messages.TempTableHasIndex_New_temporary_table_should_have_indexes, table,
ABSTRACT_QUERY_SCHEMA_TABLE__TABLE_NAME);
}
}
}

View File

@ -23,3 +23,6 @@ CastToMaxNumber_title=Query cast to max number
JoinToSubQuery_description=Query join with sub query
JoinToSubQuery_Query_join_to_sub_query_not_allowed=Query join to sub query not allowed
JoinToSubQuery_title=Query join with sub query
TempTableHasIndex_description=Temporary table should have indexes
TempTableHasIndex_New_temporary_table_should_have_indexes=New temporary table should have indexes
TempTableHasIndex_title=Temporary table should have indexes

View File

@ -1,4 +1,17 @@
#Generated by ResourceBundle Editor (http://essiembre.github.io/eclipse-rbe/)
###############################################################################
# Copyright (C) 2021, 1C-Soft LLC and others.
#
# This program and the accompanying materials are made
# available under the terms of the Eclipse Public License 2.0
# which is available at https://www.eclipse.org/legal/epl-2.0/
#
# SPDX-License-Identifier: EPL-2.0
#
# Contributors:
# 1C-Soft LLC - initial API and implementation
###############################################################################
#Generated by ResourceBundle Editor (http://essiembre.github.io/eclipse-rbe/)
CamelCaseStringLiteral_Regular_expression_to_skip_literal_content = Регулярное выражение для исключения содержимого литерела
@ -25,3 +38,9 @@ JoinToSubQuery_Query_join_to_sub_query_not_allowed = Соединение в з
JoinToSubQuery_description = Соединение запроса с подзапросом
JoinToSubQuery_title = Соединение запроса с подзапросом
TempTableHasIndex_New_temporary_table_should_have_indexes = Новая временная таблица должна содержать индексы
TempTableHasIndex_description = Временная таблица должна содержать индексы
TempTableHasIndex_title = Временная таблица должна содержать индексы

View File

@ -10,9 +10,12 @@ Bundle-RequiredExecutionEnvironment: JavaSE-11
Bundle-Localization: fragment
Import-Package: com._1c.g5.v8.bm.integration;version="[9.1.0,10.0.0)",
com._1c.g5.v8.dt.core.platform;version="[10.3.0,11.0.0)",
com._1c.g5.v8.dt.dcs.util;version="[13.0.0,14.0.0)",
com._1c.g5.v8.dt.form.model;version="[9.0.0,10.0.0)",
com._1c.g5.v8.dt.mcore;version="[6.0.0,7.0.0)",
com.e1c.g5.v8.dt.testing.check;version="[1.0.0,2.0.0)",
com._1c.g5.v8.dt.testing;version="[3.0.0,4.0.0)",
com._1c.g5.v8.dt.validation.marker;version="[4.0.0,5.0.0)",
com.e1c.g5.v8.dt.testing.check;version="[1.0.0,2.0.0)",
org.junit;version="[4.13.0,5.0.0)"
Require-Bundle: org.eclipse.core.resources;bundle-version="[3.13.900,4.0.0)"
Require-Bundle: org.eclipse.core.resources;bundle-version="[3.13.900,4.0.0)",
org.eclipse.xtext;bundle-version="[2.24.0,3.0.0)"

View File

@ -15,4 +15,5 @@ output.. = bin/
bin.includes = META-INF/,\
.,\
fragment.properties,\
workspace/
workspace/,\
resources/

View File

@ -0,0 +1,13 @@
SELECT
1 AS Field
INTO T
INDEX BY
Field
;
////////////////////////////////////////////////////////////////////////////////
SELECT
T.Field
FROM
T AS T

View File

@ -0,0 +1,10 @@
SELECT
1 AS Field
INTO T
;
////////////////////////////////////////////////////////////////////////////////
SELECT
T.Field
FROM
T AS T

View File

@ -29,11 +29,10 @@ import com._1c.g5.v8.dt.form.model.Form;
import com._1c.g5.v8.dt.form.model.FormAttribute;
import com._1c.g5.v8.dt.validation.marker.Marker;
import com.e1c.g5.v8.dt.testing.check.CheckTestBase;
import com.e1c.v8codestyle.ql.check.CamelCaseStringLiteral;
import com.e1c.v8codestyle.ql.check.CastToMaxNumber;
/**
* Test {@link CamelCaseStringLiteral} class that checks string literal contains only camel-case words
* or non-word symbols.
* Test {@link CastToMaxNumber} class that checks CAST(10, NUMBER(31,2)) expression to max allowed number.
*
* @author Dmitriy Marmyshev
*/

View File

@ -20,11 +20,10 @@ import com._1c.g5.v8.bm.core.IBmObject;
import com._1c.g5.v8.dt.core.platform.IDtProject;
import com._1c.g5.v8.dt.validation.marker.Marker;
import com.e1c.g5.v8.dt.testing.check.CheckTestBase;
import com.e1c.v8codestyle.ql.check.CamelCaseStringLiteral;
import com.e1c.v8codestyle.ql.check.JoinToSubQuery;
/**
* Test {@link CamelCaseStringLiteral} class that checks string literal contains only camel-case words
* or non-word symbols.
* Test {@link JoinToSubQuery} class that checks that selection query has join with some sub query.
*
* @author Dmitriy Marmyshev
*/

View File

@ -0,0 +1,131 @@
/*******************************************************************************
* Copyright (C) 2021, 1C-Soft LLC and others.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* 1C-Soft LLC - initial API and implementation
*******************************************************************************/
package com.e1c.v8codestyle.ql.itests;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.nio.charset.StandardCharsets;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.emf.ecore.EObject;
import org.junit.Before;
import org.junit.Test;
import com._1c.g5.v8.dt.core.platform.IDtProject;
import com._1c.g5.v8.dt.dcs.util.DcsUtil;
import com._1c.g5.v8.dt.ql.model.QuerySchema;
import com._1c.g5.v8.dt.ql.model.QuerySchemaSelectQuery;
import com.e1c.g5.v8.dt.ql.check.QlBasicDelegateCheck;
import com.e1c.g5.v8.dt.ql.check.QlBasicDelegateCheck.QueryOwner;
import com.e1c.g5.v8.dt.testing.check.SingleProjectReadOnlyCheckTestBase;
import com.e1c.v8codestyle.ql.check.TempTableHasIndex;
/**
* Test {@link TempTableHasIndex} class that checks selection query that put to new temporary table and has indexes.
*
* @author Dmitriy Marmyshev
*/
public class TempTableHasIndexTest
extends SingleProjectReadOnlyCheckTestBase
{
private static final String PROJECT_NAME = "QlEmptyProject";
private static final String FOLDER = "/resources/";
private TestingCheckResultAcceptor resultAcceptor;
private TestingQlResultAcceptor qlResultAcceptor;
private TempTableHasIndex check;
@Override
protected String getTestConfigurationName()
{
return PROJECT_NAME;
}
@Before
public void setupCheck() throws Exception
{
resultAcceptor = new TestingCheckResultAcceptor();
qlResultAcceptor = new TestingQlResultAcceptor();
QlBasicDelegateCheck.setResultAcceptor((o, f) -> qlResultAcceptor);
check = new TempTableHasIndex();
}
@Test
public void testTempTableWithoutIndex() throws Exception
{
IDtProject project = dtProjectManager.getDtProject(PROJECT_NAME);
String queryText =
new String(getClass().getResourceAsStream(FOLDER + "temp-table-has-no-index.ql").readAllBytes(),
StandardCharsets.UTF_8);
QuerySchema querySchema = DcsUtil.getQuerySchema(queryText, project);
assertNotNull(querySchema);
assertEquals(2, querySchema.getQueries().size());
QlBasicDelegateCheck.setOwner(new QueryOwner(querySchema, null));
EObject selectQuery = querySchema.getQueries().get(1);
assertTrue(selectQuery instanceof QuerySchemaSelectQuery);
check.check(selectQuery, resultAcceptor, null, new NullProgressMonitor());
assertTrue(qlResultAcceptor.messages.isEmpty());
assertTrue(qlResultAcceptor.featuredMessages.isEmpty());
selectQuery = querySchema.getQueries().get(0);
assertTrue(selectQuery instanceof QuerySchemaSelectQuery);
check.check(selectQuery, resultAcceptor, null, new NullProgressMonitor());
assertTrue(qlResultAcceptor.messages.isEmpty());
assertFalse(qlResultAcceptor.featuredMessages.isEmpty());
}
@Test
public void testTempTableWithIndex() throws Exception
{
IDtProject project = dtProjectManager.getDtProject(PROJECT_NAME);
String queryText =
new String(getClass().getResourceAsStream(FOLDER + "temp-table-has-index.ql").readAllBytes(),
StandardCharsets.UTF_8);
QuerySchema querySchema = DcsUtil.getQuerySchema(queryText, project);
assertNotNull(querySchema);
assertEquals(2, querySchema.getQueries().size());
QlBasicDelegateCheck.setOwner(new QueryOwner(querySchema, null));
EObject selectQuery = querySchema.getQueries().get(1);
assertTrue(selectQuery instanceof QuerySchemaSelectQuery);
check.check(selectQuery, resultAcceptor, null, new NullProgressMonitor());
assertTrue(qlResultAcceptor.messages.isEmpty());
assertTrue(qlResultAcceptor.featuredMessages.isEmpty());
selectQuery = querySchema.getQueries().get(0);
assertTrue(selectQuery instanceof QuerySchemaSelectQuery);
check.check(selectQuery, resultAcceptor, null, new NullProgressMonitor());
assertTrue(qlResultAcceptor.messages.isEmpty());
assertTrue(qlResultAcceptor.featuredMessages.isEmpty());
}
}

View File

@ -0,0 +1,48 @@
/*******************************************************************************
* Copyright (C) 2021, 1C-Soft LLC and others.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* 1C-Soft LLC - initial API and implementation
*******************************************************************************/
/**
*
*/
package com.e1c.v8codestyle.ql.itests;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import com.e1c.g5.v8.dt.check.ICheckResultAcceptor;
import com.e1c.g5.v8.dt.check.Issue;
/**
* @author Dmitriy Marmyshev
*
*/
class TestingCheckResultAcceptor
implements ICheckResultAcceptor
{
final Map<Object, Collection<Issue>> issues = new HashMap<>();
Iterable<?> iterable;
@Override
public void addIssue(Object object, Issue issue)
{
issues.computeIfAbsent(object, k -> new ArrayList<>()).add(issue);
}
@Override
public void delegateChecks(Iterable<?> paramIterable)
{
this.iterable = paramIterable;
}
}

View File

@ -0,0 +1,71 @@
/*******************************************************************************
* Copyright (C) 2021, 1C-Soft LLC and others.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* 1C-Soft LLC - initial API and implementation
*******************************************************************************/
/**
*
*/
package com.e1c.v8codestyle.ql.itests;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.xtext.util.Triple;
import org.eclipse.xtext.util.Tuples;
import com.e1c.g5.v8.dt.ql.check.QlBasicDelegateCheck.IQlResultAcceptor;
/**
* @author Dmitriy Marmyshev
*
*/
class TestingQlResultAcceptor
implements IQlResultAcceptor
{
final List<String> messages = new ArrayList<>();
final List<Triple<String, EObject, EStructuralFeature>> featuredMessages = new ArrayList<>();
@Override
public void addIssue(String message)
{
messages.add(message);
}
@Override
public void addIssue(String message, EObject target, EStructuralFeature feature)
{
featuredMessages.add(Tuples.create(message, target, feature));
}
@Override
public void addIssue(String message, EObject target, EStructuralFeature manyFeature, int index)
{
featuredMessages.add(Tuples.create(message, target, manyFeature));
}
@Override
public void addIssue(String message, int length)
{
messages.add(message);
}
@Override
public void addIssue(String message, int lineNumber, int offset, int length)
{
messages.add(message);
}
}

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>QlEmptyProject</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.xtext.ui.shared.xtextBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.xtext.ui.shared.xtextNature</nature>
<nature>com._1c.g5.v8.dt.core.V8ConfigurationNature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,2 @@
eclipse.preferences.version=1
encoding/<project>=UTF-8

View File

@ -0,0 +1,2 @@
Manifest-Version: 1.0
Runtime-Version: 8.3.19

View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<cmi:CommandInterface xmlns:cmi="http://g5.1c.ru/v8/dt/cmi"/>

View File

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<mdclass:Configuration xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass" uuid="94c92315-dfd3-4b19-a4fe-9ee7925c8d60">
<name>StringLiteralCameCase</name>
<synonym>
<key>en</key>
<value>String literal came case</value>
</synonym>
<containedObjects classId="9cd510cd-abfc-11d4-9434-004095e12fc7" objectId="8d8badc8-f461-497c-9189-c0507354369e"/>
<containedObjects classId="9fcd25a0-4822-11d4-9414-008048da11f9" objectId="6ef8f846-54e6-40a4-856c-9782214c8982"/>
<containedObjects classId="e3687481-0a87-462c-a166-9f34594f9bba" objectId="ad988dc7-f15d-4a34-9e4e-f62471f40a89"/>
<containedObjects classId="9de14907-ec23-4a07-96f0-85521cb6b53b" objectId="89643dce-058f-4177-aa9d-9daed21804ca"/>
<containedObjects classId="51f2d5d8-ea4d-4064-8892-82951750031e" objectId="9c307ce3-b9d4-4f5a-8b34-70bb92fb0c70"/>
<containedObjects classId="e68182ea-4237-4383-967f-90c1e3370bc7" objectId="ee13ab61-9465-4ae4-968a-6f48042f3c14"/>
<containedObjects classId="fb282519-d103-4dd3-bc12-cb271d631dfc" objectId="f97bce3c-b163-48cd-b81d-2c7f886fc2cf"/>
<configurationExtensionCompatibilityMode>8.3.19</configurationExtensionCompatibilityMode>
<defaultRunMode>ManagedApplication</defaultRunMode>
<usePurposes>PersonalComputer</usePurposes>
<usedMobileApplicationFunctionalities>
<functionality>
<use>true</use>
</functionality>
<functionality>
<functionality>OSBackup</functionality>
<use>true</use>
</functionality>
</usedMobileApplicationFunctionalities>
<defaultLanguage>Language.English</defaultLanguage>
<dataLockControlMode>Managed</dataLockControlMode>
<objectAutonumerationMode>NotAutoFree</objectAutonumerationMode>
<modalityUseMode>DontUse</modalityUseMode>
<synchronousPlatformExtensionAndAddInCallUseMode>DontUse</synchronousPlatformExtensionAndAddInCallUseMode>
<compatibilityMode>8.3.19</compatibilityMode>
<languages uuid="1948febd-ba2a-4164-b1dd-d54b052e3660">
<name>English</name>
<synonym>
<key>en</key>
<value>English</value>
</synonym>
<languageCode>en</languageCode>
</languages>
</mdclass:Configuration>

View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<cmi:CommandInterface xmlns:cmi="http://g5.1c.ru/v8/dt/cmi"/>