{"id":51671152,"url":"https://github.com/gentleeduck/duck-sqllsp","last_synced_at":"2026-07-15T00:42:34.508Z","repository":{"id":359994759,"uuid":"1248230225","full_name":"gentleeduck/duck-sqllsp","owner":"gentleeduck","description":"Multi-dialect SQL Language Server in Rust. 300+ lint rules, context-aware completion (50 phases), schema-aware hover, formatter, code lenses, inlay hints. PG-first; MySQL / SQLite / MSSQL supported. tower-lsp + libpg_query.","archived":false,"fork":false,"pushed_at":"2026-06-15T11:22:41.000Z","size":3222,"stargazers_count":0,"open_issues_count":2,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-06-15T13:14:20.248Z","etag":null,"topics":["completion","formatter","language-server","libpg-query","linter","lsp","mssql","mysql","neovim","postgresql","rust","sql","sqlite","tower-lsp","vscode"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gentleeduck.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":"ROADMAP_ADVANCED.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-24T11:14:09.000Z","updated_at":"2026-06-15T11:22:46.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/gentleeduck/duck-sqllsp","commit_stats":null,"previous_names":["gentleeduck/duck-sqllsp"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/gentleeduck/duck-sqllsp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gentleeduck%2Fduck-sqllsp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gentleeduck%2Fduck-sqllsp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gentleeduck%2Fduck-sqllsp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gentleeduck%2Fduck-sqllsp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gentleeduck","download_url":"https://codeload.github.com/gentleeduck/duck-sqllsp/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gentleeduck%2Fduck-sqllsp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35485403,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-14T02:00:06.603Z","response_time":114,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["completion","formatter","language-server","libpg-query","linter","lsp","mssql","mysql","neovim","postgresql","rust","sql","sqlite","tower-lsp","vscode"],"created_at":"2026-07-15T00:42:33.873Z","updated_at":"2026-07-15T00:42:34.499Z","avatar_url":"https://github.com/gentleeduck.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"./public/logo-dark.svg\" alt=\"duck-sqllsp\" width=\"120\"/\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003educk-sqllsp\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  Persistent multi-dialect SQL Language Server. PostgreSQL is the deepest target; MySQL / MariaDB, SQLite, and SQL Server are first-class for syntax, completion, hover, formatting, and connection-backed introspection. Built on tower-lsp + libpg_query.\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"./LICENSE\"\u003eMIT\u003c/a\u003e -\n  \u003ca href=\"./CHANGELOG.md\"\u003eChangelog\u003c/a\u003e -\n  \u003ca href=\"./CONTRIBUTING.md\"\u003eContributing\u003c/a\u003e -\n  \u003ca href=\"./dsl-cli\"\u003eCrate docs\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://crates.io/crates/duck-sqllsp\"\u003e\u003cimg src=\"https://img.shields.io/crates/v/duck-sqllsp.svg\" alt=\"crates.io\"/\u003e\u003c/a\u003e\n  \u003ca href=\"https://docs.rs/duck-sqllsp\"\u003e\u003cimg src=\"https://docs.rs/duck-sqllsp/badge.svg\" alt=\"docs.rs\"/\u003e\u003c/a\u003e\n  \u003ca href=\"./LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/crates/l/duck-sqllsp.svg\" alt=\"MIT\"/\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n---\n\n## What you get\n\n- **300+ lint rules** (PG-first, dialect-aware) covering schema correctness, transaction safety, query smells, migration footguns, vendor mismatches (MySQL `ENGINE=`, Oracle `DUAL`/`CONNECT BY`, SQL Server `BEGIN TRANSACTION`, ...).\n- **Context-aware completion** across ~50 phases: `CREATE INDEX ... USING` + opclass slot, `CREATE TRIGGER ... EXECUTE FUNCTION`, `CREATE POLICY ... FOR / TO`, `ALTER COLUMN TYPE`, `CALL \u003cproc\u003e`, PL/pgSQL local-variable scope, JOIN target resolution, etc.\n- **Rich hover cards** for tables (compact `CREATE TABLE` + indexes + triggers + policies + comment + `ALTER TABLE OWNER TO`), columns, functions, keywords, types, NULL three-valued logic notes.\n- **Offline mode** built in: walks the workspace for `*.sql` files (`migrations/`, `db/`, `sql/`, `schema/`) and derives a synthetic catalog so completion + hover + diagnostics work without a live DB. Live introspect (PG / MySQL / SQLite) overrides.\n- **Code lenses**: `Run` above every statement + `EXPLAIN` for DML; `+ LIMIT 100`, `EXPLAIN ANALYZE` for slow SELECTs. VS Code wires them through to the active connection's CLI in a terminal; other clients see no broken-command popups.\n- **Inlay hints**: column-name chip per INSERT VALUES tuple (DataGrip-style), `SELECT *` expansion, `JOIN ... ON ...` predicate suggestion, `-- ~N rows` at end of SELECT, literal-cast `::int` hint in WHERE.\n- **Formatter**: external `sql-formatter` v15+ reflow + DataGrip-style `CREATE TABLE` alignment + PL/pgSQL block indenter. Optional `singleLine` post-pass collapses DML statements onto one line while leaving DDL intact.\n- **Refactors / code actions**: `= NULL` -\u003e `IS NULL`, `EXISTS (...)` -\u003e `CROSS JOIN LATERAL`, `BEGIN TRANSACTION` -\u003e `BEGIN`, extract subquery to `WITH _tmp AS (...) CTE`, 30+ more.\n- **Editor integrations**: VS Code extension with connections + schema tree view, neovim setup that works with stock `vim.lsp` + `nvim-cmp`.\n\n## Install\n\n```sh\ncargo install duck-sqllsp\n```\n\nLibrary use:\n\n```sh\ncargo add dsl-analysis\n```\n\n## Quick start\n\n```lua\n-- neovim\nvim.lsp.config('duck_sqllsp', {\n  cmd = { 'duck-sqllsp', 'server' },\n  filetypes = { 'sql', 'mysql', 'plsql' },\n  root_markers = { '.duck-sqllsp.toml', '.duck-sqllsp.json', '.git' },\n})\nvim.lsp.enable('duck_sqllsp')\n```\n\n```sh\nduck-sqllsp --help\nduck-sqllsp version\nduck-sqllsp rules\nduck-sqllsp lint file.sql\nduck-sqllsp format file.sql --stdout\nduck-sqllsp introspect file.sql        # offline catalog from CREATE TABLE/FUNCTION/TYPE\nduck-sqllsp introspect --url postgres://user:pass@host/db\n```\n\nProject config example (`.duck-sqllsp.toml`):\n\n```toml\n[duck_sqllsp]\nactive_connection = \"local\"\ndialect           = \"postgres\"      # postgres / mysql / sqlite / mssql (aliases accepted)\nrequire_connection = false\n\n[duck_sqllsp.style]\nkeyword    = \"upper\"\nfunction   = \"lower\"\ntype       = \"upper\"\nidentifier = \"preserve\"\n\n[duck_sqllsp.style.createTable]\nalignColumns       = true\nopenParenOnNewLine = true\nconstraintsAtEnd   = true\n\n[duck_sqllsp.style.formatter]\nlanguage       = \"postgresql\"\nexpressionWidth = 9999\nsingleLine      = true              # collapse DML to one line; leaves DDL untouched\ndenseOperators  = true\n\n[[duck_sqllsp.connections]]\nname = \"local\"\nurl  = \"postgres://user:pass@localhost:5432/mydb\"\n```\n\n## Workspace\n\n| Crate | Role |\n| --- | --- |\n| [`dsl-parse`](dsl-parse) | SQL parser - libpg_query primary, sqlparser fallback for MySQL/SQLite/MSSQL |\n| [`dsl-catalog`](dsl-catalog) | Schema model - tables (incl. owner), columns, constraints (inline + table-level), indexes, triggers, policies, sequences, types, functions |\n| [`dsl-knowledge`](dsl-knowledge) | Static keyword / type / function reference with PG-doc links |\n| [`dsl-resolve`](dsl-resolve) | Name resolution, FROM / JOIN / LATERAL scope, CTE columns, alias chains |\n| [`dsl-format`](dsl-format) | Formatter - sql-formatter reflow + DataGrip alignment + PL/pgSQL indent + optional one-line DML pass |\n| [`dsl-analysis`](dsl-analysis) | Lint rule engine - 300+ diagnostics with narrow ranges |\n| [`dsl-completion`](dsl-completion) | Context-aware completion engine, ~50 phases, alias + scope aware |\n| [`dsl-hover`](dsl-hover) | Hover cards with cursor-side narrowing, schema-qualified resolution |\n| [`dsl-conn`](dsl-conn) | Live PG / MySQL / SQLite catalog introspection (sqlx) |\n| [`dsl-server`](dsl-server) | tower-lsp server - all 17 LSP request handlers + startup progress |\n| [`dsl-cli`](dsl-cli) | `duck-sqllsp` binary - subcommands + stdio LSP + signal handling |\n\n## Editor integrations\n\n- **VS Code**: install `wildduck.duck-sqllsp-vscode`. Sidebar tree views for connections + schema. Commands: Add Connection, Set Active, Test Connection, Refresh Schema, Restart Server, Show Logs. Run / EXPLAIN / EXPLAIN ANALYZE / + LIMIT 100 code lenses wire through to a `duck-sqllsp` terminal running `psql` / `mysql` / `sqlite3` against the active connection.\n- **neovim**: stock `vim.lsp` + `nvim-cmp`. duck-sqllsp emits `$/progress` so statusline plugins surface \"loading workspace...\" while the .sql scan + DB introspect settle.\n\n## Build\n\n```sh\ncargo build --release\ncargo test  --workspace --release\ncargo clippy --workspace --all-features --release -- -D warnings\n```\n\n2500+ tests (rules, idioms, completion phases, hover resolver, formatter, parsers).\n\n## Performance targets\n\n| Metric | Target |\n| --- | --- |\n| Completion p50 | \u003c 5 ms |\n| Diagnostics p50 | \u003c 20 ms |\n| Hover p50 | \u003c 3 ms |\n| Format p50 | \u003c 30 ms |\n| Memory idle | \u003c 30 MB |\n| Memory @ 4 MiB file | \u003c 150 MB |\n| Cold start | \u003c 50 ms |\n| Document update | incremental, no re-parse on cached handlers |\n\n## Design\n\n- **libpg_query** primary parser, **sqlparser** fallback so MySQL backticks, MSSQL bracketed idents, SQLite quirks all parse.\n- **tower-lsp** protocol layer. Every handler is a thin shim over a pure-function crate; the LSP transport is the only place tokio touches.\n- **Per-document parse cache** on `OnceLock` - first heavy handler after `didChange` pays the parse cost, the rest reuse it.\n- **Space-preserving strip** keeps 1:1 byte offsets when stripping strings / comments / dollar-quoted bodies, so diagnostic ranges map back to source byte-exact.\n- **Catalog snapshots** are `parking_lot::RwLock` reads cloned before any `.await` - no guard ever crosses an await point.\n- **`PR_SET_PDEATHSIG`** + SIGTERM / SIGINT / SIGHUP handling - the binary always dies with its editor.\n\n## Sibling repos\n\n[`@gentleduck/ui`](https://github.com/gentleeduck/duck-ui) -\n[`@gentleduck/iam`](https://github.com/gentleeduck/duck-iam) -\n[`@gentleduck/upload`](https://github.com/gentleeduck/duck-upload) -\n[`@gentleduck/md`](https://github.com/gentleeduck/duck-md)\n\n## Contributing\n\nPR checklist + style notes in [`CONTRIBUTING.md`](CONTRIBUTING.md).\nSecurity: [`SECURITY.md`](SECURITY.md). Behaviour: [`CODE_OF_CONDUCT.md`](CODE_OF_CONDUCT.md).\n\n## License\n\nMIT. See [`LICENSE`](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgentleeduck%2Fduck-sqllsp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgentleeduck%2Fduck-sqllsp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgentleeduck%2Fduck-sqllsp/lists"}