Skip to content

Commit

Permalink
Add some helper code for PLpgSQL AST
Browse files Browse the repository at this point in the history
pglast returns PLpgSQL AST as a nested dict. This patch add some glue code
to convert the nested dict into a tree of objects to make it more
convenient to work with.
  • Loading branch information
svenklemm committed Aug 24, 2024
1 parent 1bc16c9 commit 39e44d2
Showing 1 changed file with 46 additions and 0 deletions.
46 changes: 46 additions & 0 deletions src/pgspot/plpgsql.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#
# pglast returns PLpgSQL AST as a nested dict. This file contains some glue code
# to convert the nested dict into a tree of objects.
#
# Disable pylint warnings about class names cause we are trying to match the
# AST names used by PLpgSQL parser.
# pylint: disable-msg=C0103
# pylint: disable-msg=R0903


class PLpgSQLNode:
def __init__(self, raw):
self.type = list(raw.keys())[0]
self.lineno = None
for k, v in raw[self.type].items():
setattr(self, k, build_node(v))

def __str__(self):
return f"{self.type}({self.lineno})"

def __repr__(self):
fields = self.__dict__.copy()
fields.pop("type")
return f"{self.type}({fields})"


class PLpgSQL_var(PLpgSQLNode):
def __init__(self, raw):
self.refname = None
self.datatype = None
super().__init__(raw)

def __str__(self):
return f"Variable(name={self.refname} type={self.datatype})"


def build_node(node):
if isinstance(node, list):
return [build_node(n) for n in node]
if isinstance(node, dict):
name = list(node.keys())[0]
if globals().get(name) is not None:
return globals()[name](node)
return PLpgSQLNode(node)

return node

0 comments on commit 39e44d2

Please sign in to comment.