2017-11-27 9 views
0

내가 select_parser.py from pyparsing을,이 코드를 사용하여 2.2.0 대한 파싱과 실행 : 원래 정의의 이름 첨부 요소 "테이블"이 있지만pyparsing에서 select_parser.py를 사용하여 SQL에서 테이블 이름을 가져 오는 방법은 무엇입니까?

query="select z.a, b from test_table left join test2_table where 1=1 and b in (select bb from foo)" 
for key, val in select_stmt.parseString(query, parseAll=True).items(): 
    print "%s: %s" % (key, val) 

내가

$ python select_parser.pyparsing.py 
where_expr: [['1', '=', '1'], 'AND', ['b', 'IN', ['SELECT', [['bb']], 'FROM', 'foo']]] 
from: [['test_table', ['LEFT', 'JOIN'], 'test2_table', []]] 
columns: [['z.a'], ['b']] 

수를 :

single_source = ((Group(database_name("database") + "." + table_name("table*")) | table_name("table*")) + 

"table"이라는 이름으로 나오는 dict 키가 없습니다.

아마도 "from"요소가 먼저 소비 한 것입니까? 명명 된 요소가 채워지는 정확한 논리를 이해할 수 없으며 문서를 읽지 않아도 명확한 아이디어를 얻지 못했습니다 (여러 회담 등).

select_parser.py를 사용하여 SQL 쿼리의 모든 테이블 이름을 가져 오는 방법은 무엇입니까?

참고 : 올바른 대답은 목록 (또는 집합)입니다 : test_table, test2_table, foo.

필자는 "from"과 도랑 목록을 통과 할 수는 있지만 해킹 된 것처럼 보일 수 있습니다. 작동 여부는 알 수 없으며, pyparsing이 어떻게 작동하는지 생각하지 않습니다.

나는 this question, this onethis one을 볼 수 있지만 어떻게 도움이되는지 이해하지 못합니다.

답변

1

연결된 샘플 코드에는 runTests에 대한 호출이 포함됩니다. 이것은 다른 테스트 문자열을 시도하고 파서의 단위 테스트를 작성하는 훌륭한 도구입니다. , 그러나 당신이 구조의 일부 탐색을해야 할 것이다

select z.a, b from test_table left join test2_table where 1=1 and b in (select bb from foo) 
['SELECT', [['z.a'], ['b']], 'FROM', ['test_table', ['LEFT', 'JOIN'], 'test2_table', []], 'WHERE', [['1', '=', '1'], 'AND', ['b', 'IN', ['SELECT', [['bb']], 'FROM', 'foo']]]] 
- columns: [['z.a'], ['b']] 
    [0]: 
    ['z.a'] 
    [1]: 
    ['b'] 
- from: [['test_table', ['LEFT', 'JOIN'], 'test2_table', []]] 
    [0]: 
    ['test_table', ['LEFT', 'JOIN'], 'test2_table', []] 
    - table: [['test_table'], ['test2_table']] 
     [0]: 
     ['test_table'] 
     [1]: 
     ['test2_table'] 
- where_expr: [['1', '=', '1'], 'AND', ['b', 'IN', ['SELECT', [['bb']], 'FROM', 'foo']]] 
    [0]: 
    ['1', '=', '1'] 
    [1]: 
    AND 
    [2]: 
    ['b', 'IN', ['SELECT', [['bb']], 'FROM', 'foo']] 
    [0]: 
     b 
    [1]: 
     IN 
    [2]: 
     ['SELECT', [['bb']], 'FROM', 'foo'] 
     - columns: [['bb']] 
     [0]: 
      ['bb'] 
     - from: ['foo'] 
     - table: [['foo']] 
     [0]: 
      ['foo'] 

'테이블'이름 :

runTests에 대한 호출에 쿼리 문자열을 삽입, 우리는이 출력을 얻을 그들에게 다가 가라.

result = select_stmt.parseString(query) 
table_names = [] 
def visit_structure(struct): 
    if 'table' in struct: 
     table_names.extend(t[0] for t in struct.table) 
    for substruct in struct: 
     if isinstance(substruct, ParseResults): 
      visit_structure(substruct) 

visit_structure(result) 
print(table_names) 

가 제공합니다 : 귀하의 구문 분석 데이터의 미래 목록은

['test_table', 'test2_table', 'foo'] 

ParserElement.runTestsParseResults.dump 방법을 활용 여기에 한 가지 방법입니다.

+0

고마워요! 나는 runTests와 dump와 그 출력을 보았습니다. 그러나 1) struct.table 형식에 대해 몰랐습니다. 2) 트리를 가로 지르는 패러다임을 알지 못했습니다. – dfrankow

+0

명명 된 결과 필드는'result [ "name"]'dict-key 표기법 또는'result.name' 객체 - 속성 표기법을 사용하여 액세스 할 수 있습니다 (dict 표기법은 이름 표기가없는 경우 KeyError를 발생시키고 속성 표기법은 반환합니다 ''). 자세한 내용은 온라인 문서 (https://pythonhosted.org/pyparsing/pyparsing.ParseResults-class.html)를 참조하십시오. 트리를 탐색하는 것과 마찬가지로, 이것은'parseString'에서 반환 된 중첩 된 구문 분석 데이터를 걷는 것입니다. subexpressions은'Group's의 pyparsing에 래핑되므로, 파싱 된 결과에서 하부 구조를 얻습니다. – PaulMcG