Source code for bluebase.core.ast

from abc import (
    ABC,
    abstractmethod,
)
from dataclasses import dataclass

from .value import Value
from .domain import Domain
from .predicate import Comp


__all__ = (
    'Ast',
    'AstTable',
    'AstAttr',
    'AstCond',
    'AstAssign',
    'AstDefine',
    'AstSelect',
    'AstInsert',
    'AstDelete',
    'AstUpdate',
    'AstCreateTable',
    'AstDropTable',
    'AstCreateIndex',
    'AstDropIndex',
    'AstShowTables',
    'AstDescribeTable',
    'AstDumpTable',
    'AstExit',
)


[docs] @dataclass(frozen=True, slots=True) class Ast(ABC): """ An abstract base class for ASTs. .. rubric:: Common Grammar :: table: WORD | WORD "AS" WORD tables: table | tables COMMA table attr: WORD | WORD DOT WORD attrs: attr | attrs COMMA attr value: FLOAT | INT | BOOL | STRING values: value | values COMMA value hand: attr | value cond: attr COMP hand conds: cond | conds "AND" cond assign: attr COMP hand assigns: assign | assigns COMMA assign domain: BOOL | INT | FLOAT | STRING LP INT RP define: attr domain defines: define | defines COMMA define where_clause: | "WHERE" conds .. rubric:: Dispatch Grammar :: create_statement : "CREATE" "TABLE" create_table_body SC | "CREATE" "INDEX" create_index_body SC drop_statement : "DROP" "TABLE" drop_table_body SC | "DROP" "INDEX" drop_index_body SC .. rubric:: Partial Grammar :: create_table_body: table LP defines RP create_index_body: attr "OF" table drop_table_body: table drop_index_body: attr "OF" table .. rubric:: Statement Grammar :: select_statement: "SELECT" attrs "FROM" tables where_clause SC insert_statement: "INSERT" "INTO" table "VALUES" LP values RP SC delete_statement: "DELETE" "FROM" table where_clause SC update_statement: "UPDATE" table "SET" assigns where_clause SC show_tables_statement: "SHOW" "TABLES" SC describe_table_statement: "DESCRIBE" "TABLE" table SC dump_table_statement: "DUMP" "TABLE" table SC exit_statement: "EXIT" SC """ @abstractmethod def verbose(self) -> str: # pragma: no cover pass
[docs] @dataclass(frozen=True, slots=True) class AstTable(Ast): """ An AST representing a ``table``. Attributes: name: the name of the ``table`` alias: the alias of the ``table`` if ``"AS"`` is specified """ name: str alias: str | None def verbose(self) -> str: # pragma: no cover return self.name + (f" AS {self.alias}" if self.alias else "")
[docs] @dataclass(frozen=True, slots=True) class AstAttr(Ast): """ An AST representing a ``attr``. Attributes: ref: the reference of the ``attr`` if ``DOT`` is present name: the name of the ``attr`` """ ref: str | None name: str def verbose(self) -> str: # pragma: no cover return ("" if self.ref is None else f"{self.ref}.") + self.name
[docs] @dataclass(frozen=True, slots=True) class AstCond(Ast): """ An AST representing a ``cond``. Attributes: left_attr: the left ``attr`` of the ``cond`` comp: the ``COMP`` of the ``cond`` right_hand: the right ``hand`` of the ``cond`` """ left_attr: AstAttr comp: Comp right_hand: AstAttr | Value def verbose(self) -> str: # pragma: no cover tokens = [ self.left_attr.verbose(), self.comp.value, ] if isinstance(self.right_hand, AstAttr): tokens.append(self.right_hand.verbose()) else: tokens.append(str(self.right_hand)) return " ".join(tokens)
[docs] @dataclass(frozen=True, slots=True) class AstAssign(Ast): """ An AST representing a ``assign``. Attributes: left_attr: the left ``attr`` of the ``assign`` right_hand: the right ``hand`` of the ``assign`` """ left_attr: AstAttr right_hand: AstAttr | Value def verbose(self) -> str: # pragma: no cover tokens = [ self.left_attr.verbose(), "=", ] if isinstance(self.right_hand, AstAttr): tokens.append(self.right_hand.verbose()) else: tokens.append(str(self.right_hand)) return " ".join(tokens)
[docs] @dataclass(frozen=True, slots=True) class AstDefine(Ast): """ An AST representing a ``define``. Attributes: attr: the ``attr`` of the ``define`` domain: the ``domain`` of the ``define`` """ attr: AstAttr domain: Domain def verbose(self) -> str: # pragma: no cover return " ".join([ self.attr.verbose(), self.domain.verbose(), ])
[docs] @dataclass(frozen=True, slots=True) class AstSelect(Ast): """ An AST representing a ``select_statement``. Attributes: attrs: the ``attrs`` of the ``select_statement`` tables: the ``tables`` of the ``select_statement`` conds: the ``conds`` of the ``select_statement`` """ attrs: list[AstAttr] tables: list[AstTable] conds: list[AstCond] def verbose(self) -> str: # pragma: no cover tokens = [ "SELECT", ", ".join(attr.verbose() for attr in self.attrs), "FROM", ", ".join(table.verbose() for table in self.tables), ] if self.conds: tokens.append("WHERE") tokens.append(", ".join(cond.verbose() for cond in self.conds)) return " ".join(tokens)
[docs] @dataclass(frozen=True, slots=True) class AstInsert(Ast): """ An AST representing a ``insert_statement``. Attributes: table: the ``table`` of the ``insert_statement`` values: the ``values`` of the ``insert_statement`` """ table: AstTable values: tuple[Value, ...] def verbose(self) -> str: # pragma: no cover return " ".join([ "INSERT", "INTO", self.table.verbose(), "VALUES", f"({', '.join(str(value) for value in self.values)})", ])
[docs] @dataclass(frozen=True, slots=True) class AstDelete(Ast): """ An AST representing a ``delete_statement``. Attributes: table: the ``table`` of the ``delete_statement`` conds: the ``conds`` of the ``delete_statement`` """ table: AstTable conds: list[AstCond] def verbose(self) -> str: # pragma: no cover tokens = [ "DELETE", "FROM", self.table.verbose(), ] if self.conds: tokens.append("WHERE") tokens.append(", ".join(cond.verbose() for cond in self.conds)) return " ".join(tokens)
[docs] @dataclass(frozen=True, slots=True) class AstUpdate(Ast): """ An AST representing a ``update_statement``. Attributes: table: the ``table`` of the ``update_statement`` assigns: the ``assigns`` of the ``update_statement`` conds: the ``conds`` of the ``update_statement`` """ table: AstTable assigns: list[AstAssign] conds: list[AstCond] def verbose(self) -> str: # pragma: no cover tokens = [ "UPDATE", self.table.verbose(), "SET", ", ".join(assign.verbose() for assign in self.assigns), ] if self.conds: tokens.append("WHERE") tokens.append(", ".join(cond.verbose() for cond in self.conds)) return " ".join(tokens)
[docs] @dataclass(frozen=True, slots=True) class AstCreateTable(Ast): """ An AST representing a ``create_table_body``. Attributes: table: the ``table`` of the ``create_table_body`` defines: the ``defines`` of the ``create_table_body`` """ table: AstTable defines: list[AstDefine] def verbose(self) -> str: # pragma: no cover return " ".join([ "CREATE", "TABLE", self.table.verbose(), f"({', '.join(define.verbose() for define in self.defines)})", ])
[docs] @dataclass(frozen=True, slots=True) class AstCreateIndex(Ast): """ An AST representing a ``create_index_body``. Attributes: table: the ``table`` of the ``create_index_body`` attr: the ``attr`` of the ``create_index_body`` """ table: AstTable attr: AstAttr def verbose(self) -> str: # pragma: no cover return " ".join([ "CREATE", "INDEX", self.attr.verbose(), "FROM", self.table.verbose(), ])
[docs] @dataclass(frozen=True, slots=True) class AstDropTable(Ast): """ An AST representing a ``drop_table_body``. Attributes: table: the ``table`` of the ``drop_table_body`` """ table: AstTable def verbose(self) -> str: # pragma: no cover return f"DROP TABLE {self.table.verbose()}"
[docs] @dataclass(frozen=True, slots=True) class AstDropIndex(Ast): """ An AST representing a ``drop_index_body``. Attributes: table: the ``table`` of the ``drop_index_body`` attr: the ``attr`` of the ``drop_index_body`` """ table: AstTable attr: AstAttr def verbose(self) -> str: # pragma: no cover return " ".join([ "DROP", "INDEX", self.attr.verbose(), "FROM", self.table.verbose(), ])
[docs] @dataclass(frozen=True, slots=True) class AstShowTables(Ast): """ An AST representing a ``show_tables_statement``. """ def verbose(self) -> str: # pragma: no cover return "SHOW TABLES"
[docs] @dataclass(frozen=True, slots=True) class AstDescribeTable(Ast): """ An AST representing a ``describe_table_statement``. Attributes: table: the ``table`` of the ``describe_table_statement`` """ table: AstTable def verbose(self) -> str: # pragma: no cover return f"DESCRIBE TABLE {self.table.verbose()}"
[docs] @dataclass(frozen=True, slots=True) class AstDumpTable(Ast): """ An AST representing a ``dump_table_statement``. Attributes: table: the ``table`` of the ``dump_table_statement`` """ table: AstTable def verbose(self) -> str: # pragma: no cover return f"DUMP TABLE {self.table.verbose()}"
[docs] @dataclass(frozen=True, slots=True) class AstExit(Ast): """ An AST representing a ``exit_statement``. """ def verbose(self) -> str: # pragma: no cover return "EXIT"