Обработка запросов к объектному представлению реляционной базы данных (продолжение)

Транслятор языка запросов. Основная задача транслятора — преобразование запроса к объектному представлению РБД в SQL-запрос с использованием данных, хранящихся в ОСД. Для этого требуется решить следующие подзадачи:

  • заменить все присутствующие атрибуты объектов на поля таблиц;
  • сформировать список таблиц для составления раздела FROM SQL-запроса;
  • для всех связываемых таблиц в раздел WHERE добавить условия связи.

Возможны следующие варианты построения такого транслятора.

1. Выполняется полный синтаксический разбор исходного запроса на основе грамматики языка объектных запросов; в семантические процедуры, вызываемые при редуцировании правил грамматики, в которых задействованы атрибуты объектов в качестве параметров, включается вызов функции, выполняющей замену атрибутов объектов на поля таблиц и сохраняющей данные для формирования списка таблиц и связей в SQL-запросе. Эта процедура аналогична синтаксическому анализу SQL-запроса при его выполнении в СУБД. Для ее выполнения требуется полностью описанная грамматика языка запросов. Каждое правило грамматики содержит семантические процедуры, вызываемые при его редуцировании и выполняющие построение узлов дерева разбора. В случае успешного прохода всех правил грамматики в процессе создания дерева разбора и получения ее начального символа подтверждается отсутствие

синтаксических ошибок в запросе и сформированное дерево разбора передается для последующих этапов выполнения, таких как оптимизация, составление логического плана выполнения запроса и формирования множества результирующих записей. Грамматика языка объектных запросов должна полностью соответствовать грамматике языка SQL, реализованного в СУБД, за исключением правил, специфичных для объектных запросов. Несмотря на наличие автоматизированных программных средств для построения трансляторов на базе формальных грамматик [4], задача разработки, отладки и поддержки соответствия такой грамматики используемой СУБД является чрезвычайно трудоемкой. Кроме того, подобное решение приводит к зависимости транслятора от СУБД и свойственного ей диалекта языка запросов SQL.

2. Выполняется частичный разбор запроса с выделением из него только тех фрагментов, которые подлежат модификации. К ним относятся: раздел SELECT со списком выбираемых полей таблиц; раздел FROM, определяющий список таблиц, из которых производится выборка данных; раздел WHERE, накладывающий ограничения на множество записей в результирующей выборке. Порядок следования фрагментов в запросе сохраняется. Т.к. этот способ позволяет отказаться от создания анализатора, производящего полный синтаксический разбор объектного запроса, и от необходимости полного формального описания грамматики языка объектных запросов, позволяя существенно упростить разработку транслятора, то именно он будет рассмотрен далее.

Для преобразования запросов к объектному представлению РБД (OSQL-запросов) предлагается использовать частичный синтаксический разбор запроса, состоящий в последовательном выделении и модификации фрагментов исходного запроса, что позволяет сохранить его структуру и обеспечить “прозрачность” использования всех возможностей языка SQL, поддерживаемых СУБД.

SQL-запрос, а значит и запрос к объектному представлению РБД, имеет строго установленный порядок следования его компонентов, следовательно, для выделения фрагментов запроса в качестве разделителей могут быть использованы ключевые слова SELECT, WHERE, GROUP BY, HAVING, ORDER BY. Такой подход может быть успешно реализован для запросов, в составе которых нет вложенных подзапросов. Трансляция некоррелированных подзапросов выполняется независимо от внешних по отношению к ним запросов. Таким образом, для применения подхода с частичным разбором объектного запроса путем выделения фрагментов достаточно выполнить обход и трансляцию всех имеющихся подзапросов, начиная с наиболее глубоко вложенных, в направлении охватывающих их внешних запросов.

Для определения правил преобразования фрагментов OSQL-запроса в соответствующие фрагменты SQL-запроса и определения функций, необходимых для выполнения трансляции, рассматриваются упрощенные грамматики этих языков, определяющие основные синтаксические правила построения запросов, наиболее часто встречающиеся при разработке прикладных программ.

Грамматика SQL-запроса к РБД:

Грамматика запроса к объектному представлению РБД:

Функции, требующиеся для преобразования фрагментов OSQL-запроса в соответствующие фрагменты SQL-запроса, определяются путем сравнения двух грамматик.

1. <table> := translate_object ( <object> ).

Функция translate _ object возвращает название таблицы, соответствующей заданному объекту. Информация о соответствии таблиц объектам извлекается из ОСД.

2. <from_list> := add _ table ( <from_li-st>, translate_object ( <object> ) )

Функция add _ table пополняет множество таблиц раздела FROM результирующего SQL-запроса таблицами, выделенными из транслируемого фрагмента OSQL-запроса. В результате обработки всех объектов исходного запроса в разделе FROM будет сформирован список таблиц, соответствующих всем обработанным объектам.

3. <table_field> := translate_object_ attribute ( <o_complex_attribute> )

Функция translate_object_attribute преобразует атрибут объекта в поле таблицы с использованием данных из ОСД. С помощью многократного вызова данной функции все найденные в исходном запросе атрибуты объектов преобразуются в поля таблиц. При каждом вызове пополняются множество таблиц раздела FROM и множество условий связи между парами таблиц, которые также извлекаются из ОСД. Для каждой пары объектов в составном атрибуте <o_complex_attribute> определяется пара соответствующих им таблиц, после чего условие связи между ними <join _ condition> добавляется к разделу WHERE результирующего SQL-запроса.

4. <where_condition> := add_condition (<where _ condition>, <join _ condition>)

Функция add _ condition дополняет множество ограничений на результирующую выборку в разделе WHERE условиями объединения пар таблиц, выделенных в процессе разбора OSQL-запроса, используя логическую связку “И” с уже имеющимися условиями.

5. <sql_fragment> ::= translate_fragment ( <osql_fragment> )

Функция преобразует фрагмент OSQL-запроса в соответствующий фрагмент SQL-запроса путем замены всех обнаруженных в нем атрибутов объектов на поля таблиц. Замена осуществляется вызовом функции translate_object_attribute(). Данная функция применима для фрагментов <o_where _ condition>, <o _ groupby _ condition>, <o_having_condition>, <o_orderby_conditions>.

Если с помощью описанных функций последовательно обработать все фрагменты исходного запроса, то в результате будет сформировано множество таблиц раздела FROM и множество условий связи между таблицами раздела WHERE результирующего запроса, а все атрибуты объектов будут замещены полями таблиц.

При успешном выполнении запроса типа SELECT в качестве его результата СУБД возвращает набор записей, в котором названия всех полей соответствуют названиям в РБД, а не в исходном OSQL-запросе. В процессе последующей обработки результата запроса в приложении требуется знать соответствие между атрибутами объектов в исходном запросе и названиями полей результирующей выборке, для чего транслятор возвращает приложению информацию о соответствии названий атрибутов объектов исходного запроса возвращаемым названиям полей.

Трансляция запросов других типов (INSERT, UPDATE и DELETE) выполняется по аналогии с трансляцией запросов типа SELECT. При наличии подзапросов типа SELECT обработка выполняется начиная с наиболее глубоко вложенных из них, после чего транслируется внешний запрос таким образом, как если бы он не содержал подзапросов.

Необходимость трансляции запросов, которая выполняется перед их передачей в СУБД для исполнения, отражается на способе взаимодействия клиентского приложения и СУБД.

Схема взаимодействия клиентского приложения, формирующего SQL-запросы и отправляющего их с помощью функций программного интерфейса СУБД (API, Application Programming Interface), приведена на рис. 1.

Схема взаимодействия клиентского приложения и СУБД

Рисунок 1. Схема взаимодействия клиентского приложения и СУБД

Запросы, генерируемые и передаваемые клиентским приложением к СУБД, могут быть статическими и динамическими. Статические запросы составляются прикладным программистом на этапе разработки приложения, после чего они в неизменной форме внедряются в приложение. Динамические запросы формируются в процессе работы приложения. В зависимости от типа запроса предлагается два подхода к его выполнению в приложении:

  • при выполнении статических запросов — предварительная трансляция: запрос в объектной форме транслируется в SQL-запрос, который внедряется в приложение и в дальнейшем в неизменной форме передается СУБД;
  • при выполнении динамических запросов требуется выполнять динамическую трансляцию, т.е. преобразование объектного запроса, сформированного приложением в процессе его выполнения, в SQL-запрос, после чего SQL-запрос передается приложением в СУБД.

Для выполнения динамических объектных запросов в СУБД требуется их трансляция в процессе выполнения приложения, при этом возможны следующие варианты включения транслятора в ИС:

1. Клиентское приложение формирует объектный запрос, используя API транслятора, передает его транслятору; транслятор преобразует полученный запрос в SQL-запрос и передает его СУБД, используя ее API; СУБД возвращает ответ, который передается транслятору для обратного преобразования названий таблиц и полей к названиям объектов и атрибутов; транслятор передает этот ответ клиентскому приложению (рис.2).

2. Клиентское приложение формирует объектный запрос и используя API транслятора передает запрос ему; транслятор преобразует полученный объектный запрос в SQL-запрос и возвращает ответ клиентскому приложению, при этом вместе с запросом возвращается таблица соответствий исходных и транслированных названий таблиц и объектов, полей и атрибутов; клиентское приложение передает SQL-запрос СУБД и получает результат его выполнения, используя API СУБД (рис.3).

Схема взаимодействия клиентского приложения и СУБД с использованием транслятора объектных запросов — транслятор находится между клиентом и СУБД

Рисунок 2. Схема взаимодействия клиентского приложения и СУБД с использованием транслятора объектных запросов — транслятор находится между клиентом и СУБД

Схема взаимодействия клиентского приложения и СУБД с использованием транслятора объектных запросов — транслятор работает независимо от СУБД

Рисунок 3. Схема взаимодействия клиентского приложения и СУБД с использованием транслятора объектных запросов — транслятор работает независимо от СУБД

Несмотря на то, что первый подход является архитектурно более простым, чем второй, его реализация приведет к существенному снижению производительности при трансляции запросов на выборку данных, результат выполнения которых содержит большое число записей. Это объясняется тем, что передача и временное хранение полного ответа СУБД в памяти транслятора значительно снизит эффективность использования функций API СУБД, позволяющих извлекать и просматривать только интересующие фрагменты результирующей выборки, поэтому для практической реализации транслятора рекомендуется использовать второй подход, не имеющий подобного недостатка.

* * *

Вы активный блоггер? Тогда, думаю, вам будут интересны конкурсы для блогеров в которых можно не просто с интересом поучаствовать, но еще и выиграть призы, получить огромный опыт участия в рекламных акциях, произвести обмен ссылками с другими блогерами. Читайте специальный блог о конкурсах и не пропускайте интересных мероприятий в блогосфере.

Добавить комментарий

Ваш адрес email не будет опубликован.

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.