sqloxide

repository·main·Indexed 42 days ago

https://github.com/wseaton/sqloxide

A high-performance Python wrapper around the Rust sqlparser-rs library for SQL parsing and AST manipulation. Version 0.61.1 provides functions like parse_sql() to convert SQL strings into typed ASTs, restore_ast() to reconstruct SQL from modified ASTs, and utilities to extract or mutate expressions and relations. It supports Python 3.9 through 3.14, including free-threaded Python (3.13t, 3.14t) for parallel processing without the GIL.

Tokens
2.4K
Snippets
13
Records
14
Agent score
52%

What's inside sqloxide

  1. Use sqloxide with free-threaded Python

    main

    As of v0.61.0, sqloxide supports free-threaded Python (3.13t, 3.14t). You can parse SQL from multiple threads in parallel without the Global Interpreter Lock (GIL) and without needing manual locks, making it highly efficient for parallel processing.

    import concurrent.futures
    from sqloxide import parse_sql
    
    queries = [f"SELECT col_{i} FROM table_{i}" for i in range(100)]
    
    # Works efficiently in parallel on free-threaded Python builds
    with concurrent.futures.ThreadPoolExecutor(max_workers=8) as pool:
        results = list(pool.map(lambda q: parse_sql(sql=q, dialect="generic"), queries))
  2. Parse SQL queries with parse_sql()

    main

    Use parse_sql to convert a SQL string into a typed Abstract Syntax Tree (AST). The returned object follows the sqlparser-rs AST schema and behaves like a Python dictionary/JSON document. You must specify a dialect (e.g., 'ansi', 'generic').

    from sqloxide import parse_sql
    
    sql = """
    SELECT employee.first_name, employee.last_name
    FROM employee
    ORDER BY employee.first_name ASC;
    """
    
    output = parse_sql(sql=sql, dialect='ansi')
    print(output)
  3. Convert an AST back to SQL with restore_ast()

    main

    If you have modified the AST in Python, you can reconstruct the original SQL query using restore_ast. This is useful for performing manual edits to the parsed structure and then generating the resulting SQL string.

    from sqloxide import restore_ast
    
    # Assuming 'output' is an AST from parse_sql()
    query = restore_ast(ast=output)
    print(query)
  4. Modify relations using mutate_relations()

    main

    Use mutate_relations to perform structured edits specifically on table names or relations within a query. This is more targeted than general expression mutation.

    from sqloxide import parse_sql, mutate_relations
    
    sql = "SELECT something from somewhere where something = 1"
    ast = parse_sql(sql=sql, dialect="ansi")
    
    def func(x):
        return x.replace("somewhere", "anywhere")
    
    result = mutate_relations(parsed_query=ast, func=func)
    print(result)
  5. Modify expressions using mutate_expressions()

    main

    Use the visitor pattern to perform structured edits on expressions within a query. Pass the parsed AST and a function func that accepts an AST node and returns a modified version of it.

    from sqloxide import parse_sql, mutate_expressions
    
    sql = "SELECT something from somewhere where something = 1 and something_else = 2"
    
    def func(x):
        if "CompoundIdentifier" in x.keys():
            for y in x["CompoundIdentifier"]:
                y["value"] = y["value"].upper()
        return x
    
    ast = parse_sql(sql=sql, dialect="ansi")
    result = mutate_expressions(parsed_query=ast, func=func)
    print(result)
  6. Reconstitute SQL from an AST with `restore_ast`

    main

    The restore_ast function takes a list of Python objects (representing a modified AST) and converts them back into a list of SQL query strings.

    Parameters:

    • ast (list): A list of Python objects representing the SQL AST.

    Returns: A list of strings, where each string is a reconstructed SQL query.

    Errors:

    • Raises ValueError if the Python objects cannot be deserialized back into SQL statements.
    import sqloxide
    
    # Assuming 'ast' was obtained from sqloxide.parse_sql()
    sql_queries = sqloxide.restore_ast(ast)
    for query in sql_queries:
        print(query)
  7. Mutate expressions using a Python callback

    main

    Use mutate_expressions(parsed_query, func) to transform expressions within a parsed SQL query. This is a powerful tool for rewriting SQL logic.

    • parsed_query: The parsed SQL statement object.
    • func: A Python callable that accepts an expression object and returns a new expression object.

    The function performs the following lifecycle for each expression:

    1. Converts the expression object to a Python-compatible format.
    2. Passes it to your func.
    3. Takes the return value of func and converts it back into a SQL expression object to replace the original.

    Returns a list of strings, where each string is the modified SQL statement.

    def replace_with_constant(expr):
        # Logic to return a new expression object
        return new_expr
    
    modified_queries = mutate_expressions(parsed_query, replace_with_constant)
  8. Extract relations from a parsed query

    main

    Use extract_relations(parsed_query) to retrieve all relations (e.g., table names) from a previously parsed SQL query object. The parsed_query must be a Python object representing a list of SQL statements.

    Returns a list of relation objects.

    relations = extract_relations(parsed_parsed_query)
    # relations is a list of relation objects found in the query
  9. Extract expressions from a parsed query

    main

    Use extract_expressions(parsed_query) to retrieve all expressions (e.g., column references, literals, arithmetic operations) from a parsed SQL query object.

    Returns a list of expression objects.

    expressions = extract_expressions(parsed_query)
    # expressions is a list of expression objects found in the query
  10. Mutate relations using a Python callback

    main

    Use mutate_relations(parsed_query, func) to modify table identifiers within a parsed query.

    • parsed_query: The parsed SQL statement object.
    • func: A Python callable that accepts a single string (the identifier value) and returns a new string.

    The function iterates through all relations and replaces the identifier values with the return value of func.

    Returns a list of strings, where each string is the modified SQL statement.

    def rename_table(name):
        return f"new_{name}"
    
    # This will rename all tables in the query
    modified_queries = mutate_relations(parsed_query, rename_table)
  11. Extract and mutate AST components in `sqloxide`

    main

    The sqloxide module provides several functions for inspecting and modifying the SQL AST after it has been parsed. These functions allow you to traverse the tree to find specific elements or apply transformations.

    Available Functions:

    • extract_relations(ast): Extracts relations (e.g., table names) from the AST.
    • mutate_relations(ast, ...): Mutates relations within the AST.
    • extract_expressions(ast): Extracts expressions from the AST.
    • mutate_expressions(ast, ...): Mutates expressions within the AST.