Парсер для Oracle SQL - PullRequest
       44

Парсер для Oracle SQL

18 голосов
/ 20 апреля 2011

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

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

Best, Will

Ответы [ 7 ]

10 голосов
/ 21 апреля 2011

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

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

После работы над той же проблемой мне удалось заставить работать синтаксический анализатор 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");

Задачи, чтобы заставить это работать:

  • Получение OracleSQL 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 (якобы причина была в том, что это очень ценная технология, которая не будет продаваться или лицензироваться).
  • Хотя это скорее взлом, чем решение, я понял, что это может бытьполезно для некоторых случаев (не для меня). Я считаю, что использование его в реальных сценариях может быть очень рискованным с технической и юридической точек зрения.

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

4 голосов
/ 21 апреля 2011

Будет, почему бы не использовать парсер 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 невообразимых размеров.

4 голосов
/ 21 апреля 2011

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

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

4 голосов
/ 21 апреля 2011

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

2 голосов
/ 21 апреля 2011

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

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

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

1 голос
/ 09 июля 2011

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

...