This repository was archived by the owner on Jun 25, 2026. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathAstBuilder.py
More file actions
72 lines (54 loc) · 2.44 KB
/
Copy pathAstBuilder.py
File metadata and controls
72 lines (54 loc) · 2.44 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import typing as t
from cratedb_sqlparse.generated_parser.SqlBaseParser import SqlBaseParser
from cratedb_sqlparse.generated_parser.SqlBaseParserVisitor import SqlBaseParserVisitor
from cratedb_sqlparse.models import Table
class AstBuilder(SqlBaseParserVisitor):
"""
The class implements the antlr4 visitor pattern similar to how we do it in CrateDB
https://github.com/crate/crate/blob/master/libs/sql-parser/src/main/java/io/crate/sql/parser/AstBuilder.java
The biggest difference is that in CrateDB, `AstBuilder`, visitor methods
return a specialized Statement visitor.
Sqlparse just extracts whatever data it needs from the context and injects it to the current
visited statement, enriching its metadata.
"""
@property
def stmt(self):
if not hasattr(self, "_stmt"):
raise Exception("You should call `enrich` first, that is the entrypoint.")
return self._stmt
@stmt.setter
def stmt(self, value):
self._stmt = value
def enrich(self, stmt) -> None:
self.stmt = stmt
if self.stmt.ctx is None: # synthesized statement: no tree to walk
return
self.visit(self.stmt.ctx)
def visitTableName(self, ctx: SqlBaseParser.TableNameContext):
fqn = ctx.qname()
parts = self.get_text(fqn).split(".")
if len(parts) == 1:
name = parts[0]
schema = None
else:
schema, name = parts
self.stmt.metadata.tables.append(Table(schema=schema, name=name))
def visitGenericProperties(self, ctx: SqlBaseParser.GenericPropertiesContext):
node_properties = ctx.genericProperty()
properties = {}
parameterized_properties = {}
for property_ in node_properties:
key = self.get_text(property_.ident())
value = self.get_text(property_.expr())
properties[key] = value
if value and value[0] == "$":
# It might be a parameterized value, e.g. '$1'
if value[1:].isdigit():
parameterized_properties[key] = value
self.stmt.metadata.with_properties = properties
self.stmt.metadata.parameterized_properties = parameterized_properties
def get_text(self, node) -> t.Optional[str]:
"""Gets the text representation of the node or None if it doesn't have one"""
if node:
return node.getText().replace("'", "").replace('"', "")
return node