-
Notifications
You must be signed in to change notification settings - Fork 3
[Refactor] Add new AST node types and resolve AST TODOs #99
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -114,6 +114,42 @@ def __eq__(self, other): | |||||||||||||||||
| def __hash__(self): | ||||||||||||||||||
| return hash((super().__hash__(), self.value)) | ||||||||||||||||||
|
|
||||||||||||||||||
| class TypeNode(Node): | ||||||||||||||||||
| """SQL type keyword node (e.g. TEXT, DATE, INTEGER)""" | ||||||||||||||||||
| SQL_TYPE_KEYWORDS = {"TEXT", "DATE", "INTEGER", "TIMESTAMP", "VARCHAR", "BOOLEAN", "FLOAT", "SECOND", "MINUTE", "HOUR", "DAY", "WEEK", "MONTH", "YEAR", "NULL"} | ||||||||||||||||||
|
|
||||||||||||||||||
| def __init__(self, _name: str, **kwargs): | ||||||||||||||||||
| if _name not in TypeNode.SQL_TYPE_KEYWORDS: | ||||||||||||||||||
| raise ValueError(f"Invalid SQL type keyword: {_name}") | ||||||||||||||||||
| super().__init__(NodeType.TYPE, **kwargs) | ||||||||||||||||||
| self.name = _name | ||||||||||||||||||
|
|
||||||||||||||||||
| def __eq__(self, other): | ||||||||||||||||||
| if not isinstance(other, TypeNode): | ||||||||||||||||||
| return False | ||||||||||||||||||
| return super().__eq__(other) and self.name == other.name | ||||||||||||||||||
|
|
||||||||||||||||||
| def __hash__(self): | ||||||||||||||||||
| return hash((super().__hash__(), self.name)) | ||||||||||||||||||
|
|
||||||||||||||||||
| class ListNode(Node): | ||||||||||||||||||
| """A list of nodes, e.g. the right-hand side of an IN expression""" | ||||||||||||||||||
| def __init__(self, _items: List[Node], **kwargs): | ||||||||||||||||||
| super().__init__(NodeType.LIST, children=_items, **kwargs) | ||||||||||||||||||
|
|
||||||||||||||||||
| class IntervalNode(Node): | ||||||||||||||||||
| def __init__(self, _value, _unit: TypeNode, **kwargs): | ||||||||||||||||||
| super().__init__(NodeType.INTERVAL, children=[_unit], **kwargs) | ||||||||||||||||||
|
||||||||||||||||||
| super().__init__(NodeType.INTERVAL, children=[_unit], **kwargs) | |
| # Include the value in children when it is itself a Node, so that | |
| # generic traversals/formatters that walk via `children` see it. | |
| if isinstance(_value, Node): | |
| children = [_value, _unit] | |
| else: | |
| children = [_unit] | |
| super().__init__(NodeType.INTERVAL, children=children, **kwargs) |
Copilot
AI
Feb 28, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SelectNode tracks _distinct_on but does not include it in children. Any generic AST traversal that relies on children will miss DISTINCT ON expressions, which can lead to incorrect rewrites/formatting/analysis. Consider representing DISTINCT ON as part of the node’s subtree (e.g., include it in children with a dedicated wrapper node/field-aware traversal) and update consumers accordingly.
| super().__init__(NodeType.SELECT, children=_items, **kwargs) | |
| # Include DISTINCT ON expressions in children so generic AST traversals see them. | |
| children: List[Node] = list(_items) if _items is not None else [] | |
| if _distinct_on is not None: | |
| children.append(_distinct_on) | |
| super().__init__(NodeType.SELECT, children=children, **kwargs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TypeNode’s docstring says it represents SQL type keywords (TEXT/DATE/INTEGER), but the allowed keyword set also includes interval units (SECOND, MINUTE, …) and NULL. Either widen the docstring (and possibly rename the class) to reflect that it models general SQL keywords/units, or split this into separate node types to avoid confusion for AST consumers.