SQL LSP Server
A high-performance, multi-dialect SQL Language Server Protocol (LSP) implementation in Rust.
Features • Usage • API Reference • Development
✨ Features
- 🎯 Multi-Dialect Support - MySQL, PostgreSQL, Hive, ClickHouse, Elasticsearch (EQL/DSL), Redis
- 🔍 Intelligent Completion - Context-aware suggestions with AST-based analysis
- 📍 Code Navigation - Go-to-definition and find references
- ⚡ Real-Time Diagnostics - Tree-sitter powered syntax error detection
- 🎨 SQL Formatting - Professional code formatting with sqlformat
- 📊 Rich Hover Information - Detailed schema information in Markdown
- 🧵 Thread-Safe - Concurrent request handling with async/await
- 📦 Schema Management - Dynamic schema updates and auto-inference
🚀 Usage
Installation
# Build from source
# Or install via cargo
Starting the Server
The LSP server communicates via stdin/stdout using JSON-RPC 2.0 protocol:
# Start server
# With debug logging
RUST_LOG=debug
LSP Communication Protocol
All requests and responses follow the LSP specification.
1. Initialize
Request:
Response:
2. Document Sync
Open Document:
Note on URIs: The
urifield can be either:
- File URI:
file:///path/to/query.sql(saved file)- Virtual URI:
untitled:Untitled-1(in-memory, unsaved document)- Custom scheme:
inmemory://model/1or any custom identifierThe server identifies documents by their URI, so as long as the URI is unique and consistent across requests, it will work correctly.
Update Document:
3. Completion
Request:
Response:
Completion Item Kinds:
5= Field (column)7= Class (table)3= Function14= Keyword24= Operator
4. Hover
Request:
Response:
5. Go to Definition
Request:
Response:
6. Diagnostics
Notification (Server → Client):
Severity Levels:
1= Error2= Warning3= Information4= Hint
7. Document Formatting
Request:
Response:
Schema Configuration
Configure schemas via workspace/didChangeConfiguration:
Request:
Schema Structure:
interface Schema {
id: string; // UUID
database: string; // Database name
source_uri?: string; // Optional schema file URI
tables: Table[];
functions: Function[];
}
interface Table {
name: string;
comment?: string;
source_location?: [string, number]; // [URI, line number]
columns: Column[];
}
interface Column {
name: string;
data_type: string; // e.g., "INT", "VARCHAR(255)"
nullable: boolean;
comment?: string;
source_location?: [string, number];
}
interface Function {
name: string;
return_type: string;
parameters: Parameter[];
description?: string;
}
interface Parameter {
name: string;
data_type: string;
optional: boolean;
}
📖 API Reference
Supported LSP Methods
| Method | Description | Status |
|---|---|---|
initialize |
Initialize server capabilities | ✅ |
textDocument/didOpen |
Open document notification | ✅ |
textDocument/didChange |
Document change notification | ✅ |
textDocument/didClose |
Close document notification | ✅ |
textDocument/completion |
Code completion | ✅ |
textDocument/hover |
Hover information | ✅ |
textDocument/definition |
Go to definition | ✅ |
textDocument/references |
Find references | ✅ |
textDocument/formatting |
Document formatting | ✅ |
workspace/didChangeConfiguration |
Configuration updates | ✅ |
Completion Context Detection
The server uses AST-based context analysis to provide accurate completions:
| Context | Suggestions | Example |
|---|---|---|
FromClause |
Tables only | SELECT * FROM ‸ |
SelectClause |
Columns + keywords | SELECT ‸ FROM users |
WhereClause |
Columns + operators | SELECT * FROM users WHERE ‸ |
OrderByClause |
Columns + ASC/DESC | SELECT * FROM users ORDER BY ‸ |
GroupByClause |
Columns only | SELECT COUNT(*) FROM users GROUP BY ‸ |
HavingClause |
Columns + functions + operators | ... HAVING ‸ |
JoinClause |
Tables only | SELECT * FROM users JOIN ‸ |
TableColumn |
Specific table columns | SELECT u.‸ FROM users u |
Operator Filtering:
- Only keyword operators are suggested:
LIKE,IN,BETWEEN,IS NULL,IS NOT NULL - Symbol operators (
=,>,<, etc.) are excluded to reduce noise
🗄️ Supported SQL Dialects
| Dialect | Status | Features |
|---|---|---|
| MySQL | ✅ Full | MySQL 5.7+ syntax, context-aware completion |
| PostgreSQL | ✅ Full | PostgreSQL 12+ syntax, ILIKE support |
| Hive | ✅ Full | HiveQL syntax, PARTITION keyword |
| ClickHouse | ✅ Full | ClickHouse SQL, MergeTree support |
| Elasticsearch EQL | ✅ Full | Event Query Language |
| Elasticsearch DSL | ✅ Full | Query DSL (JSON) |
| Redis | ✅ Basic | Redis commands (FT.SEARCH, etc.) |
🛠 Development
Prerequisites
- Rust 1.70 or later
- Cargo
Build
# Development build
# Release build with optimizations
# Run tests
# Run linter
# Format code
Project Structure
lsp_sqls/
├── src/
│ ├── main.rs # Entry point
│ ├── server.rs # LSP server implementation
│ ├── dialect.rs # Dialect trait definition
│ ├── dialects/ # SQL dialect implementations
│ │ ├── mysql.rs # MySQL dialect
│ │ ├── postgres.rs # PostgreSQL dialect
│ │ └── ...
│ ├── parser/ # SQL parsers
│ │ └── sql.rs # Tree-sitter SQL parser
│ ├── schema.rs # Schema management
│ └── token.rs # Token definitions
├── tests/ # Integration tests
├── docs/ # Documentation
└── scripts/ # Helper scripts
└── pre-commit # Git pre-commit hook
Running Tests
# Run all tests
# Run specific test
# Run with coverage
🤝 Contributing
We welcome contributions! Please see CONTRIBUTING.md for details.
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Make your changes and add tests
- Run pre-commit checks:
make install-pre-commit - Commit:
git commit -m 'feat: add amazing feature' - Push:
git push origin feature/amazing-feature - Open a Pull Request
📝 License
This project is licensed under the MIT License - see the LICENSE file for details.
🙏 Acknowledgments
- Built with tower-lsp - LSP framework for Rust
- Powered by tree-sitter - Parser generator
- Formatted with sqlformat - SQL formatter
Made with ❤️ using Rust