@neralabs/rerail-pack-sql 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,53 @@
1
+ {
2
+ "format": "rerail.policy/v1",
3
+ "id": "sqlfluff-am01-ambiguous-distinct",
4
+ "revision": 1,
5
+ "mode": "steer",
6
+ "description": "Avoid DISTINCT in a SQL SELECT that already has GROUP BY; the grouping already makes the rows unique.",
7
+ "scope": {
8
+ "include": [
9
+ "**/*.sql"
10
+ ],
11
+ "exclude": []
12
+ },
13
+ "clauses": [
14
+ {
15
+ "id": "distinct-with-group-by",
16
+ "forbid": {
17
+ "ast": {
18
+ "language": "sql",
19
+ "rule": {
20
+ "kind": "keyword_distinct",
21
+ "inside": {
22
+ "kind": "select",
23
+ "stopBy": "neighbor",
24
+ "precedes": {
25
+ "kind": "from",
26
+ "has": {
27
+ "kind": "group_by"
28
+ }
29
+ }
30
+ }
31
+ }
32
+ }
33
+ },
34
+ "violation": {
35
+ "anchor": "witness.start",
36
+ "code": "AM01",
37
+ "message": "Remove DISTINCT from this SELECT; its GROUP BY already makes the rows unique.",
38
+ "suppress": {
39
+ "sqlfluff": {
40
+ "rules": [
41
+ "AM01",
42
+ "L021",
43
+ "all",
44
+ "ambiguous",
45
+ "ambiguous.distinct",
46
+ "core"
47
+ ]
48
+ }
49
+ }
50
+ }
51
+ }
52
+ ]
53
+ }
@@ -0,0 +1 @@
1
+ {"format":"rerail.policy/v1","id":"sqlfluff-am05-ambiguous-join","revision":1,"mode":"steer","description":"Write INNER JOIN instead of a bare JOIN in SQL so the join type is explicit.","scope":{"include":["**/*.sql"],"exclude":[]},"clauses":[{"id":"bare-join","forbid":{"ast":{"language":"sql","rule":{"any":[{"kind":"join"},{"kind":"lateral_join"}],"regex":"(?i)^join\\b"}}},"violation":{"anchor":"witness.start","code":"AM05","message":"Write this join as INNER JOIN so its type is explicit.", "suppress": { "sqlfluff": { "rules": ["AM05", "L051", "all", "ambiguous", "ambiguous.join"] } }}}]}
@@ -0,0 +1,110 @@
1
+ {
2
+ "format": "rerail.policy/v1",
3
+ "id": "sqlfluff-am09-ambiguous-order-by-limit",
4
+ "revision": 1,
5
+ "mode": "steer",
6
+ "description": "Add ORDER BY to any SQL query that uses LIMIT or OFFSET; without it, which rows come back is not deterministic.",
7
+ "scope": {
8
+ "include": [
9
+ "**/*.sql"
10
+ ],
11
+ "exclude": []
12
+ },
13
+ "clauses": [
14
+ {
15
+ "id": "limit-without-order-by",
16
+ "forbid": {
17
+ "ast": {
18
+ "language": "sql",
19
+ "rule": {
20
+ "kind": "limit",
21
+ "not": {
22
+ "any": [
23
+ {
24
+ "follows": {
25
+ "kind": "order_by",
26
+ "stopBy": "end"
27
+ }
28
+ },
29
+ {
30
+ "inside": {
31
+ "kind": "from",
32
+ "stopBy": "neighbor",
33
+ "inside": {
34
+ "kind": "set_operation",
35
+ "stopBy": "neighbor"
36
+ },
37
+ "not": {
38
+ "precedes": {
39
+ "regex": "(?s)."
40
+ }
41
+ }
42
+ }
43
+ }
44
+ ]
45
+ }
46
+ }
47
+ }
48
+ },
49
+ "violation": {
50
+ "anchor": "witness.start",
51
+ "code": "AM09",
52
+ "message": "LIMIT and OFFSET are used without ORDER BY, which may lead to non-deterministic results.",
53
+ "suppress": {
54
+ "sqlfluff": {
55
+ "rules": [
56
+ "AM09",
57
+ "all",
58
+ "ambiguous",
59
+ "ambiguous.order_by_limit"
60
+ ]
61
+ }
62
+ }
63
+ }
64
+ },
65
+ {
66
+ "id": "offset-without-limit-or-order-by",
67
+ "forbid": {
68
+ "ast": {
69
+ "language": "sql",
70
+ "rule": {
71
+ "kind": "select",
72
+ "has": {
73
+ "all": [
74
+ {
75
+ "pattern": "$OFFSET",
76
+ "kind": "offset"
77
+ },
78
+ {
79
+ "not": {
80
+ "kind": "limit"
81
+ }
82
+ },
83
+ {
84
+ "not": {
85
+ "kind": "order_by"
86
+ }
87
+ }
88
+ ]
89
+ }
90
+ }
91
+ }
92
+ },
93
+ "violation": {
94
+ "anchor": "capture.OFFSET",
95
+ "code": "AM09",
96
+ "message": "LIMIT and OFFSET are used without ORDER BY, which may lead to non-deterministic results.",
97
+ "suppress": {
98
+ "sqlfluff": {
99
+ "rules": [
100
+ "AM09",
101
+ "all",
102
+ "ambiguous",
103
+ "ambiguous.order_by_limit"
104
+ ]
105
+ }
106
+ }
107
+ }
108
+ }
109
+ ]
110
+ }
@@ -0,0 +1 @@
1
+ {"format":"rerail.policy/v1","id":"sqlfluff-cv02-convention-coalesce","revision":1,"mode":"steer","description":"Use COALESCE instead of IFNULL or NVL in SQL; it is standard and works across databases.","scope":{"include":["**/*.sql"],"exclude":[]},"clauses":[{"id":"prefer-coalesce","forbid":{"ast":{"language":"sql","rule":{"kind":"invocation","has":{"kind":"object_reference","has":{"kind":"identifier","regex":"(?i)^(ifnull|nvl)$"}},"not":{"has":{"kind":"object_reference","regex":"\\."}}}}},"violation":{"anchor":"witness.start","code":"CV02","message":"Use COALESCE instead of IFNULL or NVL.", "suppress": { "sqlfluff": { "rules": ["CV02", "L060", "all", "convention", "convention.coalesce"] } }}}]}
@@ -0,0 +1,52 @@
1
+ {
2
+ "format": "rerail.policy/v1",
3
+ "id": "sqlfluff-cv04-convention-count-rows",
4
+ "revision": 1,
5
+ "mode": "steer",
6
+ "description": "Use COUNT(*) instead of COUNT(1) or COUNT(0) to count rows in SQL; it states the intent directly.",
7
+ "scope": {
8
+ "include": [
9
+ "**/*.sql"
10
+ ],
11
+ "exclude": []
12
+ },
13
+ "clauses": [
14
+ {
15
+ "id": "count-literal",
16
+ "forbid": {
17
+ "ast": {
18
+ "language": "sql",
19
+ "rule": {
20
+ "kind": "invocation",
21
+ "regex": "^(?i:count)\\s*\\(\\s*[01]\\s*\\)$",
22
+ "has": {
23
+ "field": "parameter",
24
+ "kind": "term",
25
+ "has": {
26
+ "field": "value",
27
+ "kind": "literal"
28
+ }
29
+ }
30
+ }
31
+ }
32
+ },
33
+ "violation": {
34
+ "anchor": "witness.start",
35
+ "code": "CV04",
36
+ "message": "Use COUNT(*) to count rows.",
37
+ "suppress": {
38
+ "sqlfluff": {
39
+ "rules": [
40
+ "CV04",
41
+ "L047",
42
+ "all",
43
+ "convention",
44
+ "convention.count_rows",
45
+ "core"
46
+ ]
47
+ }
48
+ }
49
+ }
50
+ }
51
+ ]
52
+ }
@@ -0,0 +1,61 @@
1
+ {
2
+ "format": "rerail.policy/v1",
3
+ "id": "sqlfluff-cv05-convention-is-null",
4
+ "revision": 1,
5
+ "mode": "steer",
6
+ "description": "Use IS NULL or IS NOT NULL instead of comparing to NULL with =, != or <>; such a comparison is never true.",
7
+ "scope": {
8
+ "include": [
9
+ "**/*.sql"
10
+ ],
11
+ "exclude": []
12
+ },
13
+ "clauses": [
14
+ {
15
+ "id": "relational-null-comparison",
16
+ "forbid": {
17
+ "ast": {
18
+ "language": "sql",
19
+ "rule": {
20
+ "kind": "binary_expression",
21
+ "all": [
22
+ {
23
+ "has": {
24
+ "field": "operator",
25
+ "regex": "^(?:=|!=|<>)$",
26
+ "pattern": "$$OP"
27
+ }
28
+ },
29
+ {
30
+ "has": {
31
+ "field": "right",
32
+ "kind": "literal",
33
+ "has": {
34
+ "kind": "keyword_null"
35
+ }
36
+ }
37
+ }
38
+ ]
39
+ }
40
+ }
41
+ },
42
+ "violation": {
43
+ "anchor": "capture.OP",
44
+ "code": "CV05",
45
+ "message": "Comparisons with NULL should use IS or IS NOT.",
46
+ "suppress": {
47
+ "sqlfluff": {
48
+ "rules": [
49
+ "CV05",
50
+ "L049",
51
+ "all",
52
+ "convention",
53
+ "convention.is_null",
54
+ "core"
55
+ ]
56
+ }
57
+ }
58
+ }
59
+ }
60
+ ]
61
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "format": "rerail.policy/v1",
3
+ "id": "sqlfluff-cv08-convention-left-join",
4
+ "revision": 1,
5
+ "mode": "steer",
6
+ "description": "Use LEFT JOIN instead of RIGHT JOIN in SQL, swapping the table order; joins that all read left to right are easier to follow.",
7
+ "scope": {"include": ["**/*.sql"], "exclude": []},
8
+ "clauses": [
9
+ {
10
+ "id": "right-join",
11
+ "forbid": {"ast": {"language": "sql", "rule": {
12
+ "kind": "join",
13
+ "has": {"stopBy": "neighbor", "kind": "keyword_right"}
14
+ }}},
15
+ "violation": {"anchor": "witness.start", "code": "CV08", "message": "Use LEFT JOIN instead of RIGHT JOIN.", "suppress": { "sqlfluff": { "rules": ["CV08", "L055", "all", "convention", "convention.left_join"] } }}
16
+ }
17
+ ]
18
+ }
@@ -0,0 +1,234 @@
1
+ {
2
+ "format": "rerail.policy/v1",
3
+ "id": "sqlfluff-pg01-postgres-excessive-locks",
4
+ "revision": 1,
5
+ "mode": "steer",
6
+ "description": "Use CONCURRENTLY on non-unique CREATE INDEX, DROP INDEX, REINDEX and REFRESH MATERIALIZED VIEW in PostgreSQL; otherwise the table is locked while it runs.",
7
+ "scope": {
8
+ "include": [
9
+ "**/*.sql"
10
+ ],
11
+ "exclude": []
12
+ },
13
+ "clauses": [
14
+ {
15
+ "id": "create-index-without-concurrently",
16
+ "forbid": {
17
+ "ast": {
18
+ "language": "sql",
19
+ "rule": {
20
+ "kind": "create_index",
21
+ "all": [
22
+ {
23
+ "not": {
24
+ "has": {
25
+ "kind": "keyword_concurrently"
26
+ }
27
+ }
28
+ },
29
+ {
30
+ "not": {
31
+ "has": {
32
+ "kind": "keyword_unique"
33
+ }
34
+ }
35
+ },
36
+ {
37
+ "not": {
38
+ "inside": {
39
+ "stopBy": "end",
40
+ "any": [
41
+ {
42
+ "kind": "function_body"
43
+ },
44
+ {
45
+ "kind": "block"
46
+ },
47
+ {
48
+ "kind": "ERROR"
49
+ }
50
+ ]
51
+ }
52
+ }
53
+ }
54
+ ]
55
+ }
56
+ }
57
+ },
58
+ "violation": {
59
+ "anchor": "witness.start",
60
+ "code": "PG01",
61
+ "message": "CREATE INDEX should use CONCURRENTLY to avoid locking the table during the build.",
62
+ "suppress": {
63
+ "sqlfluff": {
64
+ "rules": [
65
+ "PG01",
66
+ "all",
67
+ "postgres",
68
+ "postgres.excessive_locks"
69
+ ]
70
+ }
71
+ }
72
+ }
73
+ },
74
+ {
75
+ "id": "drop-index-without-concurrently",
76
+ "forbid": {
77
+ "ast": {
78
+ "language": "sql",
79
+ "rule": {
80
+ "kind": "drop_index",
81
+ "all": [
82
+ {
83
+ "not": {
84
+ "has": {
85
+ "kind": "keyword_concurrently"
86
+ }
87
+ }
88
+ },
89
+ {
90
+ "not": {
91
+ "inside": {
92
+ "stopBy": "end",
93
+ "any": [
94
+ {
95
+ "kind": "function_body"
96
+ },
97
+ {
98
+ "kind": "block"
99
+ },
100
+ {
101
+ "kind": "ERROR"
102
+ }
103
+ ]
104
+ }
105
+ }
106
+ }
107
+ ]
108
+ }
109
+ }
110
+ },
111
+ "violation": {
112
+ "anchor": "witness.start",
113
+ "code": "PG01",
114
+ "message": "DROP statement should use CONCURRENTLY to avoid locking the table.",
115
+ "suppress": {
116
+ "sqlfluff": {
117
+ "rules": [
118
+ "PG01",
119
+ "all",
120
+ "postgres",
121
+ "postgres.excessive_locks"
122
+ ]
123
+ }
124
+ }
125
+ }
126
+ },
127
+ {
128
+ "id": "reindex-without-concurrently",
129
+ "forbid": {
130
+ "ast": {
131
+ "language": "sql",
132
+ "rule": {
133
+ "kind": "reindex_statement",
134
+ "all": [
135
+ {
136
+ "not": {
137
+ "has": {
138
+ "kind": "keyword_concurrently"
139
+ }
140
+ }
141
+ },
142
+ {
143
+ "not": {
144
+ "inside": {
145
+ "stopBy": "end",
146
+ "any": [
147
+ {
148
+ "kind": "function_body"
149
+ },
150
+ {
151
+ "kind": "block"
152
+ },
153
+ {
154
+ "kind": "ERROR"
155
+ }
156
+ ]
157
+ }
158
+ }
159
+ }
160
+ ]
161
+ }
162
+ }
163
+ },
164
+ "violation": {
165
+ "anchor": "witness.start",
166
+ "code": "PG01",
167
+ "message": "REINDEX statement should use CONCURRENTLY to avoid locking the table.",
168
+ "suppress": {
169
+ "sqlfluff": {
170
+ "rules": [
171
+ "PG01",
172
+ "all",
173
+ "postgres",
174
+ "postgres.excessive_locks"
175
+ ]
176
+ }
177
+ }
178
+ }
179
+ },
180
+ {
181
+ "id": "refresh-without-concurrently",
182
+ "forbid": {
183
+ "ast": {
184
+ "language": "sql",
185
+ "rule": {
186
+ "kind": "refresh_statement",
187
+ "all": [
188
+ {
189
+ "not": {
190
+ "has": {
191
+ "kind": "keyword_concurrently"
192
+ }
193
+ }
194
+ },
195
+ {
196
+ "not": {
197
+ "inside": {
198
+ "stopBy": "end",
199
+ "any": [
200
+ {
201
+ "kind": "function_body"
202
+ },
203
+ {
204
+ "kind": "block"
205
+ },
206
+ {
207
+ "kind": "ERROR"
208
+ }
209
+ ]
210
+ }
211
+ }
212
+ }
213
+ ]
214
+ }
215
+ }
216
+ },
217
+ "violation": {
218
+ "anchor": "witness.start",
219
+ "code": "PG01",
220
+ "message": "REFRESH statement should use CONCURRENTLY to avoid locking the table.",
221
+ "suppress": {
222
+ "sqlfluff": {
223
+ "rules": [
224
+ "PG01",
225
+ "all",
226
+ "postgres",
227
+ "postgres.excessive_locks"
228
+ ]
229
+ }
230
+ }
231
+ }
232
+ }
233
+ ]
234
+ }
@@ -0,0 +1,75 @@
1
+ {
2
+ "format": "rerail.policy/v1",
3
+ "id": "sqlfluff-pg02-postgres-not-valid-foreign-key",
4
+ "revision": 1,
5
+ "mode": "steer",
6
+ "description": "Add PostgreSQL foreign keys with NOT VALID and validate them in a separate step; checking existing rows at once locks the table.",
7
+ "scope": {
8
+ "include": [
9
+ "**/*.sql"
10
+ ],
11
+ "exclude": []
12
+ },
13
+ "clauses": [
14
+ {
15
+ "id": "foreign-key-without-not-valid",
16
+ "forbid": {
17
+ "ast": {
18
+ "language": "sql",
19
+ "rule": {
20
+ "kind": "alter_table",
21
+ "has": {
22
+ "kind": "add_constraint",
23
+ "has": {
24
+ "kind": "constraint",
25
+ "has": {
26
+ "kind": "keyword_foreign"
27
+ }
28
+ },
29
+ "not": {
30
+ "has": {
31
+ "kind": "keyword_valid"
32
+ }
33
+ }
34
+ },
35
+ "all": [
36
+ {
37
+ "not": {
38
+ "inside": {
39
+ "stopBy": "end",
40
+ "any": [
41
+ {
42
+ "kind": "function_body"
43
+ },
44
+ {
45
+ "kind": "block"
46
+ },
47
+ {
48
+ "kind": "ERROR"
49
+ }
50
+ ]
51
+ }
52
+ }
53
+ }
54
+ ]
55
+ }
56
+ }
57
+ },
58
+ "violation": {
59
+ "anchor": "witness.start",
60
+ "code": "PG02",
61
+ "message": "Add this foreign key with NOT VALID and run VALIDATE CONSTRAINT as a separate step, so the table isn't locked.",
62
+ "suppress": {
63
+ "sqlfluff": {
64
+ "rules": [
65
+ "PG02",
66
+ "all",
67
+ "postgres",
68
+ "postgres.not_valid_foreign_key"
69
+ ]
70
+ }
71
+ }
72
+ }
73
+ }
74
+ ]
75
+ }