SQLFluff trên Linux: Tự Động Hóa SQL Linting và Chuẩn Hóa Code trong CI/CD Pipeline

Database tutorial - IT technology blog
Database tutorial - IT technology blog

Chất lượng code SQL là thứ không ai để ý đến — cho đến khi họ tiếp nhận một codebase mà mỗi developer viết keyword theo kiểu riêng, thụt đầu dòng tùy tiện, và quote style không nhất quán trên 300 file. SQLFluff giải quyết vấn đề này — nó mang lại sự kỷ luật tương tự như ESLint cho JavaScript và Black cho Python, nhưng dành cho SQL.

Sau khi làm việc với MySQL, PostgreSQL và MongoDB trên nhiều dự án khác nhau, mỗi hệ thống có điểm mạnh riêng và quirk SQL riêng. SQLFluff xử lý điều này thông qua dialect-aware linting — đây là điều khiến nó thực sự hữu ích cho các team thực tế thay vì chỉ là một công cụ formatter đơn giản.

Bắt Đầu Nhanh: Chạy SQLFluff trong 5 Phút

Cài đặt bằng pip — không cần dependencies hệ thống, không cần cấu hình gì để bắt đầu:

pip install sqlfluff
sqlfluff --version

Tạo một file test với SQL được viết cẩu thả có chủ đích:

select id,name,email FROM users where status='active' and created_at > '2024-01-01'

Chạy linter trên file đó:

sqlfluff lint query.sql --dialect postgres

Bạn sẽ thấy output như sau:

== [query.sql] FAIL
L:   1 | P:   1 | CP01 | Keywords must be consistently upper case.
L:   1 | P:  10 | LT04 | Leading comma enforcement.
L:   1 | P:  17 | LT01 | Expected single space before keyword.

Sau đó tự động sửa lỗi:

sqlfluff fix query.sql --dialect postgres

SQLFluff ghi đè trực tiếp lên file. Kết quả là SQL sạch, được định dạng nhất quán — không cần chỉnh sửa thủ công. Đây là quy trình cốt lõi: lint để xem lỗi gì, fix để tự động sửa.

Tìm Hiểu Sâu: Cấu Hình và Hỗ Trợ Dialect

Gõ flags mỗi lần chạy SQLFluff rất mất thời gian. Tạo file cấu hình .sqlfluff ở thư mục gốc project và nó sẽ tự động nhận diện:

[sqlfluff]
dialect = postgres
templater = jinja
max_line_length = 120

[sqlfluff:rules:capitalisation.keywords]
capitalisation_policy = upper

[sqlfluff:rules:capitalisation.identifiers]
capitalisation_policy = lower

[sqlfluff:rules:capitalisation.functions]
capitalisation_policy = upper

[sqlfluff:rules:layout.long_lines]
ignore_comment_clauses = True

Bây giờ chỉ cần chạy sqlfluff lint . từ thư mục gốc project và nó sẽ tự động lint đệ quy tất cả các file .sql theo dialect đã cấu hình.

SQLFluff hỗ trợ nhiều dialect ngay từ đầu:

  • ansi — SQL chuẩn, dùng làm fallback tốt
  • postgres, mysql, sqlite — các database kinh điển
  • bigquery, snowflake, tsql — cloud/enterprise
  • spark, duckdb, hive — analytics engines

Các quy tắc được tổ chức theo nhóm tương ứng với các vấn đề khác nhau:

  • Layout (LT): thụt đầu dòng, khoảng cách, độ dài dòng, khoảng trắng thừa cuối dòng
  • Capitalisation (CP): viết hoa keyword và identifier
  • Aliasing (AL): yêu cầu alias cho bảng và cột
  • Structure (ST): cấu trúc subquery, điều kiện join
  • References (RF): tham chiếu cột, phát hiện mơ hồ

Để tắt một rule cụ thể ngay tại chỗ mà không vô hiệu hóa toàn project:

SELECT *  -- noqa: LT09
FROM really_long_table_name_here;

Để loại trừ rules trên toàn project:

[sqlfluff]
exclude_rules = LT09, RF01

Sử Dụng Nâng Cao: Tích Hợp CI/CD

Linting local giúp từng developer. CI/CD enforcement đảm bảo không có SQL không nhất quán nào được merge vào main. Dưới đây là cách thiết lập trên các platform phổ biến.

GitHub Actions

# .github/workflows/sql-lint.yml
name: SQL Lint

on:
  pull_request:
    paths:
      - '**.sql'

jobs:
  sqlfluff:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'

      - name: Install SQLFluff
        run: pip install sqlfluff==3.0.7

      - name: Run SQLFluff
        run: sqlfluff lint . --dialect postgres --format github-annotation

Flag --format github-annotation là điểm mấu chốt ở đây. Nó xuất lỗi dưới dạng inline PR annotation, giúp reviewer thấy lỗi lint trực tiếp trên diff thay vì phải đào bới qua CI logs.

GitLab CI

# .gitlab-ci.yml
sql-lint:
  image: python:3.11-slim
  stage: test
  script:
    - pip install sqlfluff==3.0.7
    - sqlfluff lint . --dialect postgres
  only:
    changes:
      - "**/*.sql"

Pre-commit Hooks

Pre-commit hooks phát hiện vấn đề trước khi code đến CI — phản hồi nhanh hơn và tiết kiệm thời gian pipeline:

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/sqlfluff/sqlfluff
    rev: 3.0.7
    hooks:
      - id: sqlfluff-lint
        args: [--dialect, postgres]
      - id: sqlfluff-fix
        args: [--dialect, postgres]
pip install pre-commit
pre-commit install
pre-commit run --all-files

Sau khi thiết lập, mỗi lần git commit sẽ tự động lint và fix SQL. Các thành viên trong team không cần nhớ chạy lệnh gì thủ công.

Hỗ Trợ dbt Project

Nếu project của bạn dùng dbt, SQLFluff xử lý Jinja templating một cách tự nhiên:

[sqlfluff]
templater = dbt
dialect = postgres

[sqlfluff:templater:dbt]
project_dir = ./dbt_project
profiles_dir = ~/.dbt
sqlfluff lint models/ --templater dbt

Mẹo Thực Tế

Bắt Đầu Lỏng Lẻo, Dần Dần Siết Chặt

Khi giới thiệu SQLFluff vào một legacy project, bạn có thể sẽ nhận hàng trăm lỗi ngay ngày đầu. Cố sửa tất cả trước khi merge sẽ làm nản lòng mọi người. Thay vào đó, hãy thêm -- noqa: all tạm thời vào đầu các file hiện có, rồi sửa dần từng file qua các PR tiếp theo. Cách này giúp việc triển khai trở nên khả thi thay vì cản trở cả team.

Chỉ Lint Các File Đã Thay Đổi trong CI

Với codebase lớn, lint tất cả mọi thứ trên mỗi PR rất chậm. Hãy giới hạn chỉ lint các file đã thay đổi:

git diff --name-only origin/main | grep '\.sql$' | xargs sqlfluff lint --dialect postgres

Ghim Phiên Bản

SQLFluff phát hành thường xuyên và hành vi của rules có thể thay đổi giữa các phiên bản minor. Hãy ghim phiên bản để tránh CI bị lỗi bất ngờ:

# requirements-dev.txt
sqlfluff==3.0.7

Giữ Lint và Fix Tách Biệt trong CI

Bước lint nên làm fail build. Bước fix chỉ là công cụ cho developer — bạn không muốn CI tự commit lại các file đã được format vào repo. Hãy làm rõ điều này trong Makefile của bạn:

.PHONY: lint-sql fix-sql

lint-sql:
	sqlfluff lint . --dialect postgres

fix-sql:
	sqlfluff fix . --dialect postgres

Tích Hợp VS Code

Extension SQLFluff cho VS Code (bởi dorzey) hiển thị lỗi lint ngay khi bạn gõ. Trỏ nó vào binary venv của project để dùng cùng phiên bản với CI:

// .vscode/settings.json
{
  "sqlfluff.dialect": "postgres",
  "sqlfluff.executablePath": "${workspaceFolder}/.venv/bin/sqlfluff"
}

Sự kết hợp giữa pre-commit hooks cho phát triển local và CI enforcement cho pull request tạo ra một mạng lưới an toàn hai lớp. Vấn đề được phát hiện trước khi commit. Bất cứ thứ gì lọt qua sẽ bị bắt trước khi merge. Sau vài tuần, cả team sẽ không còn phải nghĩ đến SQL style nữa — nó tự động nhất quán.

Một điều tôi ước mình đã thiết lập sớm hơn trong các project PostgreSQL: áp dụng cấu hình SQLFluff nghiêm ngặt ngay từ đầu. Việc chuẩn hóa ngược hàng trăm file SQL là công việc nhàm chán mà SQLFluff giúp bạn tránh được một cách dễ dàng khi áp dụng sớm.

Share: