odatav4-parser 0.0.1

OData V4 query string parser with AST and multi-dialect SQL rendering
Documentation
  • Coverage
  • 37.74%
    20 out of 53 items documented1 out of 23 items with examples
  • Size
  • Source code size: 33.2 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 4.66 MB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 19s Average build duration of successful builds.
  • all releases: 21s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • Repository
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • knackstedt

OData V4 Query String Parser for Rust

A Rust library that parses OData V4 query strings into an AST (Abstract Syntax Tree) and renders them into multiple SQL dialects.

Features

  • 🚀 Parse OData V4 query strings ($select, $top, $skip)
  • 🎯 Type-safe AST representation
  • 🔄 Render to multiple SQL dialects:
    • MSSQL/SQL Server - Uses TOP and OFFSET...ROWS syntax
    • SQLite - Uses LIMIT and OFFSET syntax
    • PostgreSQL - Uses LIMIT and OFFSET syntax
    • SurrealQL - Uses START and LIMIT syntax
  • ⚡ Zero-cost abstractions with compile-time safety
  • 📝 Informative error messages with position tracking

Installation

Add this to your Cargo.toml:

[dependencies]
odatav4-parser = "0.1.0"

Usage

Basic Example

use odatav4_parser::{parse, renderers::*};

fn main() {
    let query = "$select=id,name&$top=10&$skip=20";
    let options = parse(query).unwrap();

    // Render to different SQL dialects
    let mssql = mssql::MssqlRenderer::new();
    println!("MSSQL: {}", mssql.render("users", &options));
    // Output: SELECT TOP 10 [id], [name] FROM [users] ORDER BY (SELECT NULL) OFFSET 20 ROWS

    let sqlite = sqlite::SqliteRenderer::new();
    println!("SQLite: {}", sqlite.render("users", &options));
    // Output: SELECT "id", "name" FROM "users" LIMIT 10 OFFSET 20

    let surrealql = surrealql::SurrealqlRenderer::new();
    println!("SurrealQL: {}", surrealql.render("users", &options));
    // Output: SELECT id, name FROM users START 20 LIMIT 10

    let postgresql = postgresql::PostgresqlRenderer::new();
    println!("PostgreSQL: {}", postgresql.render("users", &options));
    // Output: SELECT "id", "name" FROM "users" LIMIT 10 OFFSET 20
}

Parsing Individual Options

use odatav4_parser::parse;

// Parse $select
let options = parse("$select=id,name,email").unwrap();
assert_eq!(options.select, Some(vec!["id".to_string(), "name".to_string(), "email".to_string()]));

// Parse $top
let options = parse("$top=10").unwrap();
assert_eq!(options.top, Some(10));

// Parse $skip
let options = parse("$skip=20").unwrap();
assert_eq!(options.skip, Some(20));

Error Handling

use odatav4_parser::{parse, ODataError};

match parse("$filter=name eq 'test'") {
    Ok(options) => println!("Parsed successfully"),
    Err(ODataError::UnsupportedOption(opt)) => {
        println!("Unsupported option: {}", opt);
    }
    Err(e) => println!("Parse error: {}", e),
}

Supported OData V4 Features

Currently implemented:

  • $select - Field selection
  • $top - Limit number of results
  • $skip - Skip N results (pagination)

Coming soon:

  • 🔜 $filter - Filter expressions
  • 🔜 $orderby - Sorting
  • 🔜 $expand - Navigation properties
  • 🔜 $count - Include total count
  • 🔜 $search - Full-text search

Architecture

The library follows a classic compiler architecture:

Query String → Lexer → Tokens → Parser → AST → Renderer → SQL
  1. Lexer (lexer.rs) - Tokenizes the input string
  2. Parser (parser.rs) - Builds an AST from tokens
  3. AST (ast.rs) - Type-safe representation of query options
  4. Renderers (renderers/*.rs) - Generate SQL for specific dialects

SQL Dialect Differences

Feature MSSQL SQLite PostgreSQL SurrealQL
Limit TOP N (before SELECT) LIMIT N LIMIT N LIMIT N
Offset OFFSET N ROWS OFFSET N OFFSET N START N
Identifier Quote [name] "name" "name" name

Development

Running Tests

cargo test

Running Tests with Output

cargo test -- --nocapture

Linting

cargo clippy -- -D warnings

Formatting

cargo fmt

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

MIT

References