This crate extracts documentation from SQL files by parsing:
- SQL statements (via
sqlparser) - Line and block comments
- Table and column locations
Then comments are attached to the SQL structures they describe, producing a structured, queryable documentation model.
With a directory structured like this:
sql_dir/
└── users.sqland the content of users.sql being:
/* Table storing user accounts */CREATETABLEusers (
/* Primary key for each user */
id INTEGERPRIMARY KEY,
-- The user's login name
username VARCHAR(255) NOT NULL,
/* User's email address */
email VARCHAR(255) UNIQUE NOT NULL
);A rudimentary implementation can be generated with:
# #[cfg(not(feature = "std"))]
# fnmain(){}
# #[cfg(feature = "std")]fnmain() -> Result<(), sql_docs::error::DocError>{use sql_docs::{GenericDialect,SqlDoc};use std::{env, fs};let base = env::temp_dir().join("tmp_sql_docs_example");let _ = fs::remove_dir_all(&base);
fs::create_dir_all(&base)?;let example = base.join("example.sql");
fs::write(&example,r#"-- Table storing user accounts-- Contains all user values/* Rows generated at registration */CREATE TABLE users ( /* Primary key for each user */ id INTEGER PRIMARY KEY, -- The user's login name username VARCHAR(255) NOT NULL, /* User's email address */ email VARCHAR(255) UNIQUE NOT NULL);"#,)?;let docs = SqlDoc::from_path(&example).collect_all_leading().flatten_multiline_with(". ").build::<GenericDialect>()?;let users = docs.table("users",None)?;assert_eq!(users.name(),"users");assert_eq!(
users.doc(),Some("Table storing user accounts. Contains all user values. Rows generated at registration"));assert_eq!(users.path(),Some(example.as_path()));let _ = fs::remove_dir_all(&base);Ok(())}Or with no std and from a String:
# #[cfg(feature = "std")]
# fnmain(){}
# #[cfg(not(feature = "std"))]fnmain() -> Result<(), sql_docs::error::DocError>{use sql_docs::{GenericDialect,SqlDoc};let example = r#"-- Table storing user accounts-- Contains all user values/* Rows generated at registration */CREATE TABLE users ( /* Primary key for each user */ id INTEGER PRIMARY KEY, -- The user's login name username VARCHAR(255) NOT NULL, /* User's email address */ email VARCHAR(255) UNIQUE NOT NULL);"#;let docs = SqlDoc::builder_from_str(example).collect_all_leading().flatten_multiline_with(". ").build::<GenericDialect>()?;let users = docs.table("users",None)?;assert_eq!(users.name(),"users");assert_eq!(
users.doc(),Some("Table storing user accounts. Contains all user values. Rows generated at registration"));Ok(())}These are the primary entry points most users will interact with:
SqlDoc::from_pathBuild documentation from a single.sqlfile.SqlDoc::from_dirRecursively scan a directory for.sqlfiles and build documentation.SqlDocBuilder::buildFinalize the builder and produce a [SqlDoc].SqlDocBuilder::denyExclude specific files by full path.SqlDocBuilder::flatten_multilineFlatten multiline comments into a single line.SqlDocBuilder::collect_single_nearestCollect only the nearest leading comment.
This crate is designed for generating documentation from SQL schemas by attaching comments to:
- Tables
- Columns
using only comments that immediately precede the items they describe, with the ability to differentiate between multiple leading comments per statement or collect only the nearest comment preceding a statement.
This makes it well-suited for:
- Auto-generating Markdown or HTML documentation
- Building database schema explorers
- Enforcing documentation rules in CI
- Static analysis of SQL schemas
- Inline and interstitial comments are intentionally ignored.
- Comment attachment is line-based and deterministic.
- One SQL file may define multiple tables.
- No database connection is required.
sql_docitems are sorted bytablename andcolumnname, supporting binary searching