Linting BigQuery SQL with sqlfluff

Senior Data Engineer • Contractor / Freelancer • GCP & AWS Certified
Search for a command to run...

Senior Data Engineer • Contractor / Freelancer • GCP & AWS Certified
No comments yet. Be the first to comment.
Hands-on guides to data tooling, infrastructure, and operations — scheduling, pipelines, access control, and the engineering behind data workflows.
Spreadsheets are a central part of a modern workplace. Pretty much every office workplace uses one. It's also quite used for personal use cases. One such product is Google Sheets. I use it for many things - organizing finance, planning travel itinera...
Here's a useful Dataform concept: pre_operations and post_operations. As the name implies, these represent a set of actions that run before and after the main operation (table, view, or SQL operations

BigQuery has always been a SQL engine for tabular data. Object tables add an interesting twist to that. Instead of rows containing values, an object table gives you one row per file — pointing at da

Query your data lake with warehouse-grade security and performance — without moving a single file.

Ever run a heavy BigQuery SQL query, processed gigabytes of data — and then accidentally closed the tab or forgot to save the results? 😬 Don't re-run it. Your results are still there. BigQuery automa

You can use query parameters in BigQuery hashtag#SQL (now in the console as well!) — but how are they different from variables, and when should you use each? Both parameters and variables act as place

SQL folks, are you using any linters? Myself, I've used linters such as Pylint for Python, but in the last 3 years, despite working with BigQuery daily, I didn't use one.
First, what is a linter? If you haven't encountered the term before, a linter looks at the code to spot potential errors or bugs, formatting and stylistic issues. It helps enforce the general or custom code guidelines. Think of it as a code reviewer.
Today I'm exploring sqlfluff - a SQL linter. It's a configurable linter that supports, at the time of this writing, two dozen of the most popular SQL dialects, including BigQuery, which we're going to use for today's quick exercise.
We start by installing sqlfluff using pip.
pip install sqlfluff
We can now use the sqlfluff command to analyze our SQL code and even fix some of the problems :).
I've saved the following sample SQL code in a file
CREATE OR REPLACE TABLE learning.base_data (id INT64, dates ARRAY<DATE>)
AS
WITH cte as (
select id FROM UNNEST(GENERATE_ARRAY(1, 100,1)) as id
)
SELECT cte.id, GENERATE_DATE_ARRAY(DATE('2011-01-01'), CURRENT_DATE(), INTERVAL 1 DAY) as dates
FROM cte
We can now run the sqlfluff lint command, providing the name of the file and the dialect, in our case, BigQuery.
sqlfluff lint test_sql_query.sql --dialect bigquery
The linter analyzes our code and issues a list of findings. It compares the code to a set of standard, built-in guidelines, which can be overridden or ignored via configuration, based on needs.

We can also ask sqlfluff to attempt to fix these issues.
sqlfluff fix test_sql_query.sql --dialect bigquery

If we respond Yes, it will apply the proposed fix to the file we provided.
Here's how the file looks now.
CREATE OR REPLACE TABLE learning.base_data (id INT64, dates ARRAY<DATE>)
AS
WITH cte AS (
SELECT id FROM UNNEST(GENERATE_ARRAY(1, 100, 1)) AS id
)
SELECT
cte.id,
GENERATE_DATE_ARRAY(DATE('2011-01-01'), CURRENT_DATE(), INTERVAL 1 DAY)
AS dates
FROM cte
Another run of sqlfluff lint would yield no issues found.

As with other linters, sqlfluff is configurable. You can configure, enable and disable the rules via project-level configuration files. You can also provide in-file configuration directives to override upper-level rules. This would allow you to customize the behavior to your own or your team's and organization's conventions and standards.
I don't know many people who just write SQL in a text file and share it with someone. It's helpful to have your automated peer review to have a look at your code. There is also a plugin for Visual Studio Code that helps make your SQL compliant as you write it, so before it is saved.
A linter brings great value when deployed as part of your project's CI/CD pipeline as a quality control checkpoint. For instance, this could be a pre-commit hook to ensure code standards are upheld. This way, only code that adheres to the standard is merged into the bigger codebase.
A good part of people use a templating provided by something like dbt. Judging by documentation, sqlfluff does support Jinja and dbt templating, but I'm yet to give it a try :).
For me, the next step would be trying it out in an actual project, and hopefully use it in production soon.
Thanks for reading and keep enjoying SQL!
Found it useful? Subscribe to my Analytics newsletter at notjustsql.com.