pglast.visitors
— Other ways to inspect and manipulate the AST¶
- class pglast.visitors.Action¶
Abstract action singleton.
- class pglast.visitors.ActionMeta¶
Metaclass used to implement action singleton.
- class pglast.visitors.Add¶
Marker used to tell the iterator to insert nodes in the current sequence.
- class pglast.visitors.Ancestor(parent=None, node=None, member=None)¶
Simple object to keep track of the node’s ancestors while it’s being visited.
- Parameters
parent (Ancestor) – the parent of the new instance
node – the tracked object
member – either the name of the attribute or the index in the sequence that points to the tracked object in the parent container
An instance of this class represent a particular ancestor in the hierarchy chain: it carries a reference that points to the higher item in the chain, the associated
ast.Node
instance and a member, either the attribute name or sequential index in the parent node: the latter happens when the parent node is actually a tuple, not anNode
instance.Iteration yields the sequence of involved members, that is the path starting from the root of the AST tree that leads to leaf node.
Accessing an instance with a positive index returns the nth node up in the hierarchy.
When applied (using the
@
operator) to anast.Node
instance will traverse that node returning the leaf one corresponding to the whole chain.Example:
>>> tree = parse_sql('select 1') >>> root = Ancestor() >>> root ROOT >>> root@tree is tree True >>> root[0] is None True >>> select_stmt_path = root / (tree, 0) / (tree[0], 'stmt') >>> select_stmt_path ROOT → 0 → stmt >>> select_stmt_path@tree is tree[0].stmt True >>> select_stmt_path[0] is tree[0] True >>> columns_path = (select_stmt_path ... / (tree[0].stmt, 'targetList')) >>> first_col_path = (columns_path ... / (tree[0].stmt.targetList[0], 0)) >>> first_col_path ROOT → 0 → stmt → targetList → 0 >>> first_col_path[0] <ResTarget val=<A_Const val=<Integer val=1>>> >>> first_col_path[1] is columns_path[0] True
As said, the node is not always a
ast.Node
, but may be a tuple, possibly containing subtuples, for example thefunctions
slot ofRangeFunction
:>>> tree = parse_sql('SELECT * FROM ROWS' ... ' FROM(generate_series(10,11), get_users())') >>> root = Ancestor() >>> from_clause_path = (root / (tree, 0) / (tree[0], 'stmt') ... / (tree[0].stmt, 'fromClause')) >>> from_clause = tree[0].stmt.fromClause >>> from_clause_path@tree is from_clause True >>> range_function_path = (from_clause_path ... / (from_clause, 0)) >>> range_function = from_clause[0] >>> functions_path = (range_function_path ... / (range_function, 'functions')) >>> functions = from_clause[0].functions >>> functions_path@tree is functions True >>> generate_series_path = (functions_path ... / (functions, 0)) >>> generate_series_path@tree is functions[0] True >>> type(generate_series_path.node) <class 'tuple'> >>> type(generate_series_path.member) <class 'int'> >>> type(generate_series_path.node[0]) <class 'tuple'> >>> generate_series_path.node[0][0] <FuncCall funcname=(<String val='generate_series'>,)...
As an aid to visitors that apply changes to the AST, there are two methods,
update()
andapply()
, that takes care of the different cases, when node is an AST instance or instead it’s a tuple (or subtuple); the former does not directly change the AST tree, but postpones that when the latter is called.- apply()¶
Apply the pending change, if any, to the actual node.
- find_nearest(cls)¶
Find the nearest ancestor with a node of the given cls.
- update(new_value)¶
Set new_value as a pending change to the tracked node.
- class pglast.visitors.Continue¶
Marker used to tell the iterator to keep going.
- class pglast.visitors.Delete¶
Marker used to tell the iterator to delete current node.
- class pglast.visitors.ReferencedRelations(cte_names=None, skip_with_clause=None)¶
Concrete implementation of the
referenced_relations()
function.- Parameters
cte_names (set) – the set of surrounding CTE names
skip_with_clause (WithClause) – skip this clause, when specified
Calling an instance of this class will return a set of the names of the relations referenced by the given
node
.- visit_RangeVar(ancestors, node)¶
Collect relation names, taking into account defined CTE names
- class pglast.visitors.Skip¶
Marker used to tell the iterator to not descend into the current node.
- class pglast.visitors.Visitor¶
Base class implementing the visitor pattern.
To use it, you shall write a subclass that implements a set of particular named methods, specifically
visit_XYZ
whereXYZ
is the name of a class name defined in thepglast.ast
module.Instances of this class are callables and accept either a
ast.Node
instance or a sequence of instances, typically the result ofparse_sql
. The argument will be traversed in a breadth first order and eachNode
instance will be passed to the correspondingvisit_XYZ
method if it is implemented, falling back to the defaultvisit
method. If none of them are defined, the node will be ignored.The
visit_XYZ
methods receive two arguments: the ancestry chain of the node, an instance ofAncestor
and theNode
instance itself. The methods may return eitherNone
, an action or a new node that will replace the original one.- iterate(node)¶
Iterate thru node’s AST using a breadth-first traversing.
- Parameters
node – either a
ast.Node
instance or a tuple of those
This is a generator, that yields
Node
instances together with their ancestors chain as it finds them while traversing the tree.
- visit = None¶
The default visit method for any node without a specific one. When
None
, nothing happens.
- pglast.visitors.referenced_relations(stmt)¶
Return the set of relation names referenced in the given stmt.
- Parameters
stmt – either a string containing the
SQL
statement or aast.Node
instance- Returns
a set of strings, the names of the relations
Example:
>>> referenced_relations('WITH q1(x,y) AS (SELECT 1,2)' ... ' SELECT * FROM q1, q2') {'q2'}