Exit Codes

By default, SDF exits with the following status codes
  • 0 if no linter violations were found
  • 0 if linter completes successfully with any number of linter warnings
  • 64 if the linter fails for syntax reasons in any file
In CI/CD scenarios you may want to have the linter exit with a non-zero code if the linter finds any violations. For this, SDF supports the -w error flag which turns any lint warning into an error. In sdf yml, you configure this as follows::
---
sdf-args:
  # turns lint warnings into errors with non-zero exit code
  lint: >
    -w error 

Capitalization Keywords

SDF107

Inconsistent capitalization of keywords
ConfigurationSDF ErrorSQLFluff AliasAuto-fix
capitalization-keywordsSDF107L010
Example: sdf lint -w capitalization-keywords=upper Configuration:
workspace.sdf.yml
sdf-args
   lint: >
      -w capitalization-keywords=consistent 
      ...
   
# capitalization_keywords is one of [consistent, upper, lower, pascal, snake, camel, off]
# Default: capitalization-keywords=consistent
Anti-pattern Referencing keywords in inconsistent capitalization. All keywords should be either uppercase or lowercase, not both. Keywords are dialect-specific.
select a 
FROM my_table 
Best-practice
SELECT a 
FROM my_table 
 
-- or 
 
select a 
from my_table 

Capitalization Literals

SDF108

SDF109

Inconsistent capitalization of boolean/null literal
ConfigurationSDF ErrorSQLFluff AliasAuto-fix
capitalization-literalsSDF108, SDF109L040
Example: sdf lint -w capitalization-literals=upper Configuration:
workspace.sdf.yml
sdf-args
   lint: >
      -w capitalization-keywords=consistent 
      ...
   # capitalization-literals is one of [consistent, upper, lower, pascal, snake, camel, off] 
   # default: capitalization-literals: consistent
Anti-pattern Referencing literals in inconsistent capitalization. All references should be either uppercase or lowercase, not both.
SELECT 
   a, 
   null, 
   true, 
   FALSE 
FROM my_table 
Best-practice
SELECT 
   a, 
   NULL, 
   TRUE, 
   FALSE 
FROM my_table 
 
-- or 
 
SELECT 
   a, 
   null, 
   true, 
   false 
FROM my_table 

Capitalization Types

SDF110

Inconsistent capitalization of datatypes.
ConfigurationSDF ErrorSQLFluff AliasAuto-fix
capitalization-typesSDF110L063
Example: sdf lint -w capitalization-types=upper Configuration:
workspace.sdf.yml
sdf-args
   lint: >
      -w capitalization-types=consistent 
      ...
   # capitalization-types is one of [consistent, upper, lower, pascal, snake, camel, off] 
   # default: capitalization-types: consistent
Anti-pattern Referencing datatypes in inconsistent capitalization. All references should be either uppercase or lowercase, not both.
CREATE TABLE t ( 
   a INT, 
   b varchar(100) 
); 
Best-practice
CREATE TABLE t ( 
   a INT, 
   b VARCHAR(100) 
); 
 
-- or 
 
CREATE TABLE t ( 
   a int, 
   b varchar(100) 
); 

Capitalization Functions

SDF106

Inconsistent capitalization of function names
ConfigurationSDF ErrorSQLFluff AliasAuto-fix
capitalization-functionsSDF106L030
Example: sdf lint -w capitalization-functions=upper Configuration:
workspace.sdf.yml
sdf-args
   lint: >
      -w capitalization-functions=consistent 
      ...
   # capitalization-functions is one of [consistent, upper, lower, pascal, snake, camel, off] 
   # default: capitalization-functions: consistent
Anti-pattern Referencing functions in inconsistent capitalization. All references should be either uppercase or lowercase, not both.
SELECT 
   max(a) AS max_a, 
   MIN(a) AS min_a 
FROM my_table 
Best-practice
SELECT 
   MAX(a) AS max_a, 
   MIN(a) AS min_a 
FROM my_table 
 
-- or 
 
SELECT 
   max(a) AS max_a, 
   min(a) AS min_a 
FROM my_table 

Convention Blocked Words

SDF124

Specify a list of names to block from being identifiers.
ConfigurationSDF ErrorSQLFluff AliasAuto-fix
convention-blocked-wordsSDF124L062
Examples:
  • Blocking a single word: sdf lint -w convention-blocked-words=department
  • Blocking multiple words: sdf lint -w convention-blocked-words=word1,word2,...,wordn
Configuration:
workspace.sdf.yml
sdf-args
   lint: >
      -w convention-blocked-words=foooo
      ...
   # default: []

References Keywords

SDF125

Keywords should not be used as identifiers
ConfigurationSDF ErrorSQLFluff AliasAuto-fix
references-keywordsSDF125L029
Example: sdf lint -w references-keywords Configuration:
workspace.sdf.yml
sdf-args
   lint: >
      -w references-keywords
      ...
Anti-pattern Using built-in keywords or functions as identifiers. sss
SELECT
    sum.a
FROM foo AS sum
Best-practice
SELECT
    vee.a
FROM foo AS vee

References Special Chars

SDF117

Do not use special characters in identifiers
ConfigurationSDF ErrorSQLFluff AliasAuto-fix
references-special-charsSDF117L057
Example:
  • Disallows $ character: sdf lint -w references-special-chars=$
  • Disallows $ and . characters: sdf lint -w references-special-chars=$.
Configuration:
workspace.sdf.yml
sdf-args:
   # special_chars is a string of chars to block (e.g., "%<>"")
   lint: >
      -w references-special-chars=$.%<>
      ...
Anti-pattern Using special characters within identifiers when creating or aliasing objects.
SELECT 
    num AS "My Num", 
    num > 100 AS "num > 100", 
    num / 100.0 AS "num %" 
FROM my_table 
Best-practice
SELECT 
    num AS my_num, 
    num > 100 AS num_greater_than_100, 
    num / 100.0 AS num_percentage 
FROM my_table 

References Quoting

SDF118

Unnecessary quoted identifier
ConfigurationSDF ErrorSQLFluff AliasAuto-fix
references-quotingSDF118L059
Example: sdf lint -w references-quoting Configuration:
workspace.sdf.yml
sdf-args:
   lint: >
      -w references-quoting
      ...
Anti-pattern Using quotes when naming a valid identifier, that is not a reserved keyword.
SELECT 'a' AS "a" 
Best-practice Use unquoted identifiers where possible.
SELECT 'a' AS a 

References Qualification

SDF116

Columns reference should specify source table or view in queries with more than one source.
ConfigurationSDF ErrorSQLFluff AliasAuto-fix
references-qualificationSDF116L027
Example: sdf lint -w references-qualification Configuration:
workspace.sdf.yml
sdf-args:
   lint: >
      -w references-qualification
      ...
Anti-pattern Not specifying the source table or view when referencing columns in queries involving more than one source, thus creating ambiguity.
SELECT 
   col_a, 
   col_b 
FROM table_a LEFT OUTER JOIN table_b USING (col_a) 
Best-practice
SELECT 
   table_a.col_a, 
   table_b.col_b 
FROM table_a LEFT OUTER JOIN table_b USING (col_a) 

Ambiguous Column References

SDF105

Inconsistent column references in GROUP BY/ORDER BY clauses of both ordinal and non-ordinal
ConfigurationSDF ErrorSQLFluff AliasAuto-fix
ambiguous-column-referencesSDF105L054
Example: sdf lint -w ambiguous-column-references Configuration:
workspace.sdf.yml
sdf-args:
   lint: >
      -w ambiguous-column-references
      ...
Anti-pattern Using both explicit and implicit column references in the GROUP BY or ORDER BY clause. Reference should be consistent.
SELECT 
   a, 
   b, 
   SUM(b) AS sum_b 
FROM my_table 
GROUP BY 
   a, 2 
ORDER BY 
   1, b 
Best-practice Use unquoted identifiers where possible.
-- explicit 
SELECT 
   a, 
   b, 
   SUM(c) AS sum_c 
FROM my_table 
GROUP BY 
   a, b 
ORDER BY 
   a, b 
 
-- implicit 
SELECT 
   a, 
   b, 
   SUM(c) AS sum_c 
FROM my_table 
GROUP BY 
   1, 2 
ORDER BY 
   1, 2 

Structure Else Null

SDF119

Redundant ELSE NULL in a case when statement
ConfigurationSDF ErrorSQLFluff AliasAuto-fix
structure-else-nullSDF119L035
Example: sdf lint -w structure-else-null Configuration:
workspace.sdf.yml
sdf-args:
   lint: >
      -w structure-else-null
      ...
Anti-pattern Stating ELSE NULL within a CASE WHEN statement.
SELECT 
   CASE 
       WHEN num = 1 THEN '1' 
       WHEN num = 2 THEN '2' 
       ELSE NULL -- this is always implicit 
   END AS a 
FROM my_table 
Best-practice
SELECT 
   CASE 
       WHEN num = 1 THEN '1' 
       WHEN num = 2 THEN '2' 
   END AS a 
FROM my_table 

Structure Simple Case

SDF120

CASE statement can be simplified
ConfigurationSDF ErrorSQLFluff AliasAuto-fix
structure-simple-caseSDF120L043
Example: sdf lint -w structure-simple-case Configuration:
workspace.sdf.yml
sdf-args:
   lint: >
      -w structure-simple-case
      ...
Anti-pattern The following CASE statement are unnecessary and can be simplified:
-- boolean outcome 
SELECT 
   CASE 
       WHEN num > 1 THEN TRUE 
       ELSE FALSE 
   END AS is_num_greater_than_one 
FROM my_table 
 
-- handle NULLs 
SELECT 
   CASE 
       WHEN num IS NULL THEN 0 
       ELSE num 
   END AS num_not_null 
FROM my_table 
Best-practice Use simpler SQL syntax:
-- boolean outcome 
SELECT 
   COALESCE(num > 1, FALSE) AS is_num_greater_than_one 
FROM my_table 
 
-- handle NULLs 
SELECT 
   COALESCE(num, 0) AS num_not_null 
FROM my_table 

Structure Unused Cte

SDF121

Query defines a CTE (common-table expression) but does not use it
ConfigurationSDF ErrorSQLFluff AliasAuto-fix
structure-unused-cteSDF121L045
Example: sdf lint -w structure-unused-cte Configuration:
workspace.sdf.yml
sdf-args:
   lint: >
      -w structure-unused-cte
      ...
Anti-pattern Defining CTEs that are not being used in the query (e.g., sub_2 in the example below).
WITH 
sub1 AS ( 
    SELECT 'a' AS a 
), 
 
sub2 AS ( 
    SELECT 'b' AS b 
) 
 
SELECT a 
FROM sub1 
Best-practice
WITH 
sub1 AS ( 
    SELECT 'a' AS a 
), 
 
SELECT a 
FROM sub1 

Structure Nested Case

SDF122

Nested CASE statement in ELSE clause could be flattened.
ConfigurationSDF ErrorSQLFluff AliasAuto-fix
structure-nested-caseSDF122L058
Example: sdf lint -w structure-nested-case Configuration:
workspace.sdf.yml
sdf-args:
   lint: >
      -w structure-nested-case
      ...
Anti-pattern Unnecessarily nesting CASE statements.
SELECT 
   CASE 
       WHEN num = 1 THEN '1' 
       ELSE 
       CASE 
           WHEN num = 2 THEN '2' 
       END 
   END AS my_num_to_varchar 
FROM my_table 
Best-practice
SELECT 
   CASE 
       WHEN num = 1 THEN '1' 
       WHEN num = 2 THEN '2' 
   END AS my_num_to_varchar 
FROM my_table 

Structure Distinct

SDF123

DISTINCT used with parentheses
ConfigurationSDF ErrorSQLFluff AliasAuto-fix
structure-distinctSDF123L015
Example: sdf lint -w structure-distinct Configuration:
workspace.sdf.yml
sdf-args:
   lint: >
      -w structure-distinct
      ...
Anti-pattern Using DISTINCT with parentheses. In the example below, all columns are affected by the DISTINCT but can mistaken to think only column a is.
SELECT DISTINCT(a), b 
FROM my_table 
Best-practice
SELECT DISTINCT a, b 
FROM my_table 

Structure Subquery

SDF113

Join/From clauses should not contain subqueries. Use CTEs instead
ConfigurationSDF ErrorSQLFluff AliasAuto-fix
structure-subquerySDF113L042
Example: sdf lint -w structure-subquery=join Configuration:
workspace.sdf.yml
# subquery_scope is one of ['join', 'from', 'both'] 
sdf-args:
   lint: >
      -w structure-subquery
      ...
Anti-pattern Selecting from a subquery instead of defining the subquery in a CTE.
SELECT 
   sub.a 
FROM (SELECT 'a' AS a) AS sub 
Best-practice
WITH 
sub AS ( 
   SELECT 'a' AS a 
) 
 
SELECT 
   sub.a 
FROM sub 

Structure Join Condition Order

SDF114

Join conditions column references should follow tables reference order
ConfigurationSDF ErrorSQLFluff AliasAuto-fix
structure_join_condition_orderSDF114ST09
Example: sdf lint -w structure_join_condition_order Configuration:
workspace.sdf.yml
sdf-args:
   lint: >
      -w structure_join_condition_order
      ...
Anti-pattern Referencing columns in join ON clause statement in a different order than the tables are referenced in the JOIN clause
SELECT 
   first_table.a, 
   second_table.a 
FROM first_table 
   LEFT OUTER JOIN second_table ON ( 
   second_table.a = first_table.a 
) 
Best-practice
SELECT 
   first_table.a, 
   second_table.a 
FROM first_table 
   LEFT OUTER JOIN second_table ON ( 
   first_table.a = second_table.a 
) 

Structure Column Order

SDF115

Select wildcards then simple targets before calculations and aggregates.
ConfigurationSDF ErrorSQLFluff AliasAuto-fix
structure-column-orderSDF115L034
Example: sdf lint -w structure-column-order Configuration:
workspace.sdf.yml
sdf-args:
   lint: >
      -w structure-column-order
      ...
Anti-pattern Wildcard listed after single targets
SELECT 
   a, 
   *, 
   b 
FROM my_table 
Best-practice
   *, 
   a, 
   b 
FROM my_table 

Convention Terminator

SDF111

Statements should not end with a semi-colon. Multi-statements must be separated with a semi-colon but the final statement should NOT end with one.
ConfigurationSDF ErrorSQLFluff AliasAuto-fix
convention-terminatorSDF111L052
Example: sdf lint -w convention-terminator Configuration:
workspace.sdf.yml
sdf-args:
   lint: >
      -w convention-terminator
      ...
Anti-pattern Ending the last statement with a semi-colon
-- single statement 
SELECT a FROM my_table; 
 
-- multi-statement 
SELECT a FROM table_a; 
SELECT b FROM table_b; 
Best-practice
-- single statement 
SELECT a FROM my_table 
 
-- multi-statement 
SELECT a FROM table_a; 
SELECT b FROM table_b 

Convention Comma

SDF104

Avoid trailing commas in lists.
ConfigurationSDF ErrorSQLFluff AliasAuto-fix
convention-commaSDF104N/A
Configuration:
workspace.sdf.yml
sdf-args:
   lint: >
      -w convention-comma
      ...
Anti-pattern
SELECT
    ['Very', 'Long', 'List',] AS mylist
Best-practice
SELECT
    ['Very', 'Long', 'List'] AS mylist