Skip to content

Commit 3417f5b

Browse files
authored
Feat/add snowflake support (#44)
* Add snowflake grammar support * Update rule helper tool * Update rules * Cleanup --------- Co-authored-by: gretard <[email protected]>
1 parent 1beafb9 commit 3417f5b

File tree

140 files changed

+398712
-233436
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

140 files changed

+398712
-233436
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,4 @@ examples/1-tsql/tools
3333

3434
**/tools/**
3535

36+
src/sonar-sql-plugin/examples/**

README.md

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Currently plug-in supports:
1717
- [PostgreSQL](https://github.com/tshprecher/antlr_psql)
1818
- [PostgreSQL](https://github.com/antlr/grammars-v4/tree/master/sql/postgresql)
1919
- [VSQL](https://github.com/gretard/antlr4-grammar-vsql)
20+
- [SNOWFLAKE](https://github.com/antlr/grammars-v4/tree/master/sql/snowflake)
2021
- Reporting of issues found by:
2122
- [SQLCodeGuard](https://www.red-gate.com/products/sql-development/sql-code-guard/index)
2223
- [MSBuild](https://msdn.microsoft.com/en-us/library/dd172133(v=vs.100).aspx)
@@ -34,8 +35,8 @@ Tutorials:
3435

3536
## Requirements ##
3637
Different plugin versions supports the following:
37-
- 1.0.0 - Sonarqube 7.4+versions
38-
- 1.2.0 - Sonarqube 9+versions
38+
- 1.0.0 - Sonarqube 7.4+ versions
39+
- 1.2.0 - Sonarqube 9+ versions
3940

4041
## Installation ##
4142
1. Download and install SonarQube
@@ -97,6 +98,17 @@ sonar.sources=src
9798
sonar.language=sql
9899
sonar.sql.dialect=vsql
99100
```
101+
### SNOWFLAKE ###
102+
Sonar settings for snowflake. You can check example at [here](https://github.com/gretard/sonar-sql-plugin/tree/master/examples/4-vsql)
103+
```
104+
sonar.projectKey=examples.sql.snowflake.project
105+
sonar.projectName=examples.sql.snowflake.project
106+
sonar.projectVersion=1.1
107+
sonar.sources=src
108+
# optional
109+
sonar.language=sql
110+
sonar.sql.dialect=snowflake
111+
```
100112

101113
### Custom rules example ###
102114
This is an example for sonar settings for project which uses custom plugin rules from local directory (located at ./rules directory). You can check full example at [here](https://github.com/gretard/sonar-sql-plugin/tree/master/examples/6-pssql-with-custom-rules)
@@ -140,9 +152,9 @@ Please configure additional properties:
140152
`sonar.lang.patterns.plsqlopen=na`
141153

142154
## Using command line tools
143-
With the plugin - there is additional cli tool available (they are not required for sonar execution):
155+
With the plugin - there is additional cli tool available (it does not require sonar execution):
144156

145-
- **rulesHelper.jar** - command line helper tool for writing custom sql rules
157+
- **rulesHelper.jar** - command line helper tool for working with plugin and custom sql rules
146158

147159

148160
### rulesHelper
@@ -155,19 +167,30 @@ Full help info:
155167

156168
```
157169
Please pass the following:
158-
action (print or verify)
159-
type (text or file)
160-
value (sql string or path to folder)
161-
dialect (tsql, pssql, mysql, pssql, pssqlv2)
162-
Example:
163-
print text "SELECT * FROM dbo.test;" tsql
170+
action (print, verify or analyze)
171+
type (text or file)
172+
value (sql string or path to rules file/folder)
173+
dialect (tsql, pssql, mysql, pssql, pssqlv2, snowflake)
174+
folder (folder to analyze, only applicable when using analyze action)
164175
165-
Example:
166-
verify file "c:/tests/customRules.rules;" mysql
176+
Example to print AST tree:
177+
print text "SELECT * FROM dbo.test;" tsql
178+
179+
Example to verify custom rules definitions:
180+
verify file "c:/tests/customRules.rules;" mysql
181+
182+
Example to execute custom rules and plugin rules against specified folder:
183+
analyze file "c:/tests/customRules.rules;" snowflake "c:\docs\src"
184+
185+
Example to execute sql analysis againt specified folder:
186+
analyze file "NA" snowflake "c:\docs\src"
167187
```
168188

169189

170190
## Contributing ##
191+
### Building locally
192+
Run: ```mvn versions:display-dependency-updates spotless:check spotless:apply install```
193+
171194
### Developing locally
172195
Added container definitions for easy development with VSCode. Download the [remote containers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) and let it figure out the maven targets.
173196
<img width="1917" alt="vscode_remote_containers_extension_maven" src="https://user-images.githubusercontent.com/3657015/125957363-653c9f6f-b5cc-4a3c-96ef-9dc18d0f8bfb.png">
@@ -214,3 +237,5 @@ docker run \
214237
3. Implement sql rules, example VSQLRules
215238
4. Register rules at SQLDialectRules. This step is optional as plugin will support custom rules from user project provided in xml format.
216239
5. Update ./src/external/README.md with references to your added grammar
240+
241+
Example commit for adding Snowflake grammar: https://github.com/gretard/sonar-sql-plugin/commit/e3296a5d1c69a031f24358aad87a4e46c46ea785

azure-pipelines.yml

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,23 @@
11
strategy:
22
matrix:
33
linux:
4-
imageName: 'ubuntu-16.04'
4+
imageName: 'ubuntu-latest'
55
mac:
6-
imageName: 'macos-10.13'
6+
imageName: 'macos-latest'
77
windows:
8-
imageName: 'vs2017-win2016'
8+
imageName: 'windows-latest'
99

1010
pool:
1111
vmImage: $(imageName)
1212
demands: maven
1313

1414
steps:
15+
- task: JavaToolInstaller@0
16+
inputs:
17+
versionSpec: '11'
18+
jdkArchitectureOption: 'x64'
19+
jdkSourceOption: 'PreInstalled'
20+
1521
- task: Maven@3
1622
displayName: 'Maven sonar-sql-plugin install'
1723
inputs:

docs/customRulesSetup.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ Mandatory fields for rule:
4545
- FailIfNotFound - reports code issue if no node was found violating rule
4646
- FailIfLessFound/FailIfMoreFound - reports code issue if rule was not violated less or more times than value defined by times value
4747
- SkipIfFound/SkipIfNotFound - skips code issue reporting at all if rule was satisfied or not
48+
- SkipIfLessFound/SkipIfMoreFound - skips code issue reporting at all if rule was matches less or more times than value defined by times value
4849
- textCheckType - defines how to search for particular text in nodes, can be:
4950
- Contains - will be checked if node contains some defined text
5051
- Regexp - will be checked if node's text matches regexp

docs/pluginRules.md

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,16 @@
33
SLEEP/WAITFOR is used<h2>Code examples</h2><h3>Non-compliant</h3><pre><code>WAITFOR '10:00:00';</code></pre>
44

55
## C002 - SELECT * is used
6-
<p>Supported dialects: MYSQL,PSSQLV2,TSQL</p>
6+
<p>Supported dialects: MYSQL,SNOWFLAKE,PSSQLV2,TSQL</p>
77
<h2>Description</h2><p>SELECT * is used. Please list names.</p><h2>Code examples</h2><h3>Non-compliant</h3><pre><code>SELECT t1.*, t2.* from dbo.test as t1 inner join dbo.test2 as t2 on t1.id=t2.id;</code></pre><h3>Compliant</h3><pre><code>SELECT name, surname from dbo.test;</code></pre><pre><code>SELECT name, surname, 1 * 3 from dbo.test;</code></pre>
88

99
## C003 - INSERT statement without columns listed
10-
<p>Supported dialects: MYSQL,PSSQLV2,TSQL</p>
10+
<p>Supported dialects: MYSQL,SNOWFLAKE,PSSQLV2,TSQL</p>
1111
<h2>Description</h2><p>INSERT statement does not have columns listed. Always use a column list in your INSERT statements.</p><h2>Code examples</h2><h3>Non-compliant</h3><pre><code>INSERT INTO dbo.test VALUES (1,2);
1212
INSERT INTO dbo.test2 VALUES (1,2);</code></pre><h3>Compliant</h3><pre><code>INSERT INTO dbo.test (a,b) VALUES (1,2);</code></pre>
1313

1414
## C004 - ORDER BY clause contains positional references
15-
<p>Supported dialects: MYSQL,PSSQL,PSSQLV2,TSQL</p>
15+
<p>Supported dialects: MYSQL,PSSQL,SNOWFLAKE,PSSQLV2,TSQL</p>
1616
<h2>Description</h2><p>Do not use column numbers in the ORDER BY clause. Always use column names in an order by clause. Avoid positional references.</p><h2>Code examples</h2><h3>Non-compliant</h3><pre><code>SELECT * from dbo.test order by 1, 2;</code></pre><h3>Compliant</h3><pre><code>SELECT * from dbo.test order by name;</code></pre>
1717

1818
## C005 - EXECUTE/EXEC for dynamic query is used
@@ -24,8 +24,8 @@ INSERT INTO dbo.test2 VALUES (1,2);</code></pre><h3>Compliant</h3><pre><code>INS
2424
<h2>Description</h2><p>Use of NOLOCK might cause data inconsistency problems.</p><h2>Code examples</h2><h3>Non-compliant</h3><pre><code>SELECT name, surname from dbo.test WITH (NOLOCK);</code></pre><h3>Compliant</h3><pre><code>SELECT name, surname from dbo.test;</code></pre>
2525

2626
## C009 - Non-sargable statement used
27-
<p>Supported dialects: MYSQL,PSSQL,PSSQLV2,TSQL</p>
28-
<h2>Description</h2><p>Use of non-sargeable arguments might cause performance problems.</p><h2>Code examples</h2><h3>Non-compliant</h3><pre><code>SELECT name, surname from dbo.test where year(date) > 2008 and month = 12;</code></pre><pre><code>SELECT name, surname from dbo.test where name like '%red' </code></pre><h3>Compliant</h3><pre><code>SELECT MAX(RateChangeDate) FROM HumanResources.EmployeePayHistory WHERE BusinessEntityID = 1</code></pre><pre><code>SELECT name, surname from dbo.test where date between 2008-10-10 and 2010-10-10;</code></pre><pre><code>SELECT max(price) from dbo.items;</code></pre>
27+
<p>Supported dialects: VSQL,MYSQL,PSSQL,SNOWFLAKE,PSSQLV2,TSQL</p>
28+
<h2>Description</h2><p>Use of non-sargeable arguments might cause performance problems.</p><h2>Code examples</h2><h3>Non-compliant</h3><pre><code>SELECT name, surname from dbo.test where year(date) > 2008 and month = 12;</code></pre><pre><code>SELECT name, surname from dbo.test where name like '%red' </code></pre><h3>Compliant</h3><pre><code>SELECT MAX(RateChangeDate) FROM HumanResources.EmployeePayHistory WHERE BusinessEntityID = 1</code></pre><pre><code>SELECT name, surname from dbo.test where date between 2008-10-10 and 2010-10-10;</code></pre><pre><code>SELECT max(price) from dbo.items;</code></pre><pre><code>select department_id, count(*) from employees group by department_id having count (*) < 10;</code></pre>
2929

3030
## C010 - Defined primary key is not using recommended naming convention
3131
<p>Supported dialects: TSQL</p>
@@ -44,39 +44,47 @@ PRIMARY KEY (Id)
4444
<h2>Description</h2><p>Defined foreign key is not using recommended naming convention to start with FK_.</p><h2>Code examples</h2><h3>Non-compliant</h3><pre><code>ALTER TABLE dbo.Orders ADD CONSTRAINT ClientId FOREIGN KEY (ClientId) REFERENCES dbo.Clients(Id); </code></pre><h3>Compliant</h3><pre><code>ALTER TABLE dbo.Orders ADD CONSTRAINT FK_ClientId FOREIGN KEY (ClientId) REFERENCES dbo.Clients(Id); </code></pre>
4545

4646
## C012 - Comparison operator (=, <>, !=) to check if value is null used
47-
<p>Supported dialects: MYSQL,PSSQL,PSSQLV2,TSQL</p>
47+
<p>Supported dialects: MYSQL,PSSQL,SNOWFLAKE,PSSQLV2,TSQL</p>
4848
<h2>Description</h2><p>It is not advisable to use comparison operator to check if value is null as comparison operators return UNKNOWN when either or both arguments are NULL. Please use IS NULL or IS NOT NULL instead.</p><h2>Code examples</h2><h3>Non-compliant</h3><pre><code>SELECT * from dbo.test where name = null and surname = 'Test' ;</code></pre><pre><code>SELECT * from dbo.test where name != null;</code></pre><pre><code>SELECT * from dbo.test where name <> null;</code></pre><h3>Compliant</h3><pre><code>SELECT * from dbo.test where name IS NULL;</code></pre><pre><code>SELECT * from dbo.test where name IS NOT NULL;</code></pre><pre><code>SELECT * from dbo.test where name = 'test';</code></pre>
4949

5050
## C013 - Defined index name is not using recommended naming convention
5151
<p>Supported dialects: TSQL</p>
5252
<h2>Description</h2><p>Defined index name is not using recommended naming convention to start with IX_.</p><h2>Code examples</h2><h3>Non-compliant</h3><pre><code>CREATE UNIQUE INDEX Test_Name on dbo.test (Name);</code></pre><h3>Compliant</h3><pre><code>CREATE UNIQUE INDEX IX_Test_Name on dbo.test (Name);</code></pre>
5353

5454
## C014 - OR verb is used in a WHERE clause
55-
<p>Supported dialects: MYSQL,PSSQL,PSSQLV2,TSQL</p>
55+
<p>Supported dialects: MYSQL,PSSQL,SNOWFLAKE,PSSQLV2,TSQL</p>
5656
<h2>Description</h2><p>It is advisable to consider using UNION/UNION ALL operator instead of OR verb in the WHERE clause.</p><h2>Code examples</h2><h3>Non-compliant</h3><pre><code>SELECT name, surname, count from dbo.test where name = 'Test' OR surname = 'Testor';</code></pre><h3>Compliant</h3><pre><code>SELECT name, surname, count from dbo.test where name = 'or' and surname = 'TestOR';</code></pre>
5757

5858
## C015 - UNION operator is used
59-
<p>Supported dialects: MYSQL,PSSQL,PSSQLV2,TSQL</p>
59+
<p>Supported dialects: MYSQL,PSSQL,SNOWFLAKE,PSSQLV2,TSQL</p>
6060
<h2>Description</h2><p>It is advisable to consider using UNION ALL operator instead of UNION.</p><h2>Code examples</h2><h3>Non-compliant</h3><pre><code>SELECT name, surname, count from dbo.test union SELECT name, surname, count from dbo.test2;</code></pre><h3>Compliant</h3><pre><code>SELECT name, surname, count from dbo.test union all SELECT name, surname, count from dbo.test2;</code></pre>
6161

6262
## C016 - IN/NOT IN is used for a subquery
63-
<p>Supported dialects: MYSQL,PSSQL,PSSQLV2,TSQL</p>
63+
<p>Supported dialects: MYSQL,PSSQL,SNOWFLAKE,PSSQLV2,TSQL</p>
6464
<h2>Description</h2><p>Consider using EXISTS/NOT EXISTS operator instead of IN for a subquery.</p><h2>Code examples</h2><h3>Non-compliant</h3><pre><code>SELECT name, surname, count from dbo.test where locationID in (select id from dbo.locations);</code></pre><h3>Compliant</h3><pre><code>SELECT name, surname, count from dbo.test where locationID in (1,2,3);</code></pre><pre><code>SELECT name, surname, count from dbo.test where exists (select 1 from dbo.locations where id = locationID);</code></pre>
6565

6666
## C017 - ORDER BY clause does not contain order (ASC/DESC)
67-
<p>Supported dialects: MYSQL,PSSQL,PSSQLV2,TSQL</p>
67+
<p>Supported dialects: MYSQL,PSSQL,SNOWFLAKE,PSSQLV2,TSQL</p>
6868
<h2>Description</h2><p>It is advisable to specidy order how rows should be ordered.</p><h2>Code examples</h2><h3>Non-compliant</h3><pre><code>SELECT name, surname from dbo.test order by name, surname asc;</code></pre><h3>Compliant</h3><pre><code>SELECT name, surname from dbo.test order by name desc, surname asc;</code></pre>
6969

7070
## C020 - HINT is used
7171
<p>Supported dialects: VSQL</p>
72-
HINT is used. Consider rewriting this statement.<h2>Code examples</h2><h3>Non-compliant</h3><pre><code>SELECT /*+DIRECT*/ * FROM test_table1;</code></pre><pre><code>CREATE TABLE test_table2 AS SELECT /*+DIRECT*/ * FROM test_table1;</code></pre><h3>Compliant</h3><pre><code>SELECT * FROM test_table1;</code></pre>
72+
<h2>Description</h2><p>HINT is used. Consider rewriting this statement.</p><h2>Code examples</h2><h3>Non-compliant</h3><pre><code>SELECT /*+DIRECT*/ * FROM test_table1;</code></pre><pre><code>CREATE TABLE test_table2 AS SELECT /*+DIRECT*/ * FROM test_table1;</code></pre><h3>Compliant</h3><pre><code>SELECT * FROM test_table1;</code></pre>
7373

7474
## C021 - COMMIT is missing
7575
<p>Supported dialects: VSQL</p>
76-
COMMIT is missing after UPDATE/DELETE statement. If you run script without autocommit - your changes might be lost.<h2>Code examples</h2><h3>Non-compliant</h3><pre><code>SELECT 1; DELETE FROM temp1; SELECT 2;</code></pre><pre><code>COMMIT; DELETE FROM temp1;</code></pre><h3>Compliant</h3><pre><code>SELECT 1; DELETE FROM temp1; COMMIT; SELECT 2; </code></pre>
76+
<h2>Description</h2><p>COMMIT is missing after UPDATE/DELETE statement. If you run script without autocommit - your changes might be lost.</p><h2>Code examples</h2><h3>Non-compliant</h3><pre><code>SELECT 1; DELETE FROM temp1; SELECT 2;</code></pre><pre><code>COMMIT; DELETE FROM temp1;</code></pre><h3>Compliant</h3><pre><code>SELECT 1; DELETE FROM temp1; COMMIT; SELECT 2; </code></pre>
77+
78+
## C022 - Non-materialized view found
79+
<p>Supported dialects: SNOWFLAKE</p>
80+
<h2>Description</h2><p>Consider using materialized view.</p><h2>Code examples</h2><h3>Non-compliant</h3><pre><code>CREATE VIEW V1 (C1) AS SELECT 1 as C1;</code></pre><h3>Compliant</h3><pre><code>CREATE MATERIALIZED VIEW V1 (C1) AS SELECT 1 as C1;</code></pre>
81+
82+
## C023 - Cartesian join found
83+
<p>Supported dialects: VSQL,MYSQL,SNOWFLAKE,PSSQLV2,TSQL</p>
84+
<h2>Description</h2><p>Cartesian join without explicit JOIN clause. Consider using explicit JOIN clause.</p><h2>Code examples</h2><h3>Non-compliant</h3><pre><code>SELECT name, order_id FROM customers, orders WHERE customers.id = orders.customer_id;</code></pre><h3>Compliant</h3><pre><code>SELECT name, surname FROM customers c</code></pre><pre><code>SELECT name, bank_name FROM customers c inner join banks b on c.bank_id = b.id</code></pre>
7785

7886
## C030 - File does not start with multiline/header comment
79-
<p>Supported dialects: null</p>
87+
<p>Supported dialects: TSQL,PSSQL,MYSQL,VSQL,PSSQLV2,SNOWFLAKE</p>
8088
File does not start with multiline/header comment.<h2>Code examples</h2><h3>Non-compliant</h3><pre><code>SELECT * FROM test_table1;</code></pre><pre><code>SELECT * FROM test_table1; /*additionalComment*/ </code></pre><h3>Compliant</h3><pre><code>/* AUTHOR: test
8189
Date: 2020-01-01
8290
*/

0 commit comments

Comments
 (0)