使用ANTLR4解析MySQL的简单示例

3
我正在使用来自此处的mysql语法:https://github.com/antlr/grammars-v4/tree/master/mysql,并使用Maven生成了Java文件。现在,我正在尝试解析查询,但我不知道该如何做。
我基本上想要“获取”查询的所有不同组件,例如所选的列列表、where条件、子查询、表名等等。但我不知道该如何继续。目前为止,我已经编写了以下代码。请问是否能提供一个简单的示例,以便我可以理解用法并承担更复杂的任务?这是我的代码:
public static void main( String[] args )
{
    String sql="select cust_name from database..table where cust_name like 'Kash%'";
    ANTLRInputStream input = new ANTLRInputStream(sql);
    MySqlLexer mySqlLexer = new MySqlLexer(input);
    CommonTokenStream tokens = new CommonTokenStream(mySqlLexer);
    MySqlParser mySqlParser = new MySqlParser(tokens);

    ParseTree tree = mySqlParser.dmlStatement();
    ParseTreeWalker walker = new ParseTreeWalker();
    MySqlParserBaseListener listener=new MySqlParserBaseListener();
    ParseTreeWalker.DEFAULT.walk(listener, tree);


    System.out.println(?);
}  

使用上述代码,我得到了以下输出结果:
line 1:11 no viable alternative at input '_'
(dmlStatement _ . . _ 'Kash%')

感谢您的帮助 :)

1
该语法相当有缺陷。不要期望它能解析所有可能的MySQL输入。 - Mike Lischke
1个回答

3
我基本上想要“获取”查询中的所有不同组件,如所选列的列表、where条件、子查询、表名等等。
您的“tree”变量保存了所有这些数据:ParseTree tree = mySqlParser.dmlStatement(); “第1行:11个字符的无法接受的输入”的错误提示信息。
如果您查看词法分析器规则:
SELECT:                              'SELECT';

ID:                                  ID_LITERAL;

fragment ID_LITERAL:                 [A-Z_$0-9]*?[A-Z_$]+?[A-Z_$0-9]*;

似乎关键字和标识符中不能包含小写字母。
如果你这样运行它:
String sql = "SELECT CUST_NAME FROM CUSTOMERS WHERE CUST_NAME LIKE 'Kash%'";

MySqlLexer lexer = new MySqlLexer(CharStreams.fromString(sql));
MySqlParser parser = new MySqlParser(new CommonTokenStream(lexer));
ParseTree root = parser.dmlStatement();

System.out.println(root.toStringTree(parser));

您将看到以下输出(缩进以便更易阅读):
(dmlStatement 
  (selectStatement 
    (querySpecification SELECT 
      (selectElements 
        (selectElement 
          (fullColumnName 
            (uid 
              (simpleId CUST_NAME))))) 
      (fromClause FROM 
        (tableSources 
          (tableSource 
            (tableSourceItem 
              (tableName 
                (fullId 
                  (uid 
                    (simpleId CUSTOMERS))))))) WHERE 
        (expression 
          (predicate 
            (predicate 
              (expressionAtom 
                (fullColumnName 
                  (uid 
                    (simpleId CUST_NAME))))) LIKE 
          (predicate 
            (expressionAtom 
              (constant 
                (stringLiteral 'Kash%'))))))))))

以上代码输出如下:第1行:11处输入'_'无法识别的替代方案(dmlStatement _ . . _ 'Kash%')。 - KCK
你为什么没有在最初的问题中包含那个? - Bart Kiers
抱歉,问题被编辑了。 - KCK
我正在使用JavaScript实现,你的代码给了我Cannot read property 'replace' of undefined - Alexey Sh.
我的代码中没有使用任何 replace。如果您的代码有问题,我建议向 @AlexeySh 提出一个新的问题。 - Bart Kiers
我猜替换操作是从库中进行的。 - Alexey Sh.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接