libsyntaqlite Rust API

libsyntaqlite is an embeddable parser, formatter, and static analyzer for SQLite SQL. Its Rust API is published as the syntaqlite crate.

Feature flags

FeatureWhat it enables
fmtFormatter
analysisAnalysis (unknown tables, columns, functions, lineage)
sqliteBuilt-in SQLite dialect (enabled by default)
lspLanguage server protocol implementation
rpcJSON-RPC dispatch (parse/format/tokenize/analyze over JSON)
serdeserde::Serialize/Deserialize for AST nodes and diagnostics
dynloadLoad custom dialects from shared libraries at runtime

Formatter

Type / MethodDescription
Formatter::new()Create with SQLite dialect and default settings
Formatter::with_config(&FormatConfig)Create with custom config
fmt.format(sql) -> Result<String>Format SQL string
FormatConfigBuilder: with_line_width(), with_indent_width(), with_keyword_case(), with_semicolons()
KeywordCaseUpper or Lower

The formatter is reusable; call format() repeatedly. Internal allocations are reused across calls. Defaults: 80-char lines, 2-space indent, uppercase keywords, semicolons on.

RPC

syntaqlite::rpc (feature rpc) accepts one JSON request and returns one JSON envelope. Backs the CLI's serve json loop and the C API.

Type / MethodDescription
RpcSession::new(&dialect)Reusable session bundling parser, tokenizer, analyzer, and formatter cache
rpc::call_json(&mut session, json) -> StringRun one request, returning the {"ok":...} envelope string
rpc::handle_request(&mut session, &Value) -> Result<Value, String>Lower-level dispatch returning the raw result value

Parser

Type / MethodDescription
Parser::new()Create a parser for the SQLite grammar
parser.parse(sql) -> ParseSessionStart a parse session
session.next() -> ParseOutcomeYield next statement
ParseOutcome::Ok(stmt)Successfully parsed statement
ParseOutcome::Err(err)Parse error (parser recovers and continues)
ParseOutcome::DoneNo more statements

The parser yields statements one at a time, reusing internal allocations. It recovers from errors and continues parsing subsequent statements.

Tokenizer

Type / MethodDescription
Tokenizer::new()Create a tokenizer for the SQLite grammar
tokenizer.tokenize(sql) -> Result<Vec<Token>>Tokenize SQL string
Tokentoken_type, text, byte offsets into source

Zero-copy: tokens reference byte offsets into the source string.

Analyzer

Type / MethodDescription
Analyzer::new()Create an analyzer for the SQLite dialect
AnalysisContext::new(&mut catalog)Bundle the catalog, config, and optional module resolver for a single analysis call
analyzer.analyze(sql, &mut ctx) -> AnalysisAnalyze SQL, returning diagnostics and lineage
Catalog::new(dialect)Create an empty catalog
catalog.layer_mut(CatalogLayer::Database).insert_table(name, cols, false)Register a table
AnalysisConfig::default()Default config (warnings for unknowns)
AnalysisConfig::default().with_strict_schema()Strict mode (errors for unknowns)
model.diagnostics()Parse and semantic diagnostics

The analyzer is reusable; call analyze() repeatedly. The catalog uses a layered resolution order; populate the Database layer with your schema.

Lineage

After analyze(), the returned Analysis provides column-level lineage for SELECT statements. Lineage traces each result column back to its source table and column.

model.statements() yields one StatementAnalysis per statement; lineage methods are per-statement.

Type / MethodDescription
stmt.lineage()Per-column lineage: Option<LineageResult<&[ColumnLineage]>>
stmt.relations_accessed()Relations in FROM: Option<LineageResult<&[RelationAccess]>>
stmt.physical_tables_accessed()Physical tables after resolving CTEs/views: Option<LineageResult<&[PhysicalTableAccess]>>
stmt.defined_relations()&[DefinedRelation] containing targets created by DDL (CREATE TABLE/CREATE VIEW)
stmt.unexpanded_views()&[String] containing canonical names of views whose bodies were unavailable for expansion
LineageResult<T>Complete(T) when fully resolved; Partial(T) when some view bodies are unavailable
ColumnLineagename: String, index: u32, origin: Option<ColumnOrigin>
ColumnOrigintable: String, column: String
RelationAccessname: String, kind: RelationKind
RelationKindTable or View
PhysicalTableAccessname: String
DefinedRelationname: String, is_view: bool

Lineage methods return None for non-query statements (CREATE, INSERT, etc.). A column's origin is populated only when the column is an untransformed passthrough, such as a direct column reference or a pure rename alias. Expressions, casts, aggregates, and set-op (UNION, etc.) columns have origin: None. Result is Partial when a referenced view's body is unavailable for tracing through; unexpanded_views() lists the view names.