Я хотел бы использовать Antrl4 в Python для обработки сценариев SQL/PLSQL и извлечения условий JOIN.
Для этого я пытаюсь, во-первых, понять, как они представлены в дереве парсера, возвращаемом PlSqlParser.sql_script.
У меня есть простой SQL:
SELECT ta.col1, tb.col5
FROM mytabA ta
JOIN mayTabB tb ON ta.col1 = tb.col2
WHERE ta.col3 = 'AXA';
Я использую следующий сценарий Python для обработки сценария SQL:
from antlr4 import *
from antlr4.tree.Tree import TerminalNodeImpl
#from antlr4.tree.Tree import ParseTree
from antlr4.tree.Trees import Trees
from PlSqlLexer import PlSqlLexer
from PlSqlParser import PlSqlParser
from PlSqlParserListener import PlSqlParserListener
def handleTree(tree, lvl=0):
for child in tree.getChildren():
if isinstance(child, TerminalNode):
print(lvl*'│ ' + '└─', child)
else:
handleTree(child, lvl+1)
class KeyPrinter(PlSqlParserListener):
def enterSelect_statement(self, ctx):
handleTree(ctx, 0)
def main():
with open( "myscript.sql" ) as file:
filesrc = file.read()
lexer = PlSqlLexer(InputStream(filesrc))
tokens = CommonTokenStream(lexer)
tokens.fill()
parser = PlSqlParser(tokens)
tree = parser.sql_script()
printer = KeyPrinter()
walker = ParseTreeWalker()
walker.walk(printer, tree)
if __name__ == '__main__':
main()
И результат:
│ │ │ │ └─ SELECT
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─ ta
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─ .
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─ col1
│ │ │ │ │ └─ ,
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─ tb
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─ .
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─ col5
│ │ │ │ │ └─ FROM
│ │ │ │ │ │ │ │ │ │ │ │ │ │ └─ mytabA
│ │ │ │ │ │ │ │ │ │ │ │ └─ ta
│ │ │ │ │ │ │ │ └─ JOIN
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─ mayTabB
│ │ │ │ │ │ │ │ │ │ │ │ │ └─ tb
│ │ │ │ │ │ │ │ │ └─ ON
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─ ta
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─ .
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─ col1
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─ =
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─ tb
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─ .
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─ col2
│ │ │ │ │ └─ WHERE
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─ ta
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─ .
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─ col3
│ │ │ │ │ │ │ │ │ │ │ │ └─ =
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─ 'AXA'
Я меняю функцию handleTree, чтобы печатать child, чтобы попытаться понять, какую информацию можно использовать для извлечения нужной мне информации:
def handleTree(tree, lvl=0):
for child in tree.getChildren():
print ( child )
if isinstance(child, TerminalNode):
print(lvl*'│ ' + '└─', child)
else:
handleTree(child, lvl+1)
Теперь вывод:
[16068 15857 2535 2384]
[16066 16068 15857 2535 2384]
[16256 16066 16068 15857 2535 2384]
[16263 16256 16066 16068 15857 2535 2384]
SELECT
│ │ │ │ └─ SELECT
[16284 16263 16256 16066 16068 15857 2535 2384]
[16309 16284 16263 16256 16066 16068 15857 2535 2384]
[16326 16309 16284 16263 16256 16066 16068 15857 2535 2384]
[17255 16326 16309 16284 16263 16256 16066 16068 15857 2535 2384]
[17264 17255 16326 16309 16284 16263 16256 16066 16068 15857 2535 2384]
[17280 17264 17255 16326 16309 16284 16263 16256 16066 16068 15857 2535 2384]
[17318 17280 17264 17255 16326 16309 16284 16263 16256 16066 16068 15857 2535 2384]
[17339 17318 17280 17264 17255 16326 16309 16284 16263 16256 16066 16068 15857 2535 2384]
[17350 17339 17318 17280 17264 17255 16326 16309 16284 16263 16256 16066 16068 15857 2535 2384]
[17409 17350 17339 17318 17280 17264 17255 16326 16309 16284 16263 16256 16066 16068 15857 2535 2384]
[17472 17409 17350 17339 17318 17280 17264 17255 16326 16309 16284 16263 16256 16066 16068 15857 2535 2384]
[17555 17472 17409 17350 17339 17318 17280 17264 17255 16326 16309 16284 16263 16256 16066 16068 15857 2535 2384]
[17669 17555 17472 17409 17350 17339 17318 17280 17264 17255 16326 16309 16284 16263 16256 16066 16068 15857 2535 2384]
[2342 17669 17555 17472 17409 17350 17339 17318 17280 17264 17255 16326 16309 16284 16263 16256 16066 16068 15857 2535 2384]
[19724 2342 17669 17555 17472 17409 17350 17339 17318 17280 17264 17255 16326 16309 16284 16263 16256 16066 16068 15857 2535 2384]
[19747 19724 2342 17669 17555 17472 17409 17350 17339 17318 17280 17264 17255 16326 16309 16284 16263 16256 16066 16068 15857 2535 2384]
[20209 19747 19724 2342 17669 17555 17472 17409 17350 17339 17318 17280 17264 17255 16326 16309 16284 16263 16256 16066 16068 15857 2535 2384]
ta
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─ ta
.
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─ .
[19733 17669 17555 17472 17409 17350 17339 17318 17280 17264 17255 16326 16309 16284 16263 16256 16066 16068 15857 2535 2384]
[19747 19733 17669 17555 17472 17409 17350 17339 17318 17280 17264 17255 16326 16309 16284 16263 16256 16066 16068 15857 2535 2384]
[20209 19747 19733 17669 17555 17472 17409 17350 17339 17318 17280 17264 17255 16326 16309 16284 16263 16256 16066 16068 15857 2535 2384]
col1
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─ col1
,
│ │ │ │ │ └─ ,
[16311 16284 16263 16256 16066 16068 15857 2535 2384]
[16326 16311 16284 16263 16256 16066 16068 15857 2535 2384]
[17255 16326 16311 16284 16263 16256 16066 16068 15857 2535 2384]
[17264 17255 16326 16311 16284 16263 16256 16066 16068 15857 2535 2384]
[17280 17264 17255 16326 16311 16284 16263 16256 16066 16068 15857 2535 2384]
[17318 17280 17264 17255 16326 16311 16284 16263 16256 16066 16068 15857 2535 2384]
[17339 17318 17280 17264 17255 16326 16311 16284 16263 16256 16066 16068 15857 2535 2384]
[17350 17339 17318 17280 17264 17255 16326 16311 16284 16263 16256 16066 16068 15857 2535 2384]
[17409 17350 17339 17318 17280 17264 17255 16326 16311 16284 16263 16256 16066 16068 15857 2535 2384]
[17472 17409 17350 17339 17318 17280 17264 17255 16326 16311 16284 16263 16256 16066 16068 15857 2535 2384]
[17555 17472 17409 17350 17339 17318 17280 17264 17255 16326 16311 16284 16263 16256 16066 16068 15857 2535 2384]
[17669 17555 17472 17409 17350 17339 17318 17280 17264 17255 16326 16311 16284 16263 16256 16066 16068 15857 2535 2384]
[2342 17669 17555 17472 17409 17350 17339 17318 17280 17264 17255 16326 16311 16284 16263 16256 16066 16068 15857 2535 2384]
[19724 2342 17669 17555 17472 17409 17350 17339 17318 17280 17264 17255 16326 16311 16284 16263 16256 16066 16068 15857 2535 2384]
[19747 19724 2342 17669 17555 17472 17409 17350 17339 17318 17280 17264 17255 16326 16311 16284 16263 16256 16066 16068 15857 2535 2384]
[20209 19747 19724 2342 17669 17555 17472 17409 17350 17339 17318 17280 17264 17255 16326 16311 16284 16263 16256 16066 16068 15857 2535 2384]
tb
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─ tb
.
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─ .
[19733 17669 17555 17472 17409 17350 17339 17318 17280 17264 17255 16326 16311 16284 16263 16256 16066 16068 15857 2535 2384]
[19747 19733 17669 17555 17472 17409 17350 17339 17318 17280 17264 17255 16326 16311 16284 16263 16256 16066 16068 15857 2535 2384]
[20209 19747 19733 17669 17555 17472 17409 17350 17339 17318 17280 17264 17255 16326 16311 16284 16263 16256 16066 16068 15857 2535 2384]
col5
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─ col5
[16288 16263 16256 16066 16068 15857 2535 2384]
FROM
│ │ │ │ │ └─ FROM
[16320 16288 16263 16256 16066 16068 15857 2535 2384]
[16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[16340 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[16351 16340 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[16361 16351 16340 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[17152 16361 16351 16340 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[19376 17152 16361 16351 16340 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[20207 19376 17152 16361 16351 16340 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[20209 20207 19376 17152 16361 16351 16340 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
mytabA
│ │ │ │ │ │ │ │ │ │ │ │ │ │ └─ mytabA
[16358 16340 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[19174 16358 16340 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[20207 19174 16358 16340 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[20209 20207 19174 16358 16340 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
ta
│ │ │ │ │ │ │ │ │ │ │ │ └─ ta
[16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
JOIN
│ │ │ │ │ │ │ │ └─ JOIN
[16397 16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[16351 16397 16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[16361 16351 16397 16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[17152 16361 16351 16397 16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[19376 17152 16361 16351 16397 16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[20207 19376 17152 16361 16351 16397 16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[20209 20207 19376 17152 16361 16351 16397 16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
mayTabB
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─ mayTabB
[16358 16397 16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[19174 16358 16397 16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[20207 19174 16358 16397 16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[20209 20207 19174 16358 16397 16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
tb
│ │ │ │ │ │ │ │ │ │ │ │ │ └─ tb
[16401 16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
ON
│ │ │ │ │ │ │ │ │ └─ ON
[16414 16401 16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[17217 16414 16401 16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[17255 17217 16414 16401 16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[17264 17255 17217 16414 16401 16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[17280 17264 17255 17217 16414 16401 16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[17318 17280 17264 17255 17217 16414 16401 16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[2070 17318 17280 17264 17255 17217 16414 16401 16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[17339 2070 17318 17280 17264 17255 17217 16414 16401 16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[17350 17339 2070 17318 17280 17264 17255 17217 16414 16401 16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[17409 17350 17339 2070 17318 17280 17264 17255 17217 16414 16401 16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[17472 17409 17350 17339 2070 17318 17280 17264 17255 17217 16414 16401 16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[17555 17472 17409 17350 17339 2070 17318 17280 17264 17255 17217 16414 16401 16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[17669 17555 17472 17409 17350 17339 2070 17318 17280 17264 17255 17217 16414 16401 16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[2342 17669 17555 17472 17409 17350 17339 2070 17318 17280 17264 17255 17217 16414 16401 16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[19724 2342 17669 17555 17472 17409 17350 17339 2070 17318 17280 17264 17255 17217 16414 16401 16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[19747 19724 2342 17669 17555 17472 17409 17350 17339 2070 17318 17280 17264 17255 17217 16414 16401 16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[20209 19747 19724 2342 17669 17555 17472 17409 17350 17339 2070 17318 17280 17264 17255 17217 16414 16401 16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
ta
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─ ta
.
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─ .
[19733 17669 17555 17472 17409 17350 17339 2070 17318 17280 17264 17255 17217 16414 16401 16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[19747 19733 17669 17555 17472 17409 17350 17339 2070 17318 17280 17264 17255 17217 16414 16401 16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[20209 19747 19733 17669 17555 17472 17409 17350 17339 2070 17318 17280 17264 17255 17217 16414 16401 16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
col1
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─ col1
[17342 17318 17280 17264 17255 17217 16414 16401 16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
=
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─ =
[17343 17318 17280 17264 17255 17217 16414 16401 16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[17339 17343 17318 17280 17264 17255 17217 16414 16401 16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[17350 17339 17343 17318 17280 17264 17255 17217 16414 16401 16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[17409 17350 17339 17343 17318 17280 17264 17255 17217 16414 16401 16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[17472 17409 17350 17339 17343 17318 17280 17264 17255 17217 16414 16401 16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[17555 17472 17409 17350 17339 17343 17318 17280 17264 17255 17217 16414 16401 16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[17669 17555 17472 17409 17350 17339 17343 17318 17280 17264 17255 17217 16414 16401 16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[2342 17669 17555 17472 17409 17350 17339 17343 17318 17280 17264 17255 17217 16414 16401 16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[19724 2342 17669 17555 17472 17409 17350 17339 17343 17318 17280 17264 17255 17217 16414 16401 16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[19747 19724 2342 17669 17555 17472 17409 17350 17339 17343 17318 17280 17264 17255 17217 16414 16401 16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[20209 19747 19724 2342 17669 17555 17472 17409 17350 17339 17343 17318 17280 17264 17255 17217 16414 16401 16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
tb
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─ tb
.
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─ .
[19733 17669 17555 17472 17409 17350 17339 17343 17318 17280 17264 17255 17217 16414 16401 16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[19747 19733 17669 17555 17472 17409 17350 17339 17343 17318 17280 17264 17255 17217 16414 16401 16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
[20209 19747 19733 17669 17555 17472 17409 17350 17339 17343 17318 17280 17264 17255 17217 16414 16401 16341 16332 16320 16288 16263 16256 16066 16068 15857 2535 2384]
col2
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─ col2
[16289 16263 16256 16066 16068 15857 2535 2384]
WHERE
│ │ │ │ │ └─ WHERE
[19182 16289 16263 16256 16066 16068 15857 2535 2384]
[17217 19182 16289 16263 16256 16066 16068 15857 2535 2384]
[17255 17217 19182 16289 16263 16256 16066 16068 15857 2535 2384]
[17264 17255 17217 19182 16289 16263 16256 16066 16068 15857 2535 2384]
[17280 17264 17255 17217 19182 16289 16263 16256 16066 16068 15857 2535 2384]
[17318 17280 17264 17255 17217 19182 16289 16263 16256 16066 16068 15857 2535 2384]
[2070 17318 17280 17264 17255 17217 19182 16289 16263 16256 16066 16068 15857 2535 2384]
[17339 2070 17318 17280 17264 17255 17217 19182 16289 16263 16256 16066 16068 15857 2535 2384]
[17350 17339 2070 17318 17280 17264 17255 17217 19182 16289 16263 16256 16066 16068 15857 2535 2384]
[17409 17350 17339 2070 17318 17280 17264 17255 17217 19182 16289 16263 16256 16066 16068 15857 2535 2384]
[17472 17409 17350 17339 2070 17318 17280 17264 17255 17217 19182 16289 16263 16256 16066 16068 15857 2535 2384]
[17555 17472 17409 17350 17339 2070 17318 17280 17264 17255 17217 19182 16289 16263 16256 16066 16068 15857 2535 2384]
[17669 17555 17472 17409 17350 17339 2070 17318 17280 17264 17255 17217 19182 16289 16263 16256 16066 16068 15857 2535 2384]
[2342 17669 17555 17472 17409 17350 17339 2070 17318 17280 17264 17255 17217 19182 16289 16263 16256 16066 16068 15857 2535 2384]
[19724 2342 17669 17555 17472 17409 17350 17339 2070 17318 17280 17264 17255 17217 19182 16289 16263 16256 16066 16068 15857 2535 2384]
[19747 19724 2342 17669 17555 17472 17409 17350 17339 2070 17318 17280 17264 17255 17217 19182 16289 16263 16256 16066 16068 15857 2535 2384]
[20209 19747 19724 2342 17669 17555 17472 17409 17350 17339 2070 17318 17280 17264 17255 17217 19182 16289 16263 16256 16066 16068 15857 2535 2384]
ta
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─ ta
.
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─ .
[19733 17669 17555 17472 17409 17350 17339 2070 17318 17280 17264 17255 17217 19182 16289 16263 16256 16066 16068 15857 2535 2384]
[19747 19733 17669 17555 17472 17409 17350 17339 2070 17318 17280 17264 17255 17217 19182 16289 16263 16256 16066 16068 15857 2535 2384]
[20209 19747 19733 17669 17555 17472 17409 17350 17339 2070 17318 17280 17264 17255 17217 19182 16289 16263 16256 16066 16068 15857 2535 2384]
col3
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─ col3
[17342 17318 17280 17264 17255 17217 19182 16289 16263 16256 16066 16068 15857 2535 2384]
=
│ │ │ │ │ │ │ │ │ │ │ │ └─ =
[17343 17318 17280 17264 17255 17217 19182 16289 16263 16256 16066 16068 15857 2535 2384]
[17339 17343 17318 17280 17264 17255 17217 19182 16289 16263 16256 16066 16068 15857 2535 2384]
[17350 17339 17343 17318 17280 17264 17255 17217 19182 16289 16263 16256 16066 16068 15857 2535 2384]
[17409 17350 17339 17343 17318 17280 17264 17255 17217 19182 16289 16263 16256 16066 16068 15857 2535 2384]
[17472 17409 17350 17339 17343 17318 17280 17264 17255 17217 19182 16289 16263 16256 16066 16068 15857 2535 2384]
[17555 17472 17409 17350 17339 17343 17318 17280 17264 17255 17217 19182 16289 16263 16256 16066 16068 15857 2535 2384]
[17667 17555 17472 17409 17350 17339 17343 17318 17280 17264 17255 17217 19182 16289 16263 16256 16066 16068 15857 2535 2384]
[20185 17667 17555 17472 17409 17350 17339 17343 17318 17280 17264 17255 17217 19182 16289 16263 16256 16066 16068 15857 2535 2384]
'AXA'
│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─ 'AXA'
Кажется, мне нужно отслеживать значения массива child и определять, какие из них сигнализируют об имени таблицы, имени столбца, JOIN и т. д.
Неужели использование Antlr должно быть таким сложным?
Есть ли способ «запросить» древовидную структуру для определенных узлов, и если да, то какой запрос для получения этой конкретной информации?
Есть ли способ распечатать уникальные типы узлов, чтобы мы могли понять, какие из них искать?
@ kaby76 Python используется потому, что в системе Linux его удобнее настраивать и использовать. Кроме того, я проделал большую работу, пытаясь настроить и запустить компоненты Pythion Antlr4, я бы не хотел повторять это. У меня нет явных предпочтений в использовании посетителей — мои исследования привели меня к выводу, что вариант «Посетитель/Прослушиватель» будет самым простым способом. Полагаю, что с C# я мог бы использовать dotNet для Linux. Любые практические предложения и помощь будут горячо оценены.
@ kaby76 также добавлю: мне удалось написать сценарий Python, который сканирует весь код PLSQL и извлекает каждую функцию/процедуру, а также любые функции/процедуры, которые они вызывают, в файл JSON. Я закончил это тем, что получил плоский токенизированный источник в виде одной строки чисел для токенов и имен (например, в вопросе), а затем какой-то очень уродливый re.sub, чтобы свести его к необходимым данным. Это медленно - обработка 400 файлов заняла 40 минут). Так что можно рассмотреть что-нибудь более быстрое.
Цель Python3 работает очень медленно, поскольку грамматика plsql неоднозначна. Цель CSharp будет примерно в 8 раз быстрее, немного быстрее. Будет ли что-то подобное работать? $ trparse -i "SELECT ta.col1, tb.col5 FROM mytabA ta JOIN mayTabB tb ON ta.col1 = tb.col2 WHERE ta.col3 = 'AXA';" | trxgrep ' //join_clause' | trtext => JOIN mayTabB tb ON ta.col1 = tb.col2
@ kaby76 Я готов попробовать, да.
Вот лучший способ распечатать дерево разбора на консоли: gist.github.com/bkiers/13f72ef15d8353814cc7cbb93e9cc742
@BartKiers Спасибо. Это фантастическая помощь. Я все еще пытаюсь понять, как можно «запросить» такую структуру, чтобы легко выбрать, например, имена таблиц или имена столбцов из SQL.






Вот краткая демонстрация того, как вы можете использовать прослушиватель в Python для «прослушивания», когда парсер вводит правило синтаксического анализатора tableview_name:
import antlr4
from PlSqlLexer import PlSqlLexer
from PlSqlParser import PlSqlParser
from antlr_utils import to_string_tree # from: https://gist.github.com/bkiers/13f72ef15d8353814cc7cbb93e9cc742
from PlSqlParserListener import PlSqlParserListener
class TableViewListener(PlSqlParserListener):
# (part of the) parse tree:
#
# ║ ║ ║ ║ ╚═ tableview_name
# ║ ║ ║ ║ ╚═ identifier
# ║ ║ ║ ║ ╚═ id_expression
# ║ ║ ║ ║ ╚═ regular_id
# ║ ║ ║ ║ ╚═ "mytabA" (REGULAR_ID)
#
# ANTLR parser rule for `tableview_name`:
#
# tableview_name
# : identifier ('.' id_expression)? (
# AT_SIGN link_name
# | partition_extension_clause
# )?
# | xmltable outer_join_sign?
# ;
def enterTableview_name(self, ctx:PlSqlParser.Tableview_nameContext):
print('Found a table:', ctx.getText())
if __name__ == '__main__':
sql = """
SELECT ta.col1, tb.col5
FROM mytabA ta
JOIN mayTabB tb ON ta.col1 = tb.col2
WHERE ta.col3 = 'AXA';
"""
lexer = PlSqlLexer(antlr4.InputStream(sql))
parser = PlSqlParser(antlr4.CommonTokenStream(lexer))
root = parser.sql_script()
print(to_string_tree(root, lexer.symbolicNames))
antlr4.ParseTreeWalker.DEFAULT.walk(TableViewListener(), root)
Запуск приведенного выше кода Python выведет:
╚═ sql_script
╠═ unit_statement
║ ╚═ data_manipulation_language_statements
║ ╚═ select_statement
║ ╚═ select_only_statement
║ ╚═ subquery
║ ╚═ subquery_basic_elements
║ ╚═ query_block
║ ╠═ "SELECT" (SELECT)
║ ╠═ selected_list
║ ║ ╠═ select_list_elements
║ ║ ║ ╚═ expression
║ ║ ║ ╚═ logical_expression
║ ║ ║ ╚═ unary_logical_expression
║ ║ ║ ╚═ multiset_expression
║ ║ ║ ╚═ relational_expression
║ ║ ║ ╚═ compound_expression
║ ║ ║ ╚═ concatenation
║ ║ ║ ╚═ model_expression
║ ║ ║ ╚═ unary_expression
║ ║ ║ ╚═ atom
║ ║ ║ ╚═ general_element
║ ║ ║ ╠═ general_element
║ ║ ║ ║ ╚═ general_element_part
║ ║ ║ ║ ╚═ id_expression
║ ║ ║ ║ ╚═ regular_id
║ ║ ║ ║ ╚═ "ta" (REGULAR_ID)
║ ║ ║ ╠═ "." (PERIOD)
║ ║ ║ ╚═ general_element_part
║ ║ ║ ╚═ id_expression
║ ║ ║ ╚═ regular_id
║ ║ ║ ╚═ "col1" (REGULAR_ID)
║ ║ ╠═ "," (COMMA)
║ ║ ╚═ select_list_elements
║ ║ ╚═ expression
║ ║ ╚═ logical_expression
║ ║ ╚═ unary_logical_expression
║ ║ ╚═ multiset_expression
║ ║ ╚═ relational_expression
║ ║ ╚═ compound_expression
║ ║ ╚═ concatenation
║ ║ ╚═ model_expression
║ ║ ╚═ unary_expression
║ ║ ╚═ atom
║ ║ ╚═ general_element
║ ║ ╠═ general_element
║ ║ ║ ╚═ general_element_part
║ ║ ║ ╚═ id_expression
║ ║ ║ ╚═ regular_id
║ ║ ║ ╚═ "tb" (REGULAR_ID)
║ ║ ╠═ "." (PERIOD)
║ ║ ╚═ general_element_part
║ ║ ╚═ id_expression
║ ║ ╚═ regular_id
║ ║ ╚═ "col5" (REGULAR_ID)
║ ╠═ from_clause
║ ║ ╠═ "FROM" (FROM)
║ ║ ╚═ table_ref_list
║ ║ ╚═ table_ref
║ ║ ╠═ table_ref_aux
║ ║ ║ ╠═ table_ref_aux_internal_one
║ ║ ║ ║ ╚═ dml_table_expression_clause
║ ║ ║ ║ ╚═ tableview_name
║ ║ ║ ║ ╚═ identifier
║ ║ ║ ║ ╚═ id_expression
║ ║ ║ ║ ╚═ regular_id
║ ║ ║ ║ ╚═ "mytabA" (REGULAR_ID)
║ ║ ║ ╚═ table_alias
║ ║ ║ ╚═ identifier
║ ║ ║ ╚═ id_expression
║ ║ ║ ╚═ regular_id
║ ║ ║ ╚═ "ta" (REGULAR_ID)
║ ║ ╚═ join_clause
║ ║ ╠═ "JOIN" (JOIN)
║ ║ ╠═ table_ref_aux
║ ║ ║ ╠═ table_ref_aux_internal_one
║ ║ ║ ║ ╚═ dml_table_expression_clause
║ ║ ║ ║ ╚═ tableview_name
║ ║ ║ ║ ╚═ identifier
║ ║ ║ ║ ╚═ id_expression
║ ║ ║ ║ ╚═ regular_id
║ ║ ║ ║ ╚═ "mayTabB" (REGULAR_ID)
║ ║ ║ ╚═ table_alias
║ ║ ║ ╚═ identifier
║ ║ ║ ╚═ id_expression
║ ║ ║ ╚═ regular_id
║ ║ ║ ╚═ "tb" (REGULAR_ID)
║ ║ ╚═ join_on_part
║ ║ ╠═ "ON" (ON)
║ ║ ╚═ condition
║ ║ ╚═ expression
║ ║ ╚═ logical_expression
║ ║ ╚═ unary_logical_expression
║ ║ ╚═ multiset_expression
║ ║ ╚═ relational_expression
║ ║ ╠═ relational_expression
║ ║ ║ ╚═ compound_expression
║ ║ ║ ╚═ concatenation
║ ║ ║ ╚═ model_expression
║ ║ ║ ╚═ unary_expression
║ ║ ║ ╚═ atom
║ ║ ║ ╚═ general_element
║ ║ ║ ╠═ general_element
║ ║ ║ ║ ╚═ general_element_part
║ ║ ║ ║ ╚═ id_expression
║ ║ ║ ║ ╚═ regular_id
║ ║ ║ ║ ╚═ "ta" (REGULAR_ID)
║ ║ ║ ╠═ "." (PERIOD)
║ ║ ║ ╚═ general_element_part
║ ║ ║ ╚═ id_expression
║ ║ ║ ╚═ regular_id
║ ║ ║ ╚═ "col1" (REGULAR_ID)
║ ║ ╠═ relational_operator
║ ║ ║ ╚═ " = " (EQUALS_OP)
║ ║ ╚═ relational_expression
║ ║ ╚═ compound_expression
║ ║ ╚═ concatenation
║ ║ ╚═ model_expression
║ ║ ╚═ unary_expression
║ ║ ╚═ atom
║ ║ ╚═ general_element
║ ║ ╠═ general_element
║ ║ ║ ╚═ general_element_part
║ ║ ║ ╚═ id_expression
║ ║ ║ ╚═ regular_id
║ ║ ║ ╚═ "tb" (REGULAR_ID)
║ ║ ╠═ "." (PERIOD)
║ ║ ╚═ general_element_part
║ ║ ╚═ id_expression
║ ║ ╚═ regular_id
║ ║ ╚═ "col2" (REGULAR_ID)
║ ╚═ where_clause
║ ╠═ "WHERE" (WHERE)
║ ╚═ condition
║ ╚═ expression
║ ╚═ logical_expression
║ ╚═ unary_logical_expression
║ ╚═ multiset_expression
║ ╚═ relational_expression
║ ╠═ relational_expression
║ ║ ╚═ compound_expression
║ ║ ╚═ concatenation
║ ║ ╚═ model_expression
║ ║ ╚═ unary_expression
║ ║ ╚═ atom
║ ║ ╚═ general_element
║ ║ ╠═ general_element
║ ║ ║ ╚═ general_element_part
║ ║ ║ ╚═ id_expression
║ ║ ║ ╚═ regular_id
║ ║ ║ ╚═ "ta" (REGULAR_ID)
║ ║ ╠═ "." (PERIOD)
║ ║ ╚═ general_element_part
║ ║ ╚═ id_expression
║ ║ ╚═ regular_id
║ ║ ╚═ "col3" (REGULAR_ID)
║ ╠═ relational_operator
║ ║ ╚═ " = " (EQUALS_OP)
║ ╚═ relational_expression
║ ╚═ compound_expression
║ ╚═ concatenation
║ ╚═ model_expression
║ ╚═ unary_expression
║ ╚═ atom
║ ╚═ constant
║ ╚═ quoted_string
║ ╚═ "'AXA'" (CHAR_STRING)
╠═ ";" (SEMICOLON)
╚═ "<EOF>"
Found a table: mytabA
Found a table: mayTabB
Обратите внимание на последние 2 строки:
Found a table: mytabA
Found a table: mayTabB
Потрясающий. Это именно то, что я хотел, и я могу использовать это для получения другой информации, которая мне нужна. Спасибо.
Существует множество способов решения проблемы извлечения условий JOIN из входных файлов PlSql. Решение, которое я предлагаю здесь, использует Antlr4 , [Dotnet] ( https://dotnet.microsoft.com/en-us/ ), grammars-v4/sql/plsql грамматику и Trash Toolkit, реализующий подход с использованием командной строки. Решение включает в себя создание программы C# для грамматики, запуск программы для создания дерева синтаксического анализа, поиск узлов дерева синтаксического анализа для условий JOIN и распечатку результатов.
Преимущество этого решения с использованием командной строки заключается в том, что вам не нужно писать драйвер и посетитель вручную. Сгенерированный код представляет собой библиотеку, которую trparse использует для анализа входных данных, а затем вывода быстрых стандартизированных деревьев синтаксического анализа, что является лингва франка набора инструментов. Парсер C# примерно на порядок быстрее, чем эквивалентный парсер Python3.
Я предполагаю, что вы используете Ubuntu Linux и Bash.
Получите предпосылки.
i) Установите Dotnet 8. См. https://learn.microsoft.com/en-us/dotnet/core/install/linux-ubuntu-install?pivots=os-linux-ubuntu-2404&tabs=dotnet8
sudo apt-get update && sudo apt-get install -y dotnet-sdk-8.0
ii) Установите Trash Tool (только необходимые инструменты). Смотрите https://github.com/kaby76/Trash
for t in trcaret trgen trglob triconv trparse trtext trwdog trxgrep trxml trxml2; do dotnet tool install -g $t; done
Клонируйте репозиторий grammars-v4 и перейдите в каталог грамматики plsql.
git clone https://github.com/antlr/grammars-v4.git
cd grammars-v4/sql/plsql
Создайте программу синтаксического анализа C# для грамматики plsql.
trgen -t CSharp
cd Generated-CSharp-full # (directory name varies)
make
Создайте входные файлы (in.sql), проанализируйте входные файлы SQL и извлеките JOIN. Вы можете исключить вывод trparse на предмет ошибок и времени, перенаправив его на stderr.
$ trparse in.sql 2> /dev/null | trxgrep ' //join_clause' | trtext
JOIN mayTabB tb ON ta.col1 = tb.col2
$ trparse -l in.sql 2> /dev/null | trxgrep ' //join_clause' | trcaret
L3: JOIN mayTabB tb ON ta.col1 = tb.col2
^
trparse может анализировать несколько входных файлов, например, trparse *.sql. trxgrep считывает деревья синтаксического анализа и запускает механизм XPath2 над деревом синтаксического анализа Antlr и выводит деревья синтаксического анализа, удовлетворяющие выражению XPath. trtext читает деревья синтаксического анализа и печатает текст, связанный с каждым узлом дерева синтаксического анализа. trcaret считывает деревья синтаксического анализа и выводит строку текста из ввода, содержащую узел дерева синтаксического анализа, с курсором (требуется добавление информации о строке в деревья синтаксического анализа через trparse). Используя XPath, можно создавать сложные запросы, связывающие разные узлы дерева с определенными значениями.
+10 Каби спасибо. Я выбрал другой ответ как предпочтительный только потому, что думаю, что он поможет мне в работе, которую я выполняю, используя Python для этих целей. Но я также рассмотрю этот инструмент trparse.
Вам нужно сделать это с помощью Python3 или это можно реализовать с помощью CSharp (гораздо быстрее)? И нужно ли вам реализовать это как посетитель Antlr или это можно реализовать с помощью программы командной строки? Вы по-прежнему можете использовать Antlr, но писать программы для извлечения данных — это старомодно.