Skip to content

Repository files navigation

poste-sql.nvim

SQL execution, dataset browser, and schema introspection for Neovim. Part of the Poste family.

Requires: poste.nvim (shared infra + Rust binary)

Features

  • Execute SQL statements from .sql files (PostgreSQL, MySQL, SQLite)
  • Dataset panel — Paginated results, cell navigation (hjkl), vim-style search/filter, sorting
  • Inline editing — Edit cells, insert/delete rows, generate DML with transaction commit
  • DB Browser — Tree-view of schemas, tables, columns; generate SELECT/DESCRIBE queries
  • SQL completion — Keywords, tables, columns, functions (blink.cmp)
  • Schema introspection — PKs, FKs, indexes, DDL
  • Export/import — CSV, JSON, SQL INSERT statements
  • Multi-result tabs — Each statement gets its own tab
  • Execution log viewer — Query history with timing

Installation

-- lazy.nvim
{
"beyondlex/poste-sql.nvim",
dependencies= {
"beyondlex/poste.nvim",
"saghen/blink.cmp",
},
config=function()
require("poste-sql.init").setup()
end,
}

Usage

Open a .sql file and press <CR> on a statement to execute.

Connection management

Connections are defined in connections.toml (walked up from the SQL file):

[pg-dev]
dialect = "postgres"host = "localhost"port = 5432database = "myapp"user = "{{PG_DEV_USER}}"password = "{{PG_DEV_PASSWORD}}"

Sensitive fields support {{VAR}} references resolved at runtime from a .env file next to connections.toml (same walk-up discovery), with real OS environment variables taking precedence. Unknown references stay literal, so plaintext configs keep working. Copy .env.example to .env and keep .env out of version control — never commit credentials. user and password are percent-encoded automatically when building connection URLs, so values containing @, :, /, % etc. work as-is.

Reference in .sql files:

-- @connection pg-devSELECT*FROM users WHERE active = true;

The USE database; statement switches the active database for parsing/completion context.

Statusline context

The current connection and database are shown in the statusline as [connection/database] when mini.statusline is installed. The context updates as you move the cursor (respects @connection, @database, and USE statements).

Per-connection colors — add a color or link field in connections.toml:

[production]
color = "#ff0000"
[staging]
link = "WarningMsg"
[development]
color = "SkyBlue"
FieldTypeExample
color = "#rrggbb"Hex colorcolor = "#ff0000"
color = "CSS"CSS named colorcolor = "Red", color = "SkyBlue"
color = "HL"Highlight group (auto-detected)color = "Function"
link = "HL"Explicit highlight group linklink = "ErrorMsg"

Auto-detection: color values that are valid Neovim highlight groups are linked (:link), others are treated as CSS color names.

Dataset buffer

KeyAction
h/j/k/lMove cell
H/LPrevious/next page
0/$First/last column
gg/GFirst/last row
sSort by column
<leader>/Search
<leader>ceFilter by cell
KPreview cell
yy / ycYank cell / column
RRe-run query
<Tab>/<S-Tab>Next/previous tab

Dataset editing

KeyAction
i / aEnter edit mode
ddDelete row
o / OInsert row below/above
uUndo edit
<leader>wCommit changes (generate DML)

Export

KeyAction
<leader>ecExport as CSV
<leader>ejExport as JSON
<leader>esExport as SQL INSERT

DB Browser

Press <leader>db in a SQL file to open the database tree browser.

KeyAction
<CR>Toggle node expand/collapse
xContext menu
sGenerate SELECT *
dGenerate DESCRIBE
/Search filter
qClose

Context menu (x) shows node-specific actions. On schema/database nodes, T inserts a CREATE TABLE template with tab-stop placeholders:

create table table_name (
column_name INTEGER NOT NULL
);

Press <Tab> to jump between placeholders, <S-Tab> to go back.

SQL completion

  • KeywordsSELECT, FROM, WHERE, JOIN, etc.
  • Tables, columns, schemas — Introspected from your database
  • Functions — Aggregate and scalar functions per dialect
  • Connection-aware — Completions reflect the actual schema

Requires blink.cmp. Auto-registers as poste_sql source.

SQL Snippets

Built-in snippets appear as completion items when the prefix matches a trigger word:

TriggerTemplate
ctcreate table
sf / slselect * from ... limit 100
cntselect count(*)
insinsert into ... values
updupdate ... set ... where
deldelete from ... where
whwhere clause
colaalter table add column
colualter table modify column
ctewith ... as
idxcreate index
uniunion all

All snippets use LSP-style syntax (${1:placeholder}, $0 for exit, $$ for literal $). See :help vim.snippet or the LSP spec for details.

Custom snippets via setup():

require("poste-sql").setup({
snippets= {
-- Simple: trigger word → snippet bodymyq="SELECT * FROM ${1:table} WHERE ${2:condition};",
-- Full form: trigger, label, and snippetmyf= {
label="my custom query",
snippet="with ${1:cte} as (\n ${2:select_query}\n)\nselect * from ${1:cte};",
},
},
})

Integration Tests

# Start test databases (PG 16 on 15432, MySQL 8.0 on 13306)cd tests/sql && docker compose up -d
# Run queries
cargo run --manifest-path ../poste.nvim/Cargo.toml -- run tests/sql/queries/postgres.sql --line 4 --env dev
# Run Lua tests
tests/run.sh

License

MIT

About

No description, website, or topics provided.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages