Разбор таблиц и имен столбцов из SQL/HQL Java

Я ищу API с открытым исходным кодом в Java для анализа запроса SQL / HQL, чтобы он давал мне имена столбцов и имена таблиц, используемые в нем. Я попытался использовать JSQLParser, который дает мне имена таблиц, используемых в запросе. Но я не вижу поддержки для получения имен столбцов, используемых в запросе. Есть ли другой API, который может помочь мне с этим? Я знаю о парсере General SQL, но он кажется платным.

Вот фрагмент кода с использованием JSQLParser, который дает мне имена таблиц в запросе:

Statement statement;
    try
    {
        statement = CCJSqlParserUtil.parse( " SELECT * FROM  ( ( SELECT TBL.ID AS rRowId, TBL.NAME AS name, TBL.DESCRIPTION as description, TBL.TYPE AS type, TBL1.SHORT_NAME AS shortName  FROM ROLE_TBL TBL WHERE ( TBL.TYPE = 'CORE' OR  TBL1.SHORT_NAME = 'TNG' AND  TBL.IS_DELETED <> 1  ) ) MINUS ( SELECT TBL.ID AS rRowId, TBL.NAME AS name, TBL.DESCRIPTION as description, TBL.TYPE AS type, TBL3.SHORT_NAME AS shortName,TBL3.NAME AS tenantName FROM ROLE_TBL TBL INNER JOIN TYPE_ROLE_TBL TBL1 ON TBL.ID=TBL1.ROLE_FK LEFT OUTER JOIN TNT_TBL TBL3 ON TBL3.ID = TBL.TENANT_FK LEFT OUTER JOIN USER_TBL TBL4 ON TBL4.ID = TBL1.USER_FK WHERE ( TBL4.ID =771100 AND  TBL.IS_DELETED <> 1  ) ) ) ORDER BY name ASC" );
        Select selectStatement = (Select) statement;
        TablesNamesFinder tablesNamesFinder = new TablesNamesFinder();
        List<String> tableList = tablesNamesFinder.getTableList( selectStatement );
        System.out.println( tableList.size() );
        for( String s : tableList )
            System.out.println( s );
    }
    catch( JSQLParserException e )
    {
        e.printStackTrace();
    }

Заранее спасибо за любую помощь в этом отношении.

1 ответ

Решение

Есть несколько способов добиться этого с помощью JSqlParser ( https://github.com/JSQLParser/JSqlParser):

  1. Вы также можете перевернуть TableNamesFinder, чтобы обойти все столбцы. Как вы могли видеть в списке результатов, TableNamesFinder не пересекает все вхождения столбцов, потому что в этом нет необходимости. Таким образом, здесь также необходимо завершить реализацию обхода, чего я не сделал.

  2. Вы можете использовать функцию JSqlParser AST - Node, чтобы получить все столбцы. Для конкретных производств JSqlParser создает узлы для дерева разбора. Колонна является одним из них.

Для завершения реализации необходимо собрать все столбцы и сделать этот список отдельным (регистр, таблица и т. Д.)

String sql = "SELECT * FROM  ( ( SELECT TBL.ID AS rRowId, TBL.NAME AS name, TBL.DESCRIPTION as description, TBL.TYPE AS type, TBL1.SHORT_NAME AS shortName  FROM ROLE_TBL TBL WHERE ( TBL.TYPE = 'CORE' OR  TBL1.SHORT_NAME = 'TNG' AND  TBL.IS_DELETED <> 1  ) ) MINUS ( SELECT TBL.ID AS rRowId, TBL.NAME AS name, TBL.DESCRIPTION as description, TBL.TYPE AS type, TBL3.SHORT_NAME AS shortName,TBL3.NAME AS tenantName FROM ROLE_TBL TBL INNER JOIN TYPE_ROLE_TBL TBL1 ON TBL.ID=TBL1.ROLE_FK LEFT OUTER JOIN TNT_TBL TBL3 ON TBL3.ID = TBL.TENANT_FK LEFT OUTER JOIN USER_TBL TBL4 ON TBL4.ID = TBL1.USER_FK WHERE ( TBL4.ID =771100 AND  TBL.IS_DELETED <> 1  ) ) ) ORDER BY name ASC";

    System.out.println("using TableNamesFinder to get column names");
    Statement statement = CCJSqlParserUtil.parse(sql);
    Select selectStatement = (Select) statement;
    TablesNamesFinder tablesNamesFinder = new TablesNamesFinder() {
        @Override
        public void visit(Column tableColumn) {
            System.out.println(tableColumn);
        }
    };
    tablesNamesFinder.getTableList(selectStatement);

    System.out.println("-------------------------------------------");
    System.out.println("using ast nodes to get column names");
    SimpleNode node = (SimpleNode) CCJSqlParserUtil.parseAST(sql);

    node.jjtAccept(new CCJSqlParserDefaultVisitor() {
        @Override
        public Object visit(SimpleNode node, Object data) {
            if (node.getId() == CCJSqlParserTreeConstants.JJTCOLUMN) {
                System.out.println(node.jjtGetValue());
                return super.visit(node, data);
            } else {
                return super.visit(node, data);
            }
        }
    }, null);

Нужно иметь в виду, что JSqlParser - только парсер. Поэтому невозможно получить имя таблицы столбцов, не указав его, как в (table.column). Чтобы получить это право, схема базы данных должна быть доступна. Это становится ясно, если вы посмотрите на:

select a from table1, table2

который является действительным SQL.

Другие вопросы по тегам