Парсер для Oracle SQL

Для моего текущего проекта мне нужен парсер SQL, который анализирует операторы Oracle SQL. В настоящее время я использую jsqlparser, который хорошо работал для простых запросов. Но когда возникают определенные функции (например, cast() или (+)), синтаксический анализатор выходит из строя.

Может ли кто-нибудь предложить парсер, полностью совместимый с Oracle SQL?

Бест, Будет ли

Ответы

Ответ 1

Рассматривали ли вы Общий SQL Parser? У меня нет опыта с ним, но просмотр их веб-сайта у него есть потенциал. Лично я развернул свой собственный, построенный на парсере в Eclipse Data Tools Platform (извините, что не могу поделиться, это проприетарный), но теперь мне придется оценить тот, который я связал выше, потому что он утверждает, что имеет больше возможностей для покрытия Oracle SQL, чем мой парсер делает.

Ответ 2

ANTLR (v3, v4) генератор парсера для него было написано несколько грамматик Oracle SQL и PL/SQL; см. список грамматики (v3). Из них:

  • Я использовал Андрея Харитонкина "Oracle PL/SQL Grammar для ANTLR v3"; из памяти он поддерживал большинство синтаксиса SQL и PL/SQL с эпохи 8i, с несколькими битами и частями, появившимися в 9i и 10g
  • Глоссарий "PL/SQL" Патрика Хиггинса является новее и утверждает, что поддерживает большинство синтаксиса 11g, но он просто проглатывает большинство операторов DML - не слишком полезен, если вас особенно интересует SQL

Ответ 3

После выполнения той же самой проблемы мне удалось заставить работать SQL-парсер:

Мой код выглядит следующим образом:

import oracle.jdeveloper.db.DatabaseConnections;
import oracle.javatools.db.sql.SQLQueryBuilder;
import oracle.javatools.db.Database;
...
// load the database connections
// this is specific to Oracle SQL developer
DatabaseConnections connections = DatabaseConnections.getPrivateInstance(
    (new File("src/test/resources/connection.xml")).toURI().toURL(),
    "somePassword");
// get the one we are interested in
Database database = connections.getDatabase("the-name-of-a-sqldeveloper-connection");
SQLQueryBuilder queryBuilder = SQLQueryBuilderFactory.createBuilder(
      database, new Schema("OPTIONAL_SCHEMA"), "select * from some_table");

Задачами, необходимыми для получения этой работы, являются:

  • Получение Oracle SQL Developer является проблемой. Для этого вам необходимо взломать файлы, созданные Oracle SQL Developer, для сохранения этих соединений; файл connection.xml в приведенном выше примере выглядит примерно так:
<?xml version = '1.0' encoding = 'UTF-8'?>
<References xmlns="http://xmlns.oracle.com/adf/jndi">
   <Reference name="the-name-of-a-sqldeveloper-connection"     className="oracle.jdeveloper.db.adapter.DatabaseProvider" xmlns="">
      <Factory      className="oracle.jdevimpl.db.adapter.DatabaseProviderFactory1212"/>
  <RefAddresses>
     <StringRefAddr addrType="password">
        <Contents>HSx10FtlsPc=</Contents>
     </StringRefAddr>
     <StringRefAddr addrType="oraDriverType">
        <Contents>thin</Contents>
     </StringRefAddr>
...

Чтобы получить такой файл, вам нужно будет вставить его в папку, где хранятся настройки Oracle SQL Developer, и просто скопировать-вставить этот контент в ваш собственный файл.

  • Следующая задача - определить пароль базы данных. Это зашифровано, но этот пост (https://community.oracle.com/message/12359081) должен быть очень полезным - просто проверьте ответ в конце сообщения.

Теперь, предполагая, что вам удалось зайти так далеко, проблемы и моменты, когда я разочарован конечным решением:

  • API в построителе подходит, но синтаксический анализ будет выполнять выполнение запроса (и это может быть большой проблемой - в моем случае мне нужно, чтобы синтаксический анализ был быстрым).
  • API официально не опубликован. Не имея возможности привести здесь точную формулировку, я получил ответ Oracle, в котором говорилось, что официально не поддерживается Oracle parser (причина была в том, что это очень ценная технология, которая не будет продана или лицензирована).
  • Хотя это скорее хак, чем решение, я понял, что он может быть полезен для некоторых случаев (не мой). Я считаю, что использование его в реальных сценариях может быть очень рискованным как с технической, так и с правовой точки зрения.

Причина, по которой я опубликовал этот ответ, - привлечь внимание сообщества к тому факту, что наличие сильного анализатора Oracle SQL вполне возможно, и, возможно, однажды Oracle рассмотрит возможность разоблачения синтаксического анализа как конкурентного преимущества (я конечно, есть пользователи, которые с радостью заплатили бы некоторые сборы за получение лицензии).

Ответ 4

Учитывая, что Oracle Corporation не смогла синхронизировать парсер SQL для SQL и PL/SQL VM, если у них были разные синтаксические анализаторы SQL, маловероятно, что третья сторона сможет создать "полностью совместимый" парсер.

Какие данные вы пытаетесь извлечь из запроса? Сама база данных Oracle может иметь другие возможности, которые позволят вам извлечь эту информацию без предварительного разбора запроса.

Ответ 5

Будет ли, почему бы не использовать парсер Oracle?

create global temporary table plans as select * from table(dbms_xplan.display_cursor());
--/
declare
c number;
i varchar2(30);
l number;
stmt varchar2(4000);
begin
delete from plans;
stmt:= 'select z.* from z,skew1 where z.z = skew1.fillblocks';
l:= length(stmt);
c:=dbms_sql.open_cursor();
dbms_sql.parse (c, stmt,dbms_sql.native);
select distinct sql_id into i from v$open_cursor where sid in (select sid from v$mystat) and substr(sql_text,1,l) = substr(stmt,1,l);
insert into plans select * from table(dbms_xplan.display_cursor(i));
dbms_output.put_Line ('sql_id:'||i);
end;
/
select * from plans;

PLAN_TABLE_OUTPUT                                                             
----------------------------------------------------------------------------  
SQL_ID  97qc3ynmw1pa4, child number 0                                         
-------------------------------------                                         
select z.* from z,skew1 where z.z = skew1.fillblocks                          

Plan hash value: 942457544                                                    

----------------------------------------------------------------------------  
| Id  | Operation          | Name  | Rows  | Bytes | Cost (%CPU)| Time     |  
----------------------------------------------------------------------------  
|   0 | SELECT STATEMENT   |       |       |       |    85 (100)|          |  
|*  1 |  HASH JOIN         |       |     1 |   410 |    85   (2)| 00:00:02 |  
|   2 |   TABLE ACCESS FULL| Z     |     1 |     9 |     2   (0)| 00:00:01 |  
|   3 |   TABLE ACCESS FULL| SKEW1 |  6000 |  2349K|    82   (0)| 00:00:01 |  
----------------------------------------------------------------------------  

Predicate Information (identified by operation id):                           
---------------------------------------------------                           

   1 - access("Z"."Z"=INTERNAL_FUNCTION("SKEW1"."FILLBLOCKS"))   

Вам нужно соединение с базой данных оракула. Если выход - это то, что вы хотите, это самый простой способ получить то, что вы хотите, без повторного изобретения другого цвета для колеса. В этом примере я ограничил sql до 4000 символов, но вы могли бы подавать массив pl/sql varchar2 в функцию dbms_sql.parse, поэтому вы можете анализировать sql невообразимых размеров.

Ответ 6

Наш DMS Software Reengineering Toolkit можно получить с помощью парсера Oracle PLSQL или анализатора SQL 2011. DMS предоставляет синтаксический анализатор, строит AST, позволяет вам произвольно исследовать/преобразовывать дерево и восстанавливать AST как исходный код, если вы хотите это сделать.

Вы можете протестировать парсер, загрузив формат PLSQL, доступный с веб-сайта; который использует один и тот же базовый механизм DMS; просто не анализирует/не преобразует дерево.

Возможно, вам придется обернуть SQL-запросы в простой процедуре PLSQL.

Ответ 7

Попробуйте http://www.ibrezina.net/OracleSQL.tgz. Это ANTLR3.3 грамматика для Oracle PL/SQL. Грамматика предназначена для цели C, но может быть легко преобразована в Java или С#. В качестве примера уже включена ваша задача, список таблиц, включенных в запрос.