from __future__ import annotations

from sqlglot import exp, parse_one
from sqlglot.errors import ParseError


def extract_table_names(sql: str) -> set[str]:
    try:
        expression = parse_one(sql, read="duckdb")
    except ParseError as exc:
        raise ValueError(f"Unable to parse SQL: {exc}") from exc

    cte_names = {
        cte.alias_or_name
        for cte in expression.find_all(exp.CTE)
        if cte.alias_or_name
    }
    tables = set()
    for table in expression.find_all(exp.Table):
        name = table.name
        if name and name not in cte_names:
            tables.add(name)
    return tables
