sqlite_parser/ast_nodes.py annotated source

Back to index

        

AST 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:

  1. Type Safety: Using Python dataclasses with type hints ensures correctness
  2. Completeness: Every SQL construct has a dedicated node type
  3. Position Tracking: All nodes include source span information for error reporting
  4. Hierarchy: Clear inheritance from base classes (Statement, Expression, Clause)
  5. 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))) ) )

41
42"""
43AST Node Definitions for SQLite SQL Parser
44
45This module defines all Abstract Syntax Tree node types for representing
46SQLite SQL statements, expressions, clauses, and definitions.
47
48Each node includes position information for error reporting and debugging.
49"""
50
51from dataclasses import dataclass, field
52from typing import Optional, List, Any, Union
53from enum import Enum, auto
54

Position 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.

71
72# ==============================================================================
73# Position and Base Classes
74# ==============================================================================
75
76@dataclass
77class Position:
78    """Position in source code"""
79    line: int
80    column: int
81    offset: int  # character offset from start
82
83    def __str__(self) -> str:
84        return f"{self.line}:{self.column}"
85
86
87@dataclass
88class Span:
89    """Source code span"""
90    start: Position
91    end: Position
92
93    def __str__(self) -> str:
94        return f"{self.start}-{self.end}"
95
96

Base 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.

121
122@dataclass
123class ASTNode:
124    """Base class for all AST nodes"""
125    span: Optional[Span] = field(default=None, kw_only=True)
126
127    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)})"
130
131
132@dataclass
133class Statement(ASTNode):
134    """Base class for all SQL statements"""
135    pass
136
137
138@dataclass
139class Expression(ASTNode):
140    """Base class for all expressions"""
141    pass
142
143
144@dataclass
145class Clause(ASTNode):
146    """Base class for all clauses"""
147    pass
148

SQL 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.

165
166# ==============================================================================
167# Enums for Various SQL Constructs
168# ==============================================================================
169
170class JoinType(Enum):
171    """Types of SQL joins"""
172    INNER = auto()
173    LEFT = auto()
174    RIGHT = auto()
175    FULL = auto()
176    CROSS = auto()
177
178
179class UnaryOperator(Enum):
180    """Unary operators"""
181    PLUS = "+"
182    MINUS = "-"
183    NOT = "NOT"
184    BITNOT = "~"
185
186
187class BinaryOperator(Enum):
188    """Binary operators"""
189    # Arithmetic
190    ADD = "+"
191    SUBTRACT = "-"
192    MULTIPLY = "*"
193    DIVIDE = "/"
194    MODULO = "%"
195
196    # Comparison
197    EQUAL = "="
198    EQUAL2 = "=="
199    NOT_EQUAL = "!="
200    NOT_EQUAL2 = "<>"
201    LESS_THAN = "<"
202    GREATER_THAN = ">"
203    LESS_EQUAL = "<="
204    GREATER_EQUAL = ">="
205
206    # Logical
207    AND = "AND"
208    OR = "OR"
209
210    # Bitwise
211    BIT_AND = "&"
212    BIT_OR = "|"
213    LEFT_SHIFT = "<<"
214    RIGHT_SHIFT = ">>"
215
216    # String
217    CONCAT = "||"
218
219    # Special
220    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"
232
233
234class CompoundOperator(Enum):
235    """Compound SELECT operators"""
236    UNION = "UNION"
237    UNION_ALL = "UNION ALL"
238    INTERSECT = "INTERSECT"
239    EXCEPT = "EXCEPT"
240
241
242class ConflictResolution(Enum):
243    """Conflict resolution algorithms"""
244    ROLLBACK = "ROLLBACK"
245    ABORT = "ABORT"
246    FAIL = "FAIL"
247    IGNORE = "IGNORE"
248    REPLACE = "REPLACE"
249
250
251class TransactionType(Enum):
252    """Transaction types"""
253    DEFERRED = "DEFERRED"
254    IMMEDIATE = "IMMEDIATE"
255    EXCLUSIVE = "EXCLUSIVE"
256
257
258class TriggerTiming(Enum):
259    """Trigger timing"""
260    BEFORE = "BEFORE"
261    AFTER = "AFTER"
262    INSTEAD_OF = "INSTEAD OF"
263
264
265class TriggerEvent(Enum):
266    """Trigger events"""
267    DELETE = "DELETE"
268    INSERT = "INSERT"
269    UPDATE = "UPDATE"
270
271
272class OrderDirection(Enum):
273    """ORDER BY direction"""
274    ASC = "ASC"
275    DESC = "DESC"
276
277
278class NullsOrdering(Enum):
279    """NULLS ordering"""
280    FIRST = "FIRST"
281    LAST = "LAST"
282
283
284class FrameType(Enum):
285    """Window frame type"""
286    ROWS = "ROWS"
287    RANGE = "RANGE"
288    GROUPS = "GROUPS"
289
290
291class 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"
298
299

Literal 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.

323
324# ==============================================================================
325# Literal Expressions
326# ==============================================================================
327
328@dataclass
329class NumberLiteral(Expression):
330    """Numeric literal (integer or float)"""
331    value: Union[int, float]
332    raw: str  # original text representation
333
334
335@dataclass
336class StringLiteral(Expression):
337    """String literal"""
338    value: str
339    quote_char: str  # ' or "
340
341
342@dataclass
343class BlobLiteral(Expression):
344    """BLOB literal (X'hex')"""
345    value: bytes
346    raw: str  # original hex string
347
348
349@dataclass
350class NullLiteral(Expression):
351    """NULL literal"""
352    pass
353
354
355@dataclass
356class BooleanLiteral(Expression):
357    """Boolean literal (TRUE/FALSE)"""
358    value: bool
359
360
361@dataclass
362class CurrentTimeLiteral(Expression):
363    """CURRENT_TIME, CURRENT_DATE, CURRENT_TIMESTAMP"""
364    type: str  # TIME, DATE, or TIMESTAMP
365

Identifiers 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.

392
393# ==============================================================================
394# Identifiers and References
395# ==============================================================================
396
397@dataclass
398class Identifier(Expression):
399    """Simple identifier"""
400    name: str
401    quoted: bool = False  # whether it was quoted in source
402
403
404@dataclass
405class QualifiedIdentifier(Expression):
406    """Qualified identifier (schema.table.column)"""
407    parts: List[str]  # [schema, table, column] or [table, column] or [schema, table]
408
409    @property
410    def schema(self) -> Optional[str]:
411        return self.parts[0] if len(self.parts) == 3 else None
412
413    @property
414    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 None
420
421    @property
422    def column(self) -> str:
423        return self.parts[-1]
424
425
426@dataclass
427class Parameter(Expression):
428    """Parameter placeholder (?123, :name, @name, $name)"""
429    name: Optional[str] = None  # None for ? or ?123
430    number: Optional[int] = None  # for ?123
431    prefix: str = "?"  # ?, :, @, or $
432
433
434# ==============================================================================
435# Unary and Binary Expressions
436# ==============================================================================
437
438@dataclass
439class UnaryExpression(Expression):
440    """Unary expression"""
441    operator: UnaryOperator
442    operand: Expression
443
444
445@dataclass
446class BinaryExpression(Expression):
447    """Binary expression"""
448    operator: BinaryOperator
449    left: Expression
450    right: Expression
451
452
453@dataclass
454class BetweenExpression(Expression):
455    """BETWEEN expression"""
456    value: Expression
457    lower: Expression
458    upper: Expression
459    negated: bool = False  # NOT BETWEEN
460
461
462@dataclass
463class InExpression(Expression):
464    """IN expression"""
465    value: Expression
466    values: Union[List[Expression], 'SubqueryExpression']  # list or subquery
467    negated: bool = False  # NOT IN
468
469
470@dataclass
471class LikeExpression(Expression):
472    """LIKE/GLOB/REGEXP/MATCH expression"""
473    value: Expression
474    pattern: Expression
475    operator: str  # LIKE, GLOB, REGEXP, or MATCH
476    escape: Optional[Expression] = None  # ESCAPE clause
477    negated: bool = False
478
479
480# ==============================================================================
481# Function Calls and Special Expressions
482# ==============================================================================
483
484@dataclass
485class FunctionCall(Expression):
486    """Function call"""
487    name: str
488    args: List[Expression]
489    distinct: bool = False  # DISTINCT keyword
490    star: bool = False  # COUNT(*)
491    filter_clause: Optional['WhereClause'] = None  # FILTER (WHERE ...)
492    over_clause: Optional['WindowExpression'] = None  # OVER (...)
493
494
495@dataclass
496class 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] = None
501
502
503@dataclass
504class CastExpression(Expression):
505    """CAST expression"""
506    expression: Expression
507    type_name: str
508
509
510@dataclass
511class CollateExpression(Expression):
512    """COLLATE expression"""
513    expression: Expression
514    collation: str
515
516
517@dataclass
518class ExistsExpression(Expression):
519    """EXISTS expression"""
520    subquery: 'SubqueryExpression'
521
522
523@dataclass
524class SubqueryExpression(Expression):
525    """Subquery in parentheses"""
526    select: 'SelectStatement'
527
528
529@dataclass
530class ParenthesizedExpression(Expression):
531    """Expression in parentheses (not a subquery)"""
532    expression: Expression
533
534
535@dataclass
536class RaiseExpression(Expression):
537    """RAISE expression (for triggers only)"""
538    raise_type: str  # IGNORE, ROLLBACK, ABORT, or FAIL
539    message: Optional[str] = None  # error message (not used for IGNORE)
540
541
542# ==============================================================================
543# Window Functions
544# ==============================================================================
545
546@dataclass
547class WindowExpression(Expression):
548    """Window specification (OVER clause)"""
549    window_name: Optional[str] = None  # named window
550    partition_by: List[Expression] = field(default_factory=list)
551    order_by: List['OrderingTerm'] = field(default_factory=list)
552    frame_spec: Optional['FrameSpec'] = None
553
554
555@dataclass
556class FrameSpec(ASTNode):
557    """Window frame specification"""
558    frame_type: FrameType  # ROWS, RANGE, or GROUPS
559    start: 'FrameBoundary'
560    end: Optional['FrameBoundary'] = None  # None means CURRENT ROW
561
562
563@dataclass
564class FrameBoundary(ASTNode):
565    """Window frame boundary"""
566    bound_type: FrameBound
567    offset: Optional[Expression] = None  # for PRECEDING/FOLLOWING with offset
568
569
570# ==============================================================================
571# Common Clauses
572# ==============================================================================
573
574@dataclass
575class WhereClause(Clause):
576    """WHERE clause"""
577    condition: Expression
578
579
580@dataclass
581class OrderByClause(Clause):
582    """ORDER BY clause"""
583    terms: List['OrderingTerm']
584
585
586@dataclass
587class OrderingTerm(ASTNode):
588    """Single ORDER BY term"""
589    expression: Expression
590    direction: Optional[OrderDirection] = None
591    nulls: Optional[NullsOrdering] = None
592
593
594@dataclass
595class GroupByClause(Clause):
596    """GROUP BY clause"""
597    expressions: List[Expression]
598    having: Optional['HavingClause'] = None
599
600
601@dataclass
602class HavingClause(Clause):
603    """HAVING clause"""
604    condition: Expression
605
606
607@dataclass
608class LimitClause(Clause):
609    """LIMIT clause"""
610    limit: Expression
611    offset: Optional[Expression] = None
612
613
614@dataclass
615class ReturningClause(Clause):
616    """RETURNING clause"""
617    columns: List['ResultColumn']
618
619
620# ==============================================================================
621# SELECT Statement Components
622# ==============================================================================
623
624@dataclass
625class ResultColumn(ASTNode):
626    """Result column in SELECT"""
627    expression: Optional[Expression] = None  # None for *
628    alias: Optional[str] = None
629    table_star: Optional[str] = None  # for table.*
630
631
632@dataclass
633class FromClause(Clause):
634    """FROM clause"""
635    source: Union['TableReference', 'JoinClause']
636
637
638@dataclass
639class TableReference(ASTNode):
640    """Table reference in FROM"""
641    name: QualifiedIdentifier
642    alias: Optional[str] = None
643    indexed_by: Optional[str] = None  # INDEXED BY index_name
644    not_indexed: bool = False  # NOT INDEXED
645
646
647@dataclass
648class SubqueryTable(ASTNode):
649    """Subquery as table source"""
650    select: 'SelectStatement'
651    alias: Optional[str] = None
652
653
654@dataclass
655class TableFunctionCall(ASTNode):
656    """Table-valued function call"""
657    function: FunctionCall
658    alias: Optional[str] = None
659
660
661@dataclass
662class JoinClause(ASTNode):
663    """JOIN clause"""
664    left: Union[TableReference, SubqueryTable, 'JoinClause']
665    join_type: Optional[JoinType]  # None for comma join
666    right: Union[TableReference, SubqueryTable]
667    natural: bool = False
668    on_condition: Optional[Expression] = None
669    using_columns: List[str] = field(default_factory=list)
670
671
672@dataclass
673class WithClause(Clause):
674    """WITH clause (CTE)"""
675    recursive: bool
676    ctes: List['CommonTableExpression']
677
678
679@dataclass
680class CommonTableExpression(ASTNode):
681    """Single CTE"""
682    name: str
683    columns: List[str] = field(default_factory=list)
684    select: 'SelectStatement' = None
685    materialized: Optional[bool] = None  # True=MATERIALIZED, False=NOT MATERIALIZED, None=default
686
687

SELECT 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

728
729# ==============================================================================
730# SELECT Statement
731# ==============================================================================
732
733@dataclass
734class SelectStatement(Statement):
735    """SELECT statement (including compound SELECTs)"""
736    with_clause: Optional[WithClause] = None
737    select_core: 'SelectCore' = None
738    compound_selects: List[tuple[CompoundOperator, 'SelectCore']] = field(default_factory=list)
739    order_by: Optional[OrderByClause] = None
740    limit: Optional[LimitClause] = None
741
742
743@dataclass
744class SelectCore(ASTNode):
745    """Core SELECT (without ORDER BY/LIMIT)"""
746    distinct: bool = False  # DISTINCT
747    all: bool = False  # ALL
748    columns: List[ResultColumn] = field(default_factory=list)
749    from_clause: Optional[FromClause] = None
750    where: Optional[WhereClause] = None
751    group_by: Optional[GroupByClause] = None
752    window_definitions: List[tuple[str, WindowExpression]] = field(default_factory=list)  # named windows
753

Data 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.

780
781# ==============================================================================
782# INSERT Statement
783# ==============================================================================
784
785@dataclass
786class InsertStatement(Statement):
787    """INSERT statement"""
788    with_clause: Optional[WithClause] = None
789    replace: bool = False  # REPLACE keyword
790    conflict_resolution: Optional[ConflictResolution] = None  # OR IGNORE, etc.
791    table: QualifiedIdentifier = None
792    table_alias: Optional[str] = None
793    columns: List[str] = field(default_factory=list)
794    values: Optional['ValuesClause'] = None
795    select: Optional[SelectStatement] = None
796    default_values: bool = False  # DEFAULT VALUES
797    upsert_clauses: List['UpsertClause'] = field(default_factory=list)
798    returning: Optional[ReturningClause] = None
799
800
801@dataclass
802class ValuesClause(ASTNode):
803    """VALUES clause"""
804    rows: List[List[Expression]]  # list of value lists
805
806
807@dataclass
808class UpsertClause(ASTNode):
809    """UPSERT clause (ON CONFLICT)"""
810    conflict_target: Optional['ConflictTarget'] = None
811    do_nothing: bool = False  # DO NOTHING
812    do_update: Optional['DoUpdateClause'] = None  # DO UPDATE SET ...
813
814
815@dataclass
816class ConflictTarget(ASTNode):
817    """Conflict target for UPSERT"""
818    indexed_columns: List['IndexedColumn'] = field(default_factory=list)
819    where: Optional[WhereClause] = None
820
821
822@dataclass
823class DoUpdateClause(ASTNode):
824    """DO UPDATE SET clause"""
825    assignments: List['Assignment'] = field(default_factory=list)
826    where: Optional[WhereClause] = None
827
828
829@dataclass
830class Assignment(ASTNode):
831    """Column assignment (SET col = expr)"""
832    column: str
833    value: Expression
834
835
836# ==============================================================================
837# UPDATE Statement
838# ==============================================================================
839
840@dataclass
841class UpdateStatement(Statement):
842    """UPDATE statement"""
843    with_clause: Optional[WithClause] = None
844    conflict_resolution: Optional[ConflictResolution] = None  # OR IGNORE, etc.
845    table: QualifiedIdentifier = None
846    table_alias: Optional[str] = None
847    indexed_by: Optional[str] = None
848    not_indexed: bool = False
849    assignments: List[Assignment] = field(default_factory=list)
850    from_clause: Optional[FromClause] = None  # UPDATE FROM extension
851    where: Optional[WhereClause] = None
852    order_by: Optional[OrderByClause] = None  # if SQLITE_ENABLE_UPDATE_DELETE_LIMIT
853    limit: Optional[LimitClause] = None  # if SQLITE_ENABLE_UPDATE_DELETE_LIMIT
854    returning: Optional[ReturningClause] = None
855
856
857# ==============================================================================
858# DELETE Statement
859# ==============================================================================
860
861@dataclass
862class DeleteStatement(Statement):
863    """DELETE statement"""
864    with_clause: Optional[WithClause] = None
865    table: QualifiedIdentifier = None
866    table_alias: Optional[str] = None
867    indexed_by: Optional[str] = None
868    not_indexed: bool = False
869    where: Optional[WhereClause] = None
870    order_by: Optional[OrderByClause] = None  # if SQLITE_ENABLE_UPDATE_DELETE_LIMIT
871    limit: Optional[LimitClause] = None  # if SQLITE_ENABLE_UPDATE_DELETE_LIMIT
872    returning: Optional[ReturningClause] = None
873
874

Data 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

909
910# ==============================================================================
911# CREATE TABLE Statement
912# ==============================================================================
913
914@dataclass
915class CreateTableStatement(Statement):
916    """CREATE TABLE statement"""
917    temporary: bool = False  # TEMP/TEMPORARY
918    if_not_exists: bool = False
919    table_name: QualifiedIdentifier = None
920    columns: List['ColumnDefinition'] = field(default_factory=list)
921    constraints: List['TableConstraint'] = field(default_factory=list)
922    without_rowid: bool = False
923    strict: bool = False
924    as_select: Optional[SelectStatement] = None  # for CREATE TABLE AS SELECT
925
926
927@dataclass
928class ColumnDefinition(ASTNode):
929    """Column definition"""
930    name: str
931    type_name: Optional[str] = None
932    constraints: List['ColumnConstraint'] = field(default_factory=list)
933
934
935@dataclass
936class ColumnConstraint(ASTNode):
937    """Column constraint"""
938    name: Optional[str] = None  # CONSTRAINT name
939    constraint_type: str = None  # PRIMARY_KEY, NOT_NULL, UNIQUE, CHECK, DEFAULT, COLLATE, REFERENCES, GENERATED
940    # Specific fields based on type
941    primary_key: bool = False
942    autoincrement: bool = False
943    unique: bool = False
944    not_null: bool = False
945    check_expression: Optional[Expression] = None
946    default_value: Optional[Expression] = None
947    collation: Optional[str] = None
948    foreign_key: Optional['ForeignKeyClause'] = None
949    generated: Optional['GeneratedColumnClause'] = None
950    on_conflict: Optional[ConflictResolution] = None
951
952
953@dataclass
954class TableConstraint(ASTNode):
955    """Table constraint"""
956    name: Optional[str] = None  # CONSTRAINT name
957    constraint_type: str = None  # PRIMARY_KEY, UNIQUE, CHECK, FOREIGN_KEY
958    # Specific fields
959    columns: List['IndexedColumn'] = field(default_factory=list)  # for PRIMARY KEY, UNIQUE, FOREIGN KEY
960    check_expression: Optional[Expression] = None  # for CHECK
961    foreign_key: Optional['ForeignKeyClause'] = None  # for FOREIGN KEY
962    on_conflict: Optional[ConflictResolution] = None
963
964
965@dataclass
966class ForeignKeyClause(ASTNode):
967    """FOREIGN KEY clause"""
968    foreign_table: str
969    foreign_columns: List[str] = field(default_factory=list)
970    on_delete: Optional[str] = None  # SET NULL, SET DEFAULT, CASCADE, RESTRICT, NO ACTION
971    on_update: Optional[str] = None
972    match: Optional[str] = None  # MATCH name
973    deferrable: Optional[bool] = None
974    initially_deferred: Optional[bool] = None
975
976
977@dataclass
978class GeneratedColumnClause(ASTNode):
979    """GENERATED ALWAYS AS clause"""
980    expression: Expression
981    stored: bool = False  # STORED vs VIRTUAL
982
983
984@dataclass
985class IndexedColumn(ASTNode):
986    """Indexed column (for indexes and constraints)"""
987    expression: Expression  # can be column name or expression
988    collation: Optional[str] = None
989    direction: Optional[OrderDirection] = None
990
991
992# ==============================================================================
993# ALTER TABLE Statement
994# ==============================================================================
995
996@dataclass
997class AlterTableStatement(Statement):
998    """ALTER TABLE statement"""
999    table_name: QualifiedIdentifier = None
1000    action: 'AlterTableAction' = None
1001
1002
1003@dataclass
1004class AlterTableAction(ASTNode):
1005    """ALTER TABLE action"""
1006    action_type: str = None  # RENAME_TABLE, RENAME_COLUMN, ADD_COLUMN, DROP_COLUMN
1007    # Specific fields
1008    new_table_name: Optional[str] = None  # for RENAME TABLE
1009    old_column_name: Optional[str] = None  # for RENAME COLUMN
1010    new_column_name: Optional[str] = None  # for RENAME COLUMN
1011    column_definition: Optional[ColumnDefinition] = None  # for ADD COLUMN
1012    column_name: Optional[str] = None  # for DROP COLUMN
1013
1014
1015# ==============================================================================
1016# CREATE INDEX Statement
1017# ==============================================================================
1018
1019@dataclass
1020class CreateIndexStatement(Statement):
1021    """CREATE INDEX statement"""
1022    unique: bool = False
1023    if_not_exists: bool = False
1024    index_name: QualifiedIdentifier = None
1025    table_name: str = None
1026    indexed_columns: List[IndexedColumn] = field(default_factory=list)
1027    where: Optional[WhereClause] = None  # partial index
1028
1029
1030# ==============================================================================
1031# CREATE VIEW Statement
1032# ==============================================================================
1033
1034@dataclass
1035class CreateViewStatement(Statement):
1036    """CREATE VIEW statement"""
1037    temporary: bool = False
1038    if_not_exists: bool = False
1039    view_name: QualifiedIdentifier = None
1040    columns: List[str] = field(default_factory=list)
1041    select: SelectStatement = None
1042
1043
1044# ==============================================================================
1045# CREATE TRIGGER Statement
1046# ==============================================================================
1047
1048@dataclass
1049class CreateTriggerStatement(Statement):
1050    """CREATE TRIGGER statement"""
1051    temporary: bool = False
1052    if_not_exists: bool = False
1053    trigger_name: QualifiedIdentifier = None
1054    timing: Optional[TriggerTiming] = None  # BEFORE, AFTER, or None for INSTEAD OF
1055    instead_of: bool = False
1056    event: TriggerEvent = None  # DELETE, INSERT, UPDATE
1057    update_columns: List[str] = field(default_factory=list)  # for UPDATE OF
1058    table_name: str = None
1059    for_each_row: bool = True  # always true in SQLite currently
1060    when: Optional[WhereClause] = None
1061    body: List[Statement] = field(default_factory=list)
1062
1063
1064# ==============================================================================
1065# CREATE VIRTUAL TABLE Statement
1066# ==============================================================================
1067
1068@dataclass
1069class CreateVirtualTableStatement(Statement):
1070    """CREATE VIRTUAL TABLE statement"""
1071    if_not_exists: bool = False
1072    table_name: QualifiedIdentifier = None
1073    module_name: str = None
1074    module_arguments: List[str] = field(default_factory=list)
1075
1076
1077# ==============================================================================
1078# DROP Statements
1079# ==============================================================================
1080
1081@dataclass
1082class DropTableStatement(Statement):
1083    """DROP TABLE statement"""
1084    if_exists: bool = False
1085    table_name: QualifiedIdentifier = None
1086
1087
1088@dataclass
1089class DropIndexStatement(Statement):
1090    """DROP INDEX statement"""
1091    if_exists: bool = False
1092    index_name: QualifiedIdentifier = None
1093
1094
1095@dataclass
1096class DropViewStatement(Statement):
1097    """DROP VIEW statement"""
1098    if_exists: bool = False
1099    view_name: QualifiedIdentifier = None
1100
1101
1102@dataclass
1103class DropTriggerStatement(Statement):
1104    """DROP TRIGGER statement"""
1105    if_exists: bool = False
1106    trigger_name: QualifiedIdentifier = None
1107
1108
1109# ==============================================================================
1110# Transaction Control Statements
1111# ==============================================================================
1112
1113@dataclass
1114class BeginStatement(Statement):
1115    """BEGIN TRANSACTION statement"""
1116    transaction_type: Optional[TransactionType] = None
1117
1118
1119@dataclass
1120class CommitStatement(Statement):
1121    """COMMIT TRANSACTION statement"""
1122    pass
1123
1124
1125@dataclass
1126class RollbackStatement(Statement):
1127    """ROLLBACK TRANSACTION statement"""
1128    savepoint: Optional[str] = None  # TO SAVEPOINT name
1129
1130
1131@dataclass
1132class SavepointStatement(Statement):
1133    """SAVEPOINT statement"""
1134    name: str
1135
1136
1137@dataclass
1138class ReleaseStatement(Statement):
1139    """RELEASE SAVEPOINT statement"""
1140    name: str
1141
1142
1143# ==============================================================================
1144# Database Management Statements
1145# ==============================================================================
1146
1147@dataclass
1148class AttachStatement(Statement):
1149    """ATTACH DATABASE statement"""
1150    database_expression: Expression
1151    schema_name: str
1152
1153
1154@dataclass
1155class DetachStatement(Statement):
1156    """DETACH DATABASE statement"""
1157    schema_name: str
1158
1159
1160@dataclass
1161class AnalyzeStatement(Statement):
1162    """ANALYZE statement"""
1163    target: Optional[QualifiedIdentifier] = None  # schema, table, or index
1164
1165
1166@dataclass
1167class VacuumStatement(Statement):
1168    """VACUUM statement"""
1169    schema_name: Optional[str] = None
1170    into_filename: Optional[Expression] = None
1171
1172
1173@dataclass
1174class ReindexStatement(Statement):
1175    """REINDEX statement"""
1176    target: Optional[Union[str, QualifiedIdentifier]] = None  # collation, table, or index
1177
1178
1179@dataclass
1180class ExplainStatement(Statement):
1181    """EXPLAIN [QUERY PLAN] statement"""
1182    query_plan: bool = False
1183    statement: Statement = None
1184
1185
1186@dataclass
1187class PragmaStatement(Statement):
1188    """PRAGMA statement"""
1189    pragma_name: str
1190    schema_name: Optional[str] = None
1191    value: Optional[Union[str, int, Expression]] = None
1192