sqlparser-rs

repository·main·Indexed 25 days ago

https://github.com/apache/datafusion-sqlparser-rs

An extensible SQL Lexer and Parser written in Rust with support for ANSI SQL:2011. The library provides tools for AST traversal via Visit and VisitMut derive macros, support for custom SQL dialects through the derive_dialect! macro, and utilities for benchmarking and fuzzing.

Tokens
18.4K
Snippets
47
Records
107
Agent score
86%

What's inside sqlparser

  1. Run benchmarks for sqlparser_bench

    main
    To execute benchmarks for the SQL parser, run the cargo bench command within the sqlparser_bench crate. The benchmarking results are reported using the criterion library. Note that the benchmarking suite is located in a separate crate (sqlparser_bench) to prevent increasing the build time of the core sqlparser crate.
  2. Migrate usages of `Expr::Value` (v0.55.0)

    main

    In version 0.55.0, the Expr::Value enum variant was changed to contain a ValueWithSpan instead of a direct Value.

    Pattern Matching

    When pattern matching on Expr::Value, you must now destructure the ValueWithSpan struct to access the underlying value and the span.

    Creating Expressions

    To create a new expression with a value, use the Expr::value() method (lowercase 'v') instead of the Expr::Value variant. This method creates a ValueWithSpan containing an empty span.

    - Expr::Value(Value::SingleQuotedString(my_string)) => { ... }
    + Expr::Value(ValueWithSpan{ value: Value::SingleQuotedString(my_string), span: _ }) => { ... }
    
    - Expr::Value(Value::SingleQuotedString(my_string))
    + Expr::value(Value::SingleQuotedString(my_string))
  3. Extend the SQL parser for custom dialects

    main
    To implement support for a custom SQL dialect, the recommended approach is to write a new parser that delegates to the existing ANSI parser. This allows you to reuse the core functionality of the library while only implementing the specific extensions or syntax variations required by your dialect.
  4. Migrate usages of `ObjectName` (v0.55.0)

    main

    In version 0.55.0, the ObjectName structure was updated to use ObjectNamePart instead of Ident for its segments.

    Constructing ObjectName

    Instead of passing a vector of Ident directly to the ObjectName tuple struct, use the From implementation.

    Accessing Spans

    To access the span of an ObjectName, use the .span() method instead of accessing a .span field.

    - pub struct ObjectName(pub Vec<Ident>);
    + pub struct ObjectName(pub Vec<ObjectNamePart>)
    
    - name: ObjectName(vec![Ident::new("f")]),
    + name: ObjectName::from(vec![Ident::new("f")]),
    
    - name.span
    + name.span()
  5. Migrate to AST nodes with Source Spans

    main

    Since version 0.53.0, AST nodes include source span information for better error reporting. If you are manually constructing AST nodes or pattern matching on them, you must account for the new span field.

    Constructing Nodes

    When creating nodes like Ident, you must now provide a span. Use Span::empty() if no specific location is available.

    Old way:

    Ident {
        value: "name".into(),
        quote_style: None,
    }

    New way:

    Ident {
        value: "name".into(),
        quote_style: None,
        span: Span::empty(),
    }

    Pattern Matching

    You must update all existing pattern matches to include the span field to avoid compilation errors.

  6. Debug a fuzzer panic and get a stack trace

    main

    If the fuzzer discovers a panic, you can retrieve a stack trace using cargo hfuzz run-debug. You must provide the target name and the path to the generated fuzz files (typically found in hfuzz_workspace/<target>/*.fuzz).

    # Example for the fuzz_parse_sql target
    cargo hfuzz run fuzz_parse_sql
    cargo hfuzz run-debug fuzz_parse_sql hfuzz_workspace/fuzz_parse_sql/*.fuzz
  7. Customize visitor methods with #[visit(with = "...")] on types

    main

    You can instruct the macro to call a specific visitor method for a type by using the #[visit(with = "method_name")] attribute on the type definition. This is useful when you want the visitor to trigger specific pre_visit_ and post_visit_ hooks for that type during traversal.

    #[derive(Visit, VisitMut)]
    #[visit(with = "visit_expr")]
    enum Expr {
        IsNull(Box<Expr>),
        ..
    }
  8. Use the Visit and VisitMut derive macros

    main

    The sqlparser_derive crate provides procedural macros to automatically implement the Visit and VisitMut traits from the sqlparser crate for your structs and enums. This allows you to traverse and mutate AST structures easily.

    Basic usage involves adding #[derive(Visit, VisitMut)] to your types.

    #[derive(Visit, VisitMut)]
    struct Foo {
        boolean: bool,
        bar: Bar,
    }
    
    #[derive(Visit, VisitMut)]
    enum Bar {
        A(),
        B(String, bool),
        C { named: i32 },
    }