使用 ANTLR4 解析 T-SQL 查询
Parsing a T-SQL query using ANTLR4
我目前正在开发一个 T-SQL 解析器,它将能够为我的学校项目映射数据库中的查询。到目前为止,我已经设法解析了其中的大部分内容,但我遇到了一个似乎无法解决的问题。我正在使用 C# 和 tsql.g4 语法和 ANTLR4。
如何访问表达式?我想知道我在 select 中并且我有某种表达方式,但是表达方式是什么?是否可以从 select_statement?
中仅提取列名、模式(如果有)和数据库(如果有)
每当我尝试从 c# 代码访问 expression 时:
上下文:GrammarSQLParser.Dml_clauseContext context
context.select_statement().query_expression().query_specification().select_list().select_list_elem().expression()
我只得到方法 CopyFrom(),我没有任何 full_column_name() 方法可以进一步访问 table_name() 等等..
edit1: 仔细检查后,表达式是 column_ref_expression,但如何从表达式访问它?它们是不同的对象..
这是查询:
select p.BusinessEntityID,p.FirstName,p.LastName,adresstbl.* from person.Person as p
join (select bea.BusinessEntityID, adr.AddressLine1, adr.AddressLine2, adr.City, adr.PostalCode from person.BusinessEntityAddress as bea
join person.Address as adr
on bea.AddressID = adr.AddressID )
as adresstbl
on not p.BusinessEntityID != adresstbl.BusinessEntityID order by p.BusinessEntityID
这是我的解析树:
Lisp Parse Tree: (tsql_file (batch (sql_clauses (sql_clause
(dml_clause (select_statement (query_expression (query_specification
select (select_list (select_list_elem (expression (full_column_name
(table_name (id (simple_id p))) . (id (simple_id BusinessEntityID)))))
, (select_list_elem (expression (full_column_name (table_name (id
(simple_id p))) . (id (simple_id FirstName))))) , (select_list_elem
(expression (full_column_name (table_name (id (simple_id p))) . (id
(simple_id LastName))))) , (select_list_elem (table_name (id
(simple_id adresstbl))) . *)) from (table_sources (table_source
(table_source_item_joined (table_source_item (table_name_with_hint
(table_name (id (simple_id person)) . (id (simple_id Person))))
(as_table_alias as (table_alias (id (simple_id p))))) (join_part join
(table_source (table_source_item_joined (table_source_item
(derived_table (subquery (select_statement (query_expression (
(query_expression (query_specification select (select_list
(select_list_elem (expression (full_column_name (table_name (id
(simple_id bea))) . (id (simple_id BusinessEntityID))))) ,
(select_list_elem (expression (full_column_name (table_name (id
(simple_id adr))) . (id (simple_id AddressLine1))))) ,
(select_list_elem (expression (full_column_name (table_name (id
(simple_id adr))) . (id (simple_id AddressLine2))))) ,
(select_list_elem (expression (full_column_name (table_name (id
(simple_id adr))) . (id (simple_id City))))) , (select_list_elem
(expression (full_column_name (table_name (id (simple_id adr))) . (id
(simple_id PostalCode)))))) from (table_sources (table_source
(table_source_item_joined (table_source_item (table_name_with_hint
(table_name (id (simple_id person)) . (id (simple_id
BusinessEntityAddress)))) (as_table_alias as (table_alias (id
(simple_id bea))))) (join_part join (table_source
(table_source_item_joined (table_source_item (table_name_with_hint
(table_name (id (simple_id person)) . (id (simple_id Address))))
(as_table_alias as (table_alias (id (simple_id adr))))))) on
(search_condition (search_condition_and (search_condition_not
(predicate (expression (full_column_name (table_name (id (simple_id
bea))) . (id (simple_id AddressID)))) (comparison_operator =)
(expression (full_column_name (table_name (id (simple_id adr))) . (id
(simple_id AddressID)))))))))))))) ))))) (as_table_alias as
(table_alias (id (simple_id adresstbl))))))) on (search_condition
(search_condition_and (search_condition_not not (predicate (expression
(full_column_name (table_name (id (simple_id p))) . (id (simple_id
BusinessEntityID)))) (comparison_operator ! =) (expression
(full_column_name (table_name (id (simple_id adresstbl))) . (id
(simple_id BusinessEntityID)))))))))))))) (order_by_clause order by
(order_by_expression (expression (full_column_name (table_name (id
(simple_id p))) . (id (simple_id BusinessEntityID))))))))))) )
expression
可能是许多事情之一。如果你看语法,你会看到
expression
: DEFAULT #primitive_expression
| NULL #primitive_expression
| LOCAL_ID #primitive_expression
| constant #primitive_expression
| function_call #function_call_expression
| expression COLLATE id #function_call_expression
| case_expr #case_expression
| full_column_name #column_ref_expression
| '(' expression ')' #bracket_expression
| '(' subquery ')' #subquery_expression
| '~' expression #unary_operator_expression
| expression op=('*' | '/' | '%') expression #binary_operator_expression
| op=('+' | '-') expression #unary_operator_expression
| expression op=('+' | '-' | '&' | '^' | '|') expression #binary_operator_expression
| expression comparison_operator expression #binary_operator_expression
;
你需要弄清楚是哪一个。在你的情况下,它是一个 column_ref_expression
,在这种情况下你需要将它转换为 Column_ref_expressionContext
然后你将能够访问 full_column_name
.
有多种方法可以确定它是哪个,或者如果您只想支持语法的有限子集,您可以假设。
我目前正在开发一个 T-SQL 解析器,它将能够为我的学校项目映射数据库中的查询。到目前为止,我已经设法解析了其中的大部分内容,但我遇到了一个似乎无法解决的问题。我正在使用 C# 和 tsql.g4 语法和 ANTLR4。
如何访问表达式?我想知道我在 select 中并且我有某种表达方式,但是表达方式是什么?是否可以从 select_statement?
中仅提取列名、模式(如果有)和数据库(如果有)每当我尝试从 c# 代码访问 expression 时:
上下文:GrammarSQLParser.Dml_clauseContext context
context.select_statement().query_expression().query_specification().select_list().select_list_elem().expression()
我只得到方法 CopyFrom(),我没有任何 full_column_name() 方法可以进一步访问 table_name() 等等..
edit1: 仔细检查后,表达式是 column_ref_expression,但如何从表达式访问它?它们是不同的对象..
这是查询:
select p.BusinessEntityID,p.FirstName,p.LastName,adresstbl.* from person.Person as p
join (select bea.BusinessEntityID, adr.AddressLine1, adr.AddressLine2, adr.City, adr.PostalCode from person.BusinessEntityAddress as bea
join person.Address as adr
on bea.AddressID = adr.AddressID )
as adresstbl
on not p.BusinessEntityID != adresstbl.BusinessEntityID order by p.BusinessEntityID
这是我的解析树:
Lisp Parse Tree: (tsql_file (batch (sql_clauses (sql_clause (dml_clause (select_statement (query_expression (query_specification select (select_list (select_list_elem (expression (full_column_name (table_name (id (simple_id p))) . (id (simple_id BusinessEntityID))))) , (select_list_elem (expression (full_column_name (table_name (id (simple_id p))) . (id (simple_id FirstName))))) , (select_list_elem (expression (full_column_name (table_name (id (simple_id p))) . (id (simple_id LastName))))) , (select_list_elem (table_name (id (simple_id adresstbl))) . *)) from (table_sources (table_source (table_source_item_joined (table_source_item (table_name_with_hint (table_name (id (simple_id person)) . (id (simple_id Person)))) (as_table_alias as (table_alias (id (simple_id p))))) (join_part join (table_source (table_source_item_joined (table_source_item (derived_table (subquery (select_statement (query_expression ( (query_expression (query_specification select (select_list (select_list_elem (expression (full_column_name (table_name (id (simple_id bea))) . (id (simple_id BusinessEntityID))))) , (select_list_elem (expression (full_column_name (table_name (id (simple_id adr))) . (id (simple_id AddressLine1))))) , (select_list_elem (expression (full_column_name (table_name (id (simple_id adr))) . (id (simple_id AddressLine2))))) , (select_list_elem (expression (full_column_name (table_name (id (simple_id adr))) . (id (simple_id City))))) , (select_list_elem (expression (full_column_name (table_name (id (simple_id adr))) . (id (simple_id PostalCode)))))) from (table_sources (table_source (table_source_item_joined (table_source_item (table_name_with_hint (table_name (id (simple_id person)) . (id (simple_id BusinessEntityAddress)))) (as_table_alias as (table_alias (id (simple_id bea))))) (join_part join (table_source (table_source_item_joined (table_source_item (table_name_with_hint (table_name (id (simple_id person)) . (id (simple_id Address)))) (as_table_alias as (table_alias (id (simple_id adr))))))) on (search_condition (search_condition_and (search_condition_not (predicate (expression (full_column_name (table_name (id (simple_id bea))) . (id (simple_id AddressID)))) (comparison_operator =) (expression (full_column_name (table_name (id (simple_id adr))) . (id (simple_id AddressID)))))))))))))) ))))) (as_table_alias as (table_alias (id (simple_id adresstbl))))))) on (search_condition (search_condition_and (search_condition_not not (predicate (expression (full_column_name (table_name (id (simple_id p))) . (id (simple_id BusinessEntityID)))) (comparison_operator ! =) (expression (full_column_name (table_name (id (simple_id adresstbl))) . (id (simple_id BusinessEntityID)))))))))))))) (order_by_clause order by (order_by_expression (expression (full_column_name (table_name (id (simple_id p))) . (id (simple_id BusinessEntityID))))))))))) )
expression
可能是许多事情之一。如果你看语法,你会看到
expression
: DEFAULT #primitive_expression
| NULL #primitive_expression
| LOCAL_ID #primitive_expression
| constant #primitive_expression
| function_call #function_call_expression
| expression COLLATE id #function_call_expression
| case_expr #case_expression
| full_column_name #column_ref_expression
| '(' expression ')' #bracket_expression
| '(' subquery ')' #subquery_expression
| '~' expression #unary_operator_expression
| expression op=('*' | '/' | '%') expression #binary_operator_expression
| op=('+' | '-') expression #unary_operator_expression
| expression op=('+' | '-' | '&' | '^' | '|') expression #binary_operator_expression
| expression comparison_operator expression #binary_operator_expression
;
你需要弄清楚是哪一个。在你的情况下,它是一个 column_ref_expression
,在这种情况下你需要将它转换为 Column_ref_expressionContext
然后你将能够访问 full_column_name
.
有多种方法可以确定它是哪个,或者如果您只想支持语法的有限子集,您可以假设。