sqlite_parser/ast_nodes.py annotated source
Back to indexAST Node Definitions
This module defines the complete Abstract Syntax Tree (AST) schema for SQLite SQL. With 80+ node types, it represents every SQL construct that SQLite supports.
Design Philosophy
The AST design follows these principles:
- Type Safety: Using Python dataclasses with type hints ensures correctness
- Completeness: Every SQL construct has a dedicated node type
- Position Tracking: All nodes include source span information for error reporting
- Hierarchy: Clear inheritance from base classes (Statement, Expression, Clause)
- Immutability: Dataclasses encourage treating AST as immutable data
Node Categories
The AST is organized into logical sections:
- Position & Base Classes: Foundation for all nodes
- Enums: Type-safe representations of SQL keywords and options
- Literals: Numbers, strings, blobs, NULL, booleans, timestamps
- Identifiers: Simple and qualified names, parameters
- Expressions: Operators, function calls, CASE, CAST, etc.
- Clauses: WHERE, ORDER BY, GROUP BY, LIMIT, etc.
- Statements: SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, etc.
Usage Pattern
When the parser encounters SQL like SELECT id FROM users WHERE age > 18, it builds:
python
SelectStatement(
select_core=SelectCore(
columns=[ResultColumn(Identifier("id"))],
from_clause=FromClause(TableReference(QualifiedIdentifier(["users"]))),
where=WhereClause(BinaryExpression(">", Identifier("age"), NumberLiteral(18)))
)
)
4142"""43AST Node Definitions for SQLite SQL Parser4445This module defines all Abstract Syntax Tree node types for representing46SQLite SQL statements, expressions, clauses, and definitions.4748Each node includes position information for error reporting and debugging.49"""5051from dataclasses import dataclass, field52from typing import Optional, List, Any, Union53from enum import Enum, auto54Position Tracking
Every AST node can optionally include a Span that records its exact location
in the source code. This enables precise error messages and syntax highlighting.
Position
A Position represents a single point in the source:
- line: 1-based line number
- column: 1-based column number
- offset: 0-based character offset from start
Span
A Span represents a range using start and end positions, tracking the full
extent of each syntax element.
7172# ==============================================================================73# Position and Base Classes74# ==============================================================================7576@dataclass77class Position:78 """Position in source code"""79 line: int80 column: int81 offset: int # character offset from start8283 def __str__(self) -> str:84 return f"{self.line}:{self.column}"858687@dataclass88class Span:89 """Source code span"""90 start: Position91 end: Position9293 def __str__(self) -> str:94 return f"{self.start}-{self.end}"9596Base AST Classes
These four classes form the foundation of the AST hierarchy:
ASTNode
The root of all AST nodes. Every node optionally tracks its source span for
position-aware error messages and IDE features. The custom __repr__ omits spans
for cleaner debug output.
Statement
Represents complete SQL statements like SELECT, INSERT, CREATE TABLE. Statements are top-level constructs that can be executed independently.
Expression
Represents values and computations: literals, identifiers, operators, function calls, subqueries. Expressions produce values and can be nested.
Clause
Represents named parts of statements: WHERE, ORDER BY, GROUP BY, LIMIT. Clauses organize related syntax within statements.
121122@dataclass123class ASTNode:124 """Base class for all AST nodes"""125 span: Optional[Span] = field(default=None, kw_only=True)126127 def __repr__(self) -> str:128 fields = [f"{k}={repr(v)}" for k, v in self.__dict__.items() if k != 'span']129 return f"{self.__class__.__name__}({', '.join(fields)})"130131132@dataclass133class Statement(ASTNode):134 """Base class for all SQL statements"""135 pass136137138@dataclass139class Expression(ASTNode):140 """Base class for all expressions"""141 pass142143144@dataclass145class Clause(ASTNode):146 """Base class for all clauses"""147 pass148SQL Construct Enumerations
These enums provide type-safe representations of SQL keywords and options. Using enums instead of strings prevents typos and enables IDE autocomplete.
The enums cover: - JoinType: INNER, LEFT, RIGHT, FULL, CROSS - Operators: Unary (+, -, NOT, ~) and Binary (+, -, , /, =, <, >, AND, OR, etc.) - CompoundOperator: UNION, INTERSECT, EXCEPT - ConflictResolution: ROLLBACK, ABORT, FAIL, IGNORE, REPLACE - TransactionType: DEFERRED, IMMEDIATE, EXCLUSIVE - TriggerTiming: BEFORE, AFTER, INSTEAD OF - OrderDirection: ASC, DESC - FrameType*: ROWS, RANGE, GROUPS (for window functions)
Each enum value includes its SQL string representation for code generation.
165166# ==============================================================================167# Enums for Various SQL Constructs168# ==============================================================================169170class JoinType(Enum):171 """Types of SQL joins"""172 INNER = auto()173 LEFT = auto()174 RIGHT = auto()175 FULL = auto()176 CROSS = auto()177178179class UnaryOperator(Enum):180 """Unary operators"""181 PLUS = "+"182 MINUS = "-"183 NOT = "NOT"184 BITNOT = "~"185186187class BinaryOperator(Enum):188 """Binary operators"""189 # Arithmetic190 ADD = "+"191 SUBTRACT = "-"192 MULTIPLY = "*"193 DIVIDE = "/"194 MODULO = "%"195196 # Comparison197 EQUAL = "="198 EQUAL2 = "=="199 NOT_EQUAL = "!="200 NOT_EQUAL2 = "<>"201 LESS_THAN = "<"202 GREATER_THAN = ">"203 LESS_EQUAL = "<="204 GREATER_EQUAL = ">="205206 # Logical207 AND = "AND"208 OR = "OR"209210 # Bitwise211 BIT_AND = "&"212 BIT_OR = "|"213 LEFT_SHIFT = "<<"214 RIGHT_SHIFT = ">>"215216 # String217 CONCAT = "||"218219 # Special220 IS = "IS"221 IS_NOT = "IS NOT"222 IN = "IN"223 NOT_IN = "NOT IN"224 LIKE = "LIKE"225 NOT_LIKE = "NOT LIKE"226 GLOB = "GLOB"227 NOT_GLOB = "NOT GLOB"228 MATCH = "MATCH"229 NOT_MATCH = "NOT MATCH"230 REGEXP = "REGEXP"231 NOT_REGEXP = "NOT REGEXP"232233234class CompoundOperator(Enum):235 """Compound SELECT operators"""236 UNION = "UNION"237 UNION_ALL = "UNION ALL"238 INTERSECT = "INTERSECT"239 EXCEPT = "EXCEPT"240241242class ConflictResolution(Enum):243 """Conflict resolution algorithms"""244 ROLLBACK = "ROLLBACK"245 ABORT = "ABORT"246 FAIL = "FAIL"247 IGNORE = "IGNORE"248 REPLACE = "REPLACE"249250251class TransactionType(Enum):252 """Transaction types"""253 DEFERRED = "DEFERRED"254 IMMEDIATE = "IMMEDIATE"255 EXCLUSIVE = "EXCLUSIVE"256257258class TriggerTiming(Enum):259 """Trigger timing"""260 BEFORE = "BEFORE"261 AFTER = "AFTER"262 INSTEAD_OF = "INSTEAD OF"263264265class TriggerEvent(Enum):266 """Trigger events"""267 DELETE = "DELETE"268 INSERT = "INSERT"269 UPDATE = "UPDATE"270271272class OrderDirection(Enum):273 """ORDER BY direction"""274 ASC = "ASC"275 DESC = "DESC"276277278class NullsOrdering(Enum):279 """NULLS ordering"""280 FIRST = "FIRST"281 LAST = "LAST"282283284class FrameType(Enum):285 """Window frame type"""286 ROWS = "ROWS"287 RANGE = "RANGE"288 GROUPS = "GROUPS"289290291class FrameBound(Enum):292 """Window frame boundary"""293 UNBOUNDED_PRECEDING = "UNBOUNDED PRECEDING"294 PRECEDING = "PRECEDING"295 CURRENT_ROW = "CURRENT ROW"296 FOLLOWING = "FOLLOWING"297 UNBOUNDED_FOLLOWING = "UNBOUNDED FOLLOWING"298299Literal Expressions
Literals represent constant values in SQL. Each literal type preserves both the parsed value and metadata about how it was written:
-
NumberLiteral: Integers (42) and floats (3.14, 1.5e10). Stores both the numeric value and original text to preserve precision and formatting.
-
StringLiteral: Text in single ('text') or double quotes ("text"). Records which quote character was used.
-
BlobLiteral: Binary data as hex (X'48656C6C6F'). Stores decoded bytes and original hex string.
-
NullLiteral: The NULL keyword, representing absence of value.
-
BooleanLiteral: TRUE or FALSE keywords (SQLite extension).
-
CurrentTimeLiteral: CURRENT_TIME, CURRENT_DATE, or CURRENT_TIMESTAMP for database-provided timestamps.
All literals inherit from Expression, making them usable anywhere an expression
is expected.
323324# ==============================================================================325# Literal Expressions326# ==============================================================================327328@dataclass329class NumberLiteral(Expression):330 """Numeric literal (integer or float)"""331 value: Union[int, float]332 raw: str # original text representation333334335@dataclass336class StringLiteral(Expression):337 """String literal"""338 value: str339 quote_char: str # ' or "340341342@dataclass343class BlobLiteral(Expression):344 """BLOB literal (X'hex')"""345 value: bytes346 raw: str # original hex string347348349@dataclass350class NullLiteral(Expression):351 """NULL literal"""352 pass353354355@dataclass356class BooleanLiteral(Expression):357 """Boolean literal (TRUE/FALSE)"""358 value: bool359360361@dataclass362class CurrentTimeLiteral(Expression):363 """CURRENT_TIME, CURRENT_DATE, CURRENT_TIMESTAMP"""364 type: str # TIME, DATE, or TIMESTAMP365Identifiers and References
Identifiers name database objects and values:
Identifier
A simple name like users or age. Records whether it was quoted (allowing spaces
and keywords as names): [user name], "table", `column`.
QualifiedIdentifier
A dot-separated name like schema.table.column or table.column. Provides convenient
properties (schema, table, column) to access parts without manual indexing.
Examples:
- users → parts=["users"]
- users.id → parts=["users", "id"] (table.column)
- main.users.id → parts=["main", "users", "id"] (schema.table.column)
Parameter
A placeholder for bound values:
- Positional: ? or ?1, ?2, ...
- Named: :name, @name, $name
Used in prepared statements to safely insert user data.
392393# ==============================================================================394# Identifiers and References395# ==============================================================================396397@dataclass398class Identifier(Expression):399 """Simple identifier"""400 name: str401 quoted: bool = False # whether it was quoted in source402403404@dataclass405class QualifiedIdentifier(Expression):406 """Qualified identifier (schema.table.column)"""407 parts: List[str] # [schema, table, column] or [table, column] or [schema, table]408409 @property410 def schema(self) -> Optional[str]:411 return self.parts[0] if len(self.parts) == 3 else None412413 @property414 def table(self) -> Optional[str]:415 if len(self.parts) == 3:416 return self.parts[1]417 elif len(self.parts) == 2:418 return self.parts[0]419 return None420421 @property422 def column(self) -> str:423 return self.parts[-1]424425426@dataclass427class Parameter(Expression):428 """Parameter placeholder (?123, :name, @name, $name)"""429 name: Optional[str] = None # None for ? or ?123430 number: Optional[int] = None # for ?123431 prefix: str = "?" # ?, :, @, or $432433434# ==============================================================================435# Unary and Binary Expressions436# ==============================================================================437438@dataclass439class UnaryExpression(Expression):440 """Unary expression"""441 operator: UnaryOperator442 operand: Expression443444445@dataclass446class BinaryExpression(Expression):447 """Binary expression"""448 operator: BinaryOperator449 left: Expression450 right: Expression451452453@dataclass454class BetweenExpression(Expression):455 """BETWEEN expression"""456 value: Expression457 lower: Expression458 upper: Expression459 negated: bool = False # NOT BETWEEN460461462@dataclass463class InExpression(Expression):464 """IN expression"""465 value: Expression466 values: Union[List[Expression], 'SubqueryExpression'] # list or subquery467 negated: bool = False # NOT IN468469470@dataclass471class LikeExpression(Expression):472 """LIKE/GLOB/REGEXP/MATCH expression"""473 value: Expression474 pattern: Expression475 operator: str # LIKE, GLOB, REGEXP, or MATCH476 escape: Optional[Expression] = None # ESCAPE clause477 negated: bool = False478479480# ==============================================================================481# Function Calls and Special Expressions482# ==============================================================================483484@dataclass485class FunctionCall(Expression):486 """Function call"""487 name: str488 args: List[Expression]489 distinct: bool = False # DISTINCT keyword490 star: bool = False # COUNT(*)491 filter_clause: Optional['WhereClause'] = None # FILTER (WHERE ...)492 over_clause: Optional['WindowExpression'] = None # OVER (...)493494495@dataclass496class CaseExpression(Expression):497 """CASE expression"""498 value: Optional[Expression] = None # for CASE value WHEN ...499 when_clauses: List[tuple[Expression, Expression]] = field(default_factory=list) # [(condition, result), ...]500 else_clause: Optional[Expression] = None501502503@dataclass504class CastExpression(Expression):505 """CAST expression"""506 expression: Expression507 type_name: str508509510@dataclass511class CollateExpression(Expression):512 """COLLATE expression"""513 expression: Expression514 collation: str515516517@dataclass518class ExistsExpression(Expression):519 """EXISTS expression"""520 subquery: 'SubqueryExpression'521522523@dataclass524class SubqueryExpression(Expression):525 """Subquery in parentheses"""526 select: 'SelectStatement'527528529@dataclass530class ParenthesizedExpression(Expression):531 """Expression in parentheses (not a subquery)"""532 expression: Expression533534535@dataclass536class RaiseExpression(Expression):537 """RAISE expression (for triggers only)"""538 raise_type: str # IGNORE, ROLLBACK, ABORT, or FAIL539 message: Optional[str] = None # error message (not used for IGNORE)540541542# ==============================================================================543# Window Functions544# ==============================================================================545546@dataclass547class WindowExpression(Expression):548 """Window specification (OVER clause)"""549 window_name: Optional[str] = None # named window550 partition_by: List[Expression] = field(default_factory=list)551 order_by: List['OrderingTerm'] = field(default_factory=list)552 frame_spec: Optional['FrameSpec'] = None553554555@dataclass556class FrameSpec(ASTNode):557 """Window frame specification"""558 frame_type: FrameType # ROWS, RANGE, or GROUPS559 start: 'FrameBoundary'560 end: Optional['FrameBoundary'] = None # None means CURRENT ROW561562563@dataclass564class FrameBoundary(ASTNode):565 """Window frame boundary"""566 bound_type: FrameBound567 offset: Optional[Expression] = None # for PRECEDING/FOLLOWING with offset568569570# ==============================================================================571# Common Clauses572# ==============================================================================573574@dataclass575class WhereClause(Clause):576 """WHERE clause"""577 condition: Expression578579580@dataclass581class OrderByClause(Clause):582 """ORDER BY clause"""583 terms: List['OrderingTerm']584585586@dataclass587class OrderingTerm(ASTNode):588 """Single ORDER BY term"""589 expression: Expression590 direction: Optional[OrderDirection] = None591 nulls: Optional[NullsOrdering] = None592593594@dataclass595class GroupByClause(Clause):596 """GROUP BY clause"""597 expressions: List[Expression]598 having: Optional['HavingClause'] = None599600601@dataclass602class HavingClause(Clause):603 """HAVING clause"""604 condition: Expression605606607@dataclass608class LimitClause(Clause):609 """LIMIT clause"""610 limit: Expression611 offset: Optional[Expression] = None612613614@dataclass615class ReturningClause(Clause):616 """RETURNING clause"""617 columns: List['ResultColumn']618619620# ==============================================================================621# SELECT Statement Components622# ==============================================================================623624@dataclass625class ResultColumn(ASTNode):626 """Result column in SELECT"""627 expression: Optional[Expression] = None # None for *628 alias: Optional[str] = None629 table_star: Optional[str] = None # for table.*630631632@dataclass633class FromClause(Clause):634 """FROM clause"""635 source: Union['TableReference', 'JoinClause']636637638@dataclass639class TableReference(ASTNode):640 """Table reference in FROM"""641 name: QualifiedIdentifier642 alias: Optional[str] = None643 indexed_by: Optional[str] = None # INDEXED BY index_name644 not_indexed: bool = False # NOT INDEXED645646647@dataclass648class SubqueryTable(ASTNode):649 """Subquery as table source"""650 select: 'SelectStatement'651 alias: Optional[str] = None652653654@dataclass655class TableFunctionCall(ASTNode):656 """Table-valued function call"""657 function: FunctionCall658 alias: Optional[str] = None659660661@dataclass662class JoinClause(ASTNode):663 """JOIN clause"""664 left: Union[TableReference, SubqueryTable, 'JoinClause']665 join_type: Optional[JoinType] # None for comma join666 right: Union[TableReference, SubqueryTable]667 natural: bool = False668 on_condition: Optional[Expression] = None669 using_columns: List[str] = field(default_factory=list)670671672@dataclass673class WithClause(Clause):674 """WITH clause (CTE)"""675 recursive: bool676 ctes: List['CommonTableExpression']677678679@dataclass680class CommonTableExpression(ASTNode):681 """Single CTE"""682 name: str683 columns: List[str] = field(default_factory=list)684 select: 'SelectStatement' = None685 materialized: Optional[bool] = None # True=MATERIALIZED, False=NOT MATERIALIZED, None=default686687SELECT Statement
The SELECT statement is the most complex SQL construct, supporting queries, subqueries, joins, aggregation, window functions, and compound queries.
Structure
[WITH ...] SELECT ... FROM ... WHERE ... GROUP BY ... HAVING ...
[UNION/INTERSECT/EXCEPT SELECT ...]
[ORDER BY ...] [LIMIT ...]
SelectStatement
The top-level node for any SELECT query. It consists of:
- with_clause: Optional CTEs (WITH RECURSIVE name AS ...)
- select_core: The main SELECT...FROM...WHERE...GROUP BY
- compound_selects: Additional SELECT cores connected by UNION/INTERSECT/EXCEPT
- order_by: Global ORDER BY (applies to entire compound query)
- limit: Global LIMIT/OFFSET
SelectCore
The core SELECT logic before ORDER BY/LIMIT:
- distinct/all: DISTINCT or ALL keyword
- columns: Result columns (expressions with optional aliases)
- from_clause: Tables, joins, or subqueries
- where: Filter conditions
- group_by: Grouping expressions with optional HAVING
- window_definitions: Named windows (WINDOW name AS (...))
Compound Queries
Multiple SELECT cores can be combined: - UNION [ALL]: Combine results (ALL keeps duplicates) - INTERSECT: Common rows - EXCEPT: Rows in first but not second
728729# ==============================================================================730# SELECT Statement731# ==============================================================================732733@dataclass734class SelectStatement(Statement):735 """SELECT statement (including compound SELECTs)"""736 with_clause: Optional[WithClause] = None737 select_core: 'SelectCore' = None738 compound_selects: List[tuple[CompoundOperator, 'SelectCore']] = field(default_factory=list)739 order_by: Optional[OrderByClause] = None740 limit: Optional[LimitClause] = None741742743@dataclass744class SelectCore(ASTNode):745 """Core SELECT (without ORDER BY/LIMIT)"""746 distinct: bool = False # DISTINCT747 all: bool = False # ALL748 columns: List[ResultColumn] = field(default_factory=list)749 from_clause: Optional[FromClause] = None750 where: Optional[WhereClause] = None751 group_by: Optional[GroupByClause] = None752 window_definitions: List[tuple[str, WindowExpression]] = field(default_factory=list) # named windows753Data Modification Statements (DML)
DML statements modify table data: INSERT, UPDATE, DELETE. They all support:
- WITH clause: CTEs can be used in data modification
- RETURNING clause: Return modified rows (SQLite 3.35+)
- Conflict resolution: OR IGNORE, OR REPLACE, OR ROLLBACK, etc.
INSERT
Adds rows to a table via:
- VALUES: Explicit row values INSERT INTO t VALUES (1, 2), (3, 4)
- SELECT: Insert query results INSERT INTO t SELECT * FROM other
- DEFAULT VALUES: Use column defaults INSERT INTO t DEFAULT VALUES
Supports UPSERT (ON CONFLICT) for handling primary key/unique violations.
UPDATE
Modifies existing rows with SET assignments and optional WHERE filter. SQLite extensions: UPDATE FROM (joins) and ORDER BY/LIMIT.
DELETE
Removes rows matching WHERE condition. Optional ORDER BY/LIMIT with SQLITE_ENABLE_UPDATE_DELETE_LIMIT.
780781# ==============================================================================782# INSERT Statement783# ==============================================================================784785@dataclass786class InsertStatement(Statement):787 """INSERT statement"""788 with_clause: Optional[WithClause] = None789 replace: bool = False # REPLACE keyword790 conflict_resolution: Optional[ConflictResolution] = None # OR IGNORE, etc.791 table: QualifiedIdentifier = None792 table_alias: Optional[str] = None793 columns: List[str] = field(default_factory=list)794 values: Optional['ValuesClause'] = None795 select: Optional[SelectStatement] = None796 default_values: bool = False # DEFAULT VALUES797 upsert_clauses: List['UpsertClause'] = field(default_factory=list)798 returning: Optional[ReturningClause] = None799800801@dataclass802class ValuesClause(ASTNode):803 """VALUES clause"""804 rows: List[List[Expression]] # list of value lists805806807@dataclass808class UpsertClause(ASTNode):809 """UPSERT clause (ON CONFLICT)"""810 conflict_target: Optional['ConflictTarget'] = None811 do_nothing: bool = False # DO NOTHING812 do_update: Optional['DoUpdateClause'] = None # DO UPDATE SET ...813814815@dataclass816class ConflictTarget(ASTNode):817 """Conflict target for UPSERT"""818 indexed_columns: List['IndexedColumn'] = field(default_factory=list)819 where: Optional[WhereClause] = None820821822@dataclass823class DoUpdateClause(ASTNode):824 """DO UPDATE SET clause"""825 assignments: List['Assignment'] = field(default_factory=list)826 where: Optional[WhereClause] = None827828829@dataclass830class Assignment(ASTNode):831 """Column assignment (SET col = expr)"""832 column: str833 value: Expression834835836# ==============================================================================837# UPDATE Statement838# ==============================================================================839840@dataclass841class UpdateStatement(Statement):842 """UPDATE statement"""843 with_clause: Optional[WithClause] = None844 conflict_resolution: Optional[ConflictResolution] = None # OR IGNORE, etc.845 table: QualifiedIdentifier = None846 table_alias: Optional[str] = None847 indexed_by: Optional[str] = None848 not_indexed: bool = False849 assignments: List[Assignment] = field(default_factory=list)850 from_clause: Optional[FromClause] = None # UPDATE FROM extension851 where: Optional[WhereClause] = None852 order_by: Optional[OrderByClause] = None # if SQLITE_ENABLE_UPDATE_DELETE_LIMIT853 limit: Optional[LimitClause] = None # if SQLITE_ENABLE_UPDATE_DELETE_LIMIT854 returning: Optional[ReturningClause] = None855856857# ==============================================================================858# DELETE Statement859# ==============================================================================860861@dataclass862class DeleteStatement(Statement):863 """DELETE statement"""864 with_clause: Optional[WithClause] = None865 table: QualifiedIdentifier = None866 table_alias: Optional[str] = None867 indexed_by: Optional[str] = None868 not_indexed: bool = False869 where: Optional[WhereClause] = None870 order_by: Optional[OrderByClause] = None # if SQLITE_ENABLE_UPDATE_DELETE_LIMIT871 limit: Optional[LimitClause] = None # if SQLITE_ENABLE_UPDATE_DELETE_LIMIT872 returning: Optional[ReturningClause] = None873874Data Definition Statements (DDL)
DDL statements define and modify database schema: CREATE, ALTER, DROP.
CREATE TABLE
Defines a new table with:
- Column Definitions: Name, type, and constraints for each column
- Table Constraints: PRIMARY KEY, UNIQUE, CHECK, FOREIGN KEY across columns
- Options:
- WITHOUT ROWID: Use primary key as physical storage key (no hidden rowid)
- STRICT: Enforce type affinity strictly (SQLite 3.37+)
- IF NOT EXISTS: No error if table already exists
- TEMPORARY: Table persists only for the session
Column Constraints
- PRIMARY KEY [AUTOINCREMENT]: Unique identifier, auto-increment for INTEGER
- NOT NULL: Require value
- UNIQUE: No duplicate values
- CHECK(expr): Value must satisfy expression
- DEFAULT expr: Default value if not specified
- COLLATE: Collation for text comparison
- REFERENCES: Foreign key to another table
- GENERATED ALWAYS AS (expr) [STORED|VIRTUAL]: Computed column
Table Constraints
Applied after all columns, can reference multiple columns: - PRIMARY KEY(col1, col2, ...): Composite primary key - UNIQUE(col1, col2, ...): Composite unique constraint - CHECK(expr): Table-level check - FOREIGN KEY(cols) REFERENCES table(cols): Foreign key relationship
909910# ==============================================================================911# CREATE TABLE Statement912# ==============================================================================913914@dataclass915class CreateTableStatement(Statement):916 """CREATE TABLE statement"""917 temporary: bool = False # TEMP/TEMPORARY918 if_not_exists: bool = False919 table_name: QualifiedIdentifier = None920 columns: List['ColumnDefinition'] = field(default_factory=list)921 constraints: List['TableConstraint'] = field(default_factory=list)922 without_rowid: bool = False923 strict: bool = False924 as_select: Optional[SelectStatement] = None # for CREATE TABLE AS SELECT925926927@dataclass928class ColumnDefinition(ASTNode):929 """Column definition"""930 name: str931 type_name: Optional[str] = None932 constraints: List['ColumnConstraint'] = field(default_factory=list)933934935@dataclass936class ColumnConstraint(ASTNode):937 """Column constraint"""938 name: Optional[str] = None # CONSTRAINT name939 constraint_type: str = None # PRIMARY_KEY, NOT_NULL, UNIQUE, CHECK, DEFAULT, COLLATE, REFERENCES, GENERATED940 # Specific fields based on type941 primary_key: bool = False942 autoincrement: bool = False943 unique: bool = False944 not_null: bool = False945 check_expression: Optional[Expression] = None946 default_value: Optional[Expression] = None947 collation: Optional[str] = None948 foreign_key: Optional['ForeignKeyClause'] = None949 generated: Optional['GeneratedColumnClause'] = None950 on_conflict: Optional[ConflictResolution] = None951952953@dataclass954class TableConstraint(ASTNode):955 """Table constraint"""956 name: Optional[str] = None # CONSTRAINT name957 constraint_type: str = None # PRIMARY_KEY, UNIQUE, CHECK, FOREIGN_KEY958 # Specific fields959 columns: List['IndexedColumn'] = field(default_factory=list) # for PRIMARY KEY, UNIQUE, FOREIGN KEY960 check_expression: Optional[Expression] = None # for CHECK961 foreign_key: Optional['ForeignKeyClause'] = None # for FOREIGN KEY962 on_conflict: Optional[ConflictResolution] = None963964965@dataclass966class ForeignKeyClause(ASTNode):967 """FOREIGN KEY clause"""968 foreign_table: str969 foreign_columns: List[str] = field(default_factory=list)970 on_delete: Optional[str] = None # SET NULL, SET DEFAULT, CASCADE, RESTRICT, NO ACTION971 on_update: Optional[str] = None972 match: Optional[str] = None # MATCH name973 deferrable: Optional[bool] = None974 initially_deferred: Optional[bool] = None975976977@dataclass978class GeneratedColumnClause(ASTNode):979 """GENERATED ALWAYS AS clause"""980 expression: Expression981 stored: bool = False # STORED vs VIRTUAL982983984@dataclass985class IndexedColumn(ASTNode):986 """Indexed column (for indexes and constraints)"""987 expression: Expression # can be column name or expression988 collation: Optional[str] = None989 direction: Optional[OrderDirection] = None990991992# ==============================================================================993# ALTER TABLE Statement994# ==============================================================================995996@dataclass997class AlterTableStatement(Statement):998 """ALTER TABLE statement"""999 table_name: QualifiedIdentifier = None1000 action: 'AlterTableAction' = None100110021003@dataclass1004class AlterTableAction(ASTNode):1005 """ALTER TABLE action"""1006 action_type: str = None # RENAME_TABLE, RENAME_COLUMN, ADD_COLUMN, DROP_COLUMN1007 # Specific fields1008 new_table_name: Optional[str] = None # for RENAME TABLE1009 old_column_name: Optional[str] = None # for RENAME COLUMN1010 new_column_name: Optional[str] = None # for RENAME COLUMN1011 column_definition: Optional[ColumnDefinition] = None # for ADD COLUMN1012 column_name: Optional[str] = None # for DROP COLUMN101310141015# ==============================================================================1016# CREATE INDEX Statement1017# ==============================================================================10181019@dataclass1020class CreateIndexStatement(Statement):1021 """CREATE INDEX statement"""1022 unique: bool = False1023 if_not_exists: bool = False1024 index_name: QualifiedIdentifier = None1025 table_name: str = None1026 indexed_columns: List[IndexedColumn] = field(default_factory=list)1027 where: Optional[WhereClause] = None # partial index102810291030# ==============================================================================1031# CREATE VIEW Statement1032# ==============================================================================10331034@dataclass1035class CreateViewStatement(Statement):1036 """CREATE VIEW statement"""1037 temporary: bool = False1038 if_not_exists: bool = False1039 view_name: QualifiedIdentifier = None1040 columns: List[str] = field(default_factory=list)1041 select: SelectStatement = None104210431044# ==============================================================================1045# CREATE TRIGGER Statement1046# ==============================================================================10471048@dataclass1049class CreateTriggerStatement(Statement):1050 """CREATE TRIGGER statement"""1051 temporary: bool = False1052 if_not_exists: bool = False1053 trigger_name: QualifiedIdentifier = None1054 timing: Optional[TriggerTiming] = None # BEFORE, AFTER, or None for INSTEAD OF1055 instead_of: bool = False1056 event: TriggerEvent = None # DELETE, INSERT, UPDATE1057 update_columns: List[str] = field(default_factory=list) # for UPDATE OF1058 table_name: str = None1059 for_each_row: bool = True # always true in SQLite currently1060 when: Optional[WhereClause] = None1061 body: List[Statement] = field(default_factory=list)106210631064# ==============================================================================1065# CREATE VIRTUAL TABLE Statement1066# ==============================================================================10671068@dataclass1069class CreateVirtualTableStatement(Statement):1070 """CREATE VIRTUAL TABLE statement"""1071 if_not_exists: bool = False1072 table_name: QualifiedIdentifier = None1073 module_name: str = None1074 module_arguments: List[str] = field(default_factory=list)107510761077# ==============================================================================1078# DROP Statements1079# ==============================================================================10801081@dataclass1082class DropTableStatement(Statement):1083 """DROP TABLE statement"""1084 if_exists: bool = False1085 table_name: QualifiedIdentifier = None108610871088@dataclass1089class DropIndexStatement(Statement):1090 """DROP INDEX statement"""1091 if_exists: bool = False1092 index_name: QualifiedIdentifier = None109310941095@dataclass1096class DropViewStatement(Statement):1097 """DROP VIEW statement"""1098 if_exists: bool = False1099 view_name: QualifiedIdentifier = None110011011102@dataclass1103class DropTriggerStatement(Statement):1104 """DROP TRIGGER statement"""1105 if_exists: bool = False1106 trigger_name: QualifiedIdentifier = None110711081109# ==============================================================================1110# Transaction Control Statements1111# ==============================================================================11121113@dataclass1114class BeginStatement(Statement):1115 """BEGIN TRANSACTION statement"""1116 transaction_type: Optional[TransactionType] = None111711181119@dataclass1120class CommitStatement(Statement):1121 """COMMIT TRANSACTION statement"""1122 pass112311241125@dataclass1126class RollbackStatement(Statement):1127 """ROLLBACK TRANSACTION statement"""1128 savepoint: Optional[str] = None # TO SAVEPOINT name112911301131@dataclass1132class SavepointStatement(Statement):1133 """SAVEPOINT statement"""1134 name: str113511361137@dataclass1138class ReleaseStatement(Statement):1139 """RELEASE SAVEPOINT statement"""1140 name: str114111421143# ==============================================================================1144# Database Management Statements1145# ==============================================================================11461147@dataclass1148class AttachStatement(Statement):1149 """ATTACH DATABASE statement"""1150 database_expression: Expression1151 schema_name: str115211531154@dataclass1155class DetachStatement(Statement):1156 """DETACH DATABASE statement"""1157 schema_name: str115811591160@dataclass1161class AnalyzeStatement(Statement):1162 """ANALYZE statement"""1163 target: Optional[QualifiedIdentifier] = None # schema, table, or index116411651166@dataclass1167class VacuumStatement(Statement):1168 """VACUUM statement"""1169 schema_name: Optional[str] = None1170 into_filename: Optional[Expression] = None117111721173@dataclass1174class ReindexStatement(Statement):1175 """REINDEX statement"""1176 target: Optional[Union[str, QualifiedIdentifier]] = None # collation, table, or index117711781179@dataclass1180class ExplainStatement(Statement):1181 """EXPLAIN [QUERY PLAN] statement"""1182 query_plan: bool = False1183 statement: Statement = None118411851186@dataclass1187class PragmaStatement(Statement):1188 """PRAGMA statement"""1189 pragma_name: str1190 schema_name: Optional[str] = None1191 value: Optional[Union[str, int, Expression]] = None1192