Skip to content
kitagryPublic

About

BigQuery language server

Topics

Resources

Stars

48 stars

Watchers

2 watching

Forks

Repository files navigation

bqls

BigQuery language server

bqls-mini.mp4

Installation

Prerequisites

  • Go 1.25 or later

Install from releases

Download the latest binary from GitHub Releases and place it in your PATH.

Build from source

go install

Settings

Login to use BigQuery API

gcloud auth login
gcloud auth application-default login

Neovim

You can use bqls.nvim to integrate BigQuery with Neovim.

You can specify your BigQuery Project ID and location in the configuration. If not specified, the plugin will use gcloud config get project for the Project ID and US as the default location.

require("lspconfig").bqls.setup({
  settings = {
    project_id = "YOUR_PROJECT_ID",
    location = "YOUR_LOCATION",
  },
})

You can change project_id with workspace/didChangeConfiguration.

vim.lsp.buf_notify(0, "workspace/didChangeConfiguration", { settings = { project_id = "ANOTHER_PROJECT_ID", location = "ANOTHER_LOCATION" } })

Settings omitted from the notification keep their current values, so you can send only what changed. A lint setting, when sent, replaces the whole rule set; lint = vim.empty_dict() or lint = vim.NIL restores the defaults (a plain {} is encoded as a JSON array and rejected).

bqls also supports fetching virtual document previews (table/job info) asynchronously so the client isn't blocked while BigQuery is queried; see bqls/publishVirtualTextDocument in the API reference. This is opt-in via supports_async_virtual_text_document in initializationOptions, so bqls.nvim keeps working unmodified until it adopts the new flow.

VSCode

The official VSCode extension lives in editors/vscode in this repository.

You can also use the community extension bqls-vscode.

Lint

bqls reports lint warnings and information (diagnostic source bqls-lint, code = rule name) for queries that analyze without errors.

Rule Default Description
null-comparison on x = CAST(NULL AS T) / != always yields NULL; quick fix rewrites it to IS [NOT] NULL.
in-null on x IN (NULL) / x NOT IN (NULL) whose list holds only NULLs (including CAST(NULL AS T) and SAFE_CAST(NULL AS T)) always yields NULL. No quick fix, since IS [NOT] NULL is not equivalent.
unused-cte on A WITH entry that is never referenced (a recursive CTE's self reference does not count). Reported as information; quick fix removes the entry.
partition-filter on A time- or range-partitioned table that is read without any filter on its partition column (_PARTITIONTIME / _PARTITIONDATE for ingestion-time partitioning), so the query may scan every partition. A filter anywhere in the statement on the column or a value derived from it (through CTEs, subqueries, and UNION) counts. Statements bqls cannot trace (e.g. recursive CTEs, table functions), view definitions, DML targets, wildcard tables, unreferenced CTEs, and reads that consume no column (e.g. SELECT COUNT(*), unless the table requires a partition filter) are skipped.

Bare x = NULL / x != NULL is rejected by BigQuery itself ("Operands of = cannot be literal NULL"); bqls offers an IS [NOT] NULL quick fix on that error.

Rules can be toggled with the lint setting (also via workspace/didChangeConfiguration):

settings = {
  project_id = "YOUR_PROJECT_ID",
  lint = { rules = { ["null-comparison"] = false } },
}

Config file

To share lint settings between your editor and CI, put a .bqls.yaml in your repository. Both the language server and bqls lint look for it from the SQL file's directory up to the repository root (the directory containing .git); the nearest one wins.

lint:
  rules:
    unused-cte: false
    some-rule:          # a rule can also take an object
      enabled: true
      some_option: 10   # rule-specific options

Each rule is either true / false or an object with an optional enabled and the rule's options; the editor's lint setting takes the same form. Unknown rules and options are errors (bqls lint exits with 2; the language server logs the error and ignores the file). The language server rereads the file when it changes.

Precedence: --enable / --disable flags or the editor's lint setting > .bqls.yaml > rule defaults. Rule options are merged key by key, so a setting only needs the options it changes.

To silence a single occurrence, add a bqls:ignore comment. A comment on its own line applies to the next line; a trailing comment applies to its own line. Omitting rule names ignores every rule.

-- bqls:ignore null-comparison
SELECT * FROM t WHERE x = CAST(NULL AS INT64)
SELECT * FROM t WHERE y = CAST(NULL AS INT64) -- bqls:ignore

CLI

bqls lint runs the same analysis and lint rules as the language server, without an editor. Table schemas are fetched with Application Default Credentials; no query is run.

$ bqls lint [flags] <file|dir|->...
$ bqls lint --project my-project queries/
queries/report.sql:3:6: info: CTE `tmp` is defined but never used (unused-cte)
queries/report.sql:8:7: error: Unrecognized name: y

Directories are searched recursively for *.sql files (skipping directories whose name starts with ., such as .git), and - reads from stdin. Flags must come before files. Run bqls lint --help for the full list of rules. Each file uses the nearest .bqls.yaml (stdin uses the one found from the working directory).

Flag Description
--project BigQuery project ID. Defaults to gcloud config get project.
--location BigQuery location. Defaults to US.
--enable <rule> / --disable <rule> Turn a rule on or off. Repeatable; the last one wins. Takes precedence over the config file.
--config <path> Use this config file for every input instead of looking up .bqls.yaml.
--fix Apply the quick fixes (the first one of each finding) and write the files back, then report the findings that are left. With -, the fixed SQL is printed to stdout and the findings go to stderr. A fix that overlaps another fix in the same file is skipped (noted on stderr) and its finding is reported; running --fix again applies it.
--format text|json|github text (default) prints path:line:col: severity: message (rule). json prints an array of {file, line, column, endLine, endColumn, severity, rule, message}. github prints workflow commands that show up as annotations on pull requests.

Lines and columns are 1-based and the end position is exclusive. Columns are currently off on lines containing non-ASCII text (#375). Analysis errors are reported with severity error and no rule. With --format github, file paths are made relative to $GITHUB_WORKSPACE so annotations attach to the diff.

Exit codes: 0 nothing found, 1 any lint finding or analysis error (with --fix, any that is left after fixing), 2 usage or runtime error (bad flags, invalid config file, unreadable or unwritable file, authentication/permission/network failure while fetching table metadata). An unreadable file does not stop the others from being linted; their findings are still printed and the exit code is 2.

GitHub Actions example. The service account only needs to read table metadata (e.g. roles/bigquery.metadataViewer). Pass --project explicitly, since the fallback to gcloud config get project only works where gcloud is installed and configured. Instead of go install, you can download a binary from GitHub Releases (the lint subcommand needs a release that includes it).

jobs:
  lint:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      id-token: write
    steps:
      - uses: actions/checkout@v7
      - uses: actions/setup-go@v7
        with:
          go-version: stable
      - uses: google-github-actions/auth@v3
        with:
          workload_identity_provider: ${{ secrets.WORKLOAD_IDENTITY_PROVIDER }}
          service_account: ${{ secrets.SERVICE_ACCOUNT }}
      - run: go install github.com/kitagry/bqls@latest
      - run: bqls lint --project my-project --format github .

Save Result

In order to save for spreadsheet, you should enable Google Drive API.

  1. Enable Google Drive API and Google Sheets API
  2. gcloud auth application-default login --scopes=https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/drive

Supported Protocol

About

BigQuery language server

Topics

Resources

Stars

48 stars

Watchers

2 watching

Forks

Releases

Sponsor this project

Packages

Used by

Contributors

Languages