Разработка SQL компилятора для СУБД «ОМЕГА» Докладчик Губин Максим Владимирович Научный руководитель Соколинский Леонид Борисович Челябинск 2006 г. 1 Постановка задачи Разработка SQL компилятора СУБД «ОМЕГА» Под компилятором будем понимать программу, которая преобразует цепочку входных символов, введенных пользователем, в дерево физических операций над данными СУБД «ОМЕГА». В работе можно выделить два направления: • разработка компилятора, который на входе принимает некоторую строку запроса в терминах подмножества языка SQL, на выходе имеет физический план выполнения запроса SQL; • определение языка SQL', который является некоторым подмножеством языка SQL (точнее, можно предположить, что язык SQL' имеет ряд дополнительных ограничений наложенных на язык SQL). Челябинск 2006 г. 2 Общая структура компилятора Цепочка символов запроса Лексический анализатор Система анализа ошибок Синтаксический и семантический анализатор Таблицы лексем Дерево разбора Препроцессор Генератор логического плана Логический план запроса в терминах реляционной алгебры Генератор физического плана Челябинск 2006 г. 3 Основные компоненты SQL компилятора • лексический анализатор – предназначен для выделения лексем из цепочки символов запроса, проверки их принадлежности одному из классов лексем и передачи их синтаксическому анализатору; • синтаксический анализатор – предназначен для распознавания синтаксической структуры из представленных лексических композиций, и представления этой структуры в виде дерева разбора или синтаксического дерева; • препроцессор – предназначен для контроля употребления имен отношений, имен атрибутов и типов самих атрибутов; • генератор логического плана – предназначен для преобразования дерева разбора в логический план выполнения запроса с использованием набора операций реляционной алгебры; • генератор физического плана выполнения запроса – формирует физический план исполнения запроса в известных физических операциях. Челябинск 2006 г. 4 Лексический анализатор На входе лексического анализатора (ЛА) имеется цепочка символов некоторого алфавита. Алфавит может содержать следующие символы: • английский алфавит – {A,B,C…Z,a,b,c…z}; • арабские числа – {0,1,2,3..9}; • разделители – {_, ’, ., ;}; • операторы отношений – {=,<,>,*}. На выходе ЛА содержаться лексемы. Определим основные классы лексем: • константа (например: 1 или 1.55); • идентификатор (перем1 или атрибут2); • строка (представляет произвольный набор символов ограниченный кавычкой «‘»); • оператор «*»; • точка «.»; • запятая «,»; • точка запятая «;»; • пробел «_»; • оператор отношения «=», «>», «<». Челябинск 2006 г. 5 Детерминированный конечный автомат • • • • • Лексический анализатор строиться на основе детерминированного конечного автомата ДКА=(Q,V, ,q0,F) , где Q – конечное множество состояний автомата; V – конечное множество допустимых входных символов; – функция переходов; q0 – начальное состояние автомата, qQ; F – множество конечных состояний автомата, FQ. Челябинск 2006 г. 6 Матрица состояний ДКА CL - Классы символов ST Цифры Буквы «’» «*» «/» «.» «,» пробел «;» другой «=», «<», «>» 1 2 3 4 5 6 7 8 9 11 12 0 2 1 3 -4 -5 -6 -7 -8 -9 -11 -13 ident 1 1 1 -11 -1 -1 -1 -1 -1 -1 10 -1 constanta 2 2 1 -11 -2 -2 2 -2 -2 -2 10 -2 string 3 3 3 -3 3 3 3 3 3 3 3 3 multiply 4 2 1 3 -4 -5 -6 -11 -8 -9 10 -11 div 5 2 1 -11 -11 -11 -11 -11 -8 -11 10 -11 point 6 -11 1 -11 -11 -11 -11 -11 -11 -11 10 -11 comma 7 2 -11 -11 -11 -11 -11 -11 -8 -11 10 -11 spase 8 2 1 3 -4 -5 -6 -7 -8 -9 10 -13 point comma 9 -11 -11 -11 -11 -11 -11 -11 -8 -11 -11 -11 other 11 10 10 10 10 10 -6 -7 -8 -9 10 -11 error 12 -11 -11 -11 -11 -11 -11 -11 -11 -11 -11 -11 is 13 2 1 3 -11 -11 -11 -11 -8 -11 -11 -13 начальное сост. авт. q0 Челябинск 2006 г. 7 Основные прототипы процедур, необходимых для работы ЛА: • int D[13][12] //матрица состояний КА • char *out[]= //классы лексем • {"ident","constant","string","multiply","div","point","comma","spase","point • • • • • comma","other","error","is" }; struct tabLexAn{ int id; char name[]; char *type;} void LexAn() //структура таблицы лексем //порядковый номер лексемы //имя лексемы(содержание) //тип лексемы //функция выполнения лексического анализа Челябинск 2006 г. 8 Синтаксический анализатор Задача синтаксического анализатора состоит в преобразовании последовательности лексем в дерево разбора (синтаксическое дерево). Каждая вершина дерева разбора представляет одну из следующих сущностей: • атомы – лексические единицы, такие как служебные слова (например, SELECT), наименования атрибутов или отношений, константы, скобки операторы и иные элементы; • синтаксические конструкции – группа лексем объединенных в конструкцию по некоторому устойчивому смыслу над этой группой (например, <SFW> это такая синтаксическая конструкция как <select– from–where>). Челябинск 2006 г. 9 Грамматика языка SQL При синтаксическом анализе проверяется цепочка распознанных лексем на принадлежность множеству цепочек, порождаемых грамматикой языка SQL. Пример правил грамматики языка SQL для синтаксической конструкции <select-from-where>: <SFW>:=Select <ListAtribute> From <ListForm> Where <ListCondition>; <ListAtribute>:=<Atribute><Atribute>,<Atribute> <Atribute>:=<Identifier><Identifier>.<Form> <ListForm>:=<Form><Form>,<Form> <Form>:=<Identifier> <ListCondition>:=<Condition>(<Condition>) And (<Condition>) <Condition>:=<Atribute>=<Identifier><Atribute>=<Atribute> <Identifier>:=ident* Челябинск 2006 г. 10 Реализация синтаксического разбора При анализе цепочки лексем используется нисходящий метод разбора слева направо, т.е . Разбор осуществляется автоматом с магазинной памятью (МПавтомат) R=(Q,V,Z,,q0,z0,F), где Q – конечное множество состояний автомата; V – алфавит входных символов; Z – алфавит магазинных символов автомата VZ, – функция переходов; q0 – начальное состояние автомата, qQ; z0 – начальный символ автомата, zZ; F – множество конечных состояний автомата, FQ. Конфигурацию МП-автомата можно описать в виде тройки (q,,) QV*Z*, которая определяет состояние автомата q, цепочку еще не прочитанных символов на входе автомата и содержание магазина (стека) . Начальная конфигурация определяется (q0,,z0), V*, множество конечных состояний автомата – (q,,), qF, Z*. МП-автомат допускает цепочку символов с опустошением магазина, если при окончании разбора цепочки автомат находится в одном из конечных состояний, а стек автомата пуст. Челябинск 2006 г. 11 Прототипы основных функций, реализующих семантический анализ stack stack_SemAn //организация стека для МП-автомата tree tree_sinAn //дерево синтаксического разбора char *terminal[] //список терминалов char *neterminal[] //список нетерминалов char *first[][] //множество fist char *follow[][] //множество follow struct Gram{ //структура правил грамматики int id; char Rul[][];} int M[][] //таблица состояний предикативного //синтаксического разбора int GetRul() //процедура чтения правил из внешнего файла int spisokTerminalov() //определение списка терминалов из правил int spisokNeTerminalov() //определение списка нетерминалов из правил int oprTerm() //определение терминалов в лексемах void FindFirst() //определяем множество FIRST () int FOLLOW() //определяем множество FOLLOW() int TablRazbora() //создание таблицы синтаксического разбора int SinAn() //синтаксический анализ Челябинск 2006 г. 12 Препроцессор Для определения действительности синтаксического дерева разбора, необходимо выполнить контроль его следующих параметров: • контроль употребления имен отношений, который определяет существование отношения, зарегистрированного в текущей схеме данных; • контроль использования имен атрибутов и их разрешение, который определяет существование каждого атрибута и его принадлежность одному из отношений заявленных в синтаксическом дереве; • контроль типов, который проверяет способ использования каждого атрибута на соответствие типу атрибута. При возникновении ошибки на любом из параметров контроля, формируется код ошибки и передается управление системе обработки ошибок. Например, препроцессор может обнаружить использование атрибута с одинаковым именем в двух отношениях, используемых при выборе в одном запросе. Челябинск 2006 г. 13 Прототипы основных функций, реализующих работу препроцессора int existTable(char* name) int existAtribut(char* name) int trueType() //проверяем наличие таблицы //проверяем наличие атрибута //проверяем соответствие типа Челябинск 2006 г. 14 Генератор логического плана Генератор логического плана предназначен для преобразования дерева разбора в логический план выполнения запроса с использованием набора операций реляционной алгебры. Для примера преобразования синтаксического дерева разбора в логический план запроса, представленным выражениями реляционной алгебры, рассмотрим синтаксическую конструкцию <SFW>. Эта конструкция состоит из трех реляционных операций: • - декартова произведения всех отношений из списка <FromList>; • - оператора выбора C из условия <Condition>; • - оператора проекции L соответствующего списку <AtributList>. Челябинск 2006 г. 15 Пример Если на входе мы имеем следующий подзапрос: Select Atr1, Atr2 From From1, Form2 Where Atr1=Atr2, то выражение реляционной алгебры имеет вид: Atr , Atr ( Atr Atr (Form Form )) 1 1 2 1 Atr , Atr 1 2 2 2 Atr Atr 1 2 Form1 Челябинск 2006 г. Form2 16 Прототипы функций, реализующих генерацию логического плана запроса • tree tree_logPlan • char param[][] • void Create_logPlan() //определение дерева логического плана //определение дополнительных параметров //функция генерации логического плана