SPM или собственный предметный макроязык над процедурным расширением SQL
Внимание
В статье рассказывается о предыдущей версии SPM (1.x). Описание текущей улучшенной и более простой в использовании версии SPM 2 находится здесь.Предыстория
В ходе моих проектов приходилось и приходится писать много серверного кода в виде хранимых процедур и сценариев на процедурном расширении SQL соответствующей СУБД (в основном это MS SQL). К сожалению, при больших объемах такого кода (тысячи и десятки тысяч строк) возникает необходимость в инструменте, который бы мог:
- группировать исходный код в виде файлов и вести проект из нескольких файлов;
- транслировать код на сервер БД с диагностикой возможных ошибок;
- допускать метапрограммирование, то есть использование несложного макроязыка (функциональная декомпозиция в декларативном языке SQL как правило неэффективна прежде всего с точки зрения производительности да и сам T-SQL до выхода версии MS SQL 2000 не допускал функций, определяемых пользователем);
В результате был создан инструмент, получивший название SPM (Stored Procedures Macroprocessor).
Первая версия поддерживала только MS SQL. Однако вскоре пришлось работать с InterBase и Sybase, поэтому была введена поддержка для них. Но энтропия увеличилась, появились некие специфичные настройки, инструмент "стал толстым". Поэтому я принял решение сделать SPM практически универсальным за счет работы с СУБД через ODBC.
Поскольку, кроме хранимых процедур существуют еще их "ближайшие родственники" в виде триггеров (процедура, работающая по событию, происходящему с таблицей БД) и, на некоторых серверах БД, функций, то начиная с версии 1.4.1 SPM поддерживает разработку этих процедурных объектов. С версии 2.0.3 поддерживаются также проекции (view).
В связи с тем, что мне требовались все более и более изощренные макросы, я решил более не тратить времени на развитие собственного велосипеда, а взять за основу готовый макропроцессор GNU m4, оставив за SPM только функции менеджера файлов проекта и транслятора кода на сервер.
Рис.1. Принципы работы SPM
Макроязык
Подробное описание макроязыка и настроек m4 приводятся на его основном сайте . По умолчанию, SPM использует минимально необходимые опции для запуска макропроцессора, но вы можете добавить к ним свои, используя параметр Options в файле проекта.
Примеры макроопределений
Простой макрос:
define({RC_ERROR}, {-1})<br> define({RC_SUCCESS}, {0})
Макрос с параметрами, вызывающий другой макрос:
define({ReturnIfError}, {if ($1 != RC_SUCCESS) return RC_ERROR})
Макрос с параметрами, вызывающий другой макрос с параметрами.
define({CallProc},<br> {<br> if ProcExists($1)<br> exec $2 $3<br> }<br> define({ProcExists}, {exists(select * from sysobjects where name=$1 and type='P')}
SQL-проект
SQL-проект - это совокупность исходных и промежуточных файлов, содержащих любой процедурный код. SQL-проект ассоциирован с понятием модуля - выделенного набора объектов БД и сценариев их инициализации. Поэтому SPM может генерировать SQL-скрипты для установки или удаления модуля на сервере БД.
Макропроцессор SPM работает только с файлами SQL-проекта (далее просто "проект"). Любой проект содержит файл метаинформации, то есть сведения о других файлах, входящих в его состав и другую служебную информацию. В нашем случае главным файлом проекта может являться любой файл с расширением *.prj, который имеет следующую структуру, подобную структуре обычного INI-файла Windows:
Секция |
Элементы |
Назначение |
M4Info | Содержит информацию о макропроцессоре m4 | |
Application | Имя исполняемого файла и полный путь к нему (например, C:utilsm4m4.exe). Если m4 находится в каталоге, указанном в PATH, то путь можно не указывать. | |
Options | Дополнительные опции для запуска m4, например для вывода отладочной информации. | |
LogonInfo | Содержит информацию о параметрах соединения с сервером БД | |
ConnectionString | Строка для ODBC-соединения | |
LogonFile | Имя файла (допускается
относительный и абсолютный пути),
который содержит другую секцию LogonInfo. В
этом случае все предыдущие параметры
игнорируются и берутся из этого файла.
Использование данного параметра удобно для нескольких проектов, имеющих одни и те же настройки соединения с сервером. |
|
ServerInfo | Содержит специфичные для данного сервера БД параметры | |
ProcedurePrefix | Префикс владельца процедуры (необязательный, только MS SQL). Если не указан, процедура создается с префиксом текущего пользователя | |
BatchTerminator | Параметр BatchTerminator (необязательный)
Определяет символ окончания фрагмента SQL-скрипта. Данный символ делит скрипт на логически независимо исполняемые части. SPM интерпретирует данную лексему в файле, как явно указанное окончание объявления текущего объекта (неявным окончанием является начало объявления другого объекта или конец файла) |
|
CheckZeroSeverity | Параметр CheckZeroSeverity (Необязательный)
Определяет, является ли сообщение с приоритетом "0" ошибкой или информационным сообщением для данного сервера 0 - не является ошибкой, 1 - является (по умолчанию) |
|
SourceFiles | Содержит список исходных файлов кода | |
Count | Число исходных файлов (необязательный элемент, если его не указывать число будет ограничено 100000) | |
FileN | Имя N-го файла (допускается
относительный и абсолютный пути) Для облегчения возможной последующей вставки файлов N можно задавать с шагом от 1 до 999. |
|
IncludePaths | Содержит список путей к файлам макроопределений | |
Count | Число путей (необязательный элемент, если его не указывать число будет ограничено 100000) | |
PathN | Спецификация N-го пути (допускается относительный и абсолютный варианты) | |
InstallFiles | Содержит список файлов, которые используются для генерации SQL-скрипта установки модуля. Он создается простым слиянием файлов File1..FileN в один файл с именем _Install.sql | |
Count | Число файлов в секции (необязательный элемент, если его не указывать число будет ограничено 100000) | |
FileN | Имя N-го файла (допускается относительный и абсолютный пути) | |
UninstallFiles | Аналогично секции InstallFiles создается SQL-скрипт для удаления модуля с именем _Uninstall.sql | |
Count | Число файлов в секции (необязательный элемент, если его не указывать число будет ограничено 100000) | |
FileN | Имя N-го файла (допускается относительный и абсолютный пути) | |
PostExec | SQL-команды, которые будут выполнены после успешной трансляции всего проекта | |
PostCmd | SQL-команда в одну строку. Имеет приоритет перед файлом (см. PostCmdFile), т.е. если задана команда, то файл не выполняется. | |
PostCmdFile | Имя файла сценария из одной и более строк с команадами. Внутри нельзя использовать batch terminator. |
Пример файла проекта Sample.prj.
[M4Info]<br> Application=C:utilsm4m4.exe<br> Options=<br> <br> [LogonInfo]<br> LogonFile=logon.cfg<br> <br> [ServerInfo]<br> ServerType=0<br> <br> [SourceFiles]<br> FilesCount=1<br> File1=Sample.sqm<br> <br> [IncludePaths]<br> Count=1<br> Path1=..common<br> <br> [InstallFiles]<br> Count=3<br> File1=_Create_objects.sql<br> ; Файл _CreateProcs.sql создается автоматически и содержит<br> SQL-скрипт<br> ; создания всех процедур проекта<br> File2=_CreateProcs.sql<br> File3=_Init_objects.sql<br> <br> [UninstallFiles]<br> Count=2<br> ; Файл _DeleteProcs.sql создается автоматически и содержит<br> SQL-скрипт<br> ; удаления всех процедур проекта<br> File1=_DeleteProcs.sql<br> File2=_Destroy_objects.sql
Файл logon.cfg:
[LogonInfo]<br> ConnectionString=DRIVER={SQL<br> Server};SERVER=MY_SERVER;UID=sa;PWD=123;DATABASE=pubs;Network=DBMSSOCN;
Примеры ConnectionString для разных СУБД
СУБД | ConnectionString |
MS SQL 7/2000/2005 | DRIVER={SQL Server};SERVER=MY_SRV;UID=sa;PWD=;DATABASE=pubs;Network=DBMSSOCN; |
Interbase 6 | DRIVER={XTG Systems InterBase6 ODBC driver};SERVER=MY_SRV;DB=MY_SRV:D:IB6employee.gdb;UID=SYSDBA;PWD=masterke |
Sybase ASE 12 | DRIVER={Sybase ASE ODBC Driver};SRVR=MY_SRV;UID=sa;PWD=;DB=master; |
Файлы проекта
В проект входят файлы двух типов: исходные и производные.
Исходные файлы - это файлы макроопределений (должны иметь расширение *.sqh) и файлы кода на процедурном расширении SQL с возможным (но не обязательным) применением макроязыка (должны иметь расширение *.sqm).
Производные файлы - это файлы, образующиеся после макроподстановок в исходных файлах *.sqm (они получают то же имя, но с расширением *.sql) и их одноименные предыдущие копии с расширением *.bak. SPM создает также SQL-файлы установки/удаления модуля и создания/удаления процедур при использовании опции /build (см. ниже).
Кроме вышеперечисленных типов, SPM создает также файл Error.log, если в процессе работы выявились ошибки. Файлы Lexemes.dmp, Parcemap.dmp и Stack.dmp являются служебными и создаются только в отладочной версии SPM.
Как он работает
SPM работает по следующему сценарию.
- Для всех sqm-файлов выполняется вызов макропроцессора m4 с выводом результата в одноименный файл, но с расширением *.sql. Если в процессе работы произошли ошибки, они выводятся в файл Error.log и на этом работа прекращается.
- Осуществляется последовательная трансляция объектов (хранимых процедур, триггеров, функций и проекций (view)) из полученных sql-файлов. Если в процессе работы произошли ошибки, они выводятся в файл Error.log и на этом работа прекращается. Для MS SQL Server используется его расширения интерфейса ODBC, которые показывают подробные сведения о месте и содержании ошибки в транслируемом коде.
- SPM возвращает статус завершения своего
выполнения. Если произошли ошибки, то
статус равен "1", если все в порядке,
то нулю. Это можно проверять в командных
файлах, например так:
if errorlevel 1 goto errors_occured<br> echo все нормально<br> goto end<br> :errors_occured<br> echo произошли ошибки<br> :end
Как запустить
Макропроцессор m4 включен в дистрибутив. Вы также можете загрузить m4 с сайта GNU utilities for Win32, где он входит в комплект UNIX-утилит для Windows.
Необходимо распаковать дистрибутив и добавить каталог bin, где находятся SPM.exe и m4.exe в переменную среды PATH, либо, что не всегда является хорошей практикой, просто скопировать содержимое bin в один из каталогов, путь к которому уже указан в PATH.
Для работы с сервером БД вам необходимо установить ее клиентскую часть и ODBC-драйвер. Для MS SQL Server драйвер ODBC не требует наличия установленной клиентской части.
SPM тестировался только для следующих серверов:
- MS SQL 6.5, 7, 2000 и 2005
- Sybase ASE 12.0 и 12.5
- InterBase 6 / FireBird
Однако, никаких принципиальных ограничений по использованию, с любым другим сервером нет, за исключением требования наличия установленного ODBC драйвера.
Перейдите в каталог SQL-проекта (в котором лежит главный файл проекта *.prj). Выполните из командной строки запуск:
spm[.exe] <файл проекта> [опции]
или, для получения информации о версии программы:
spm[.exe] /ver
Расширение *.prj для файла проекта указывать необязательно.
Опции запуска приведены ниже в таблице.
Опция | Назначение |
/script | SMP только обрабатывает исходные файлы, не транслируя результаты на сервер. |
/all | SPM транслирует все процедуры на сервер независимо от того, изменялся текст в файлах или нет (аналог Rebuild All в различных средах разработки) |
/ver | SPM выводит информация о своей версии, все другие опции и названия файла проекта игнорируются, никаких действий не производится |
/build | SMP создает SQL-скрипты для установки и удаления модуля (файлы _Install.sql и Uninstall.sql, соответственно). В процессе создания скриптов будут созданы также файлы _CreateProcs.sql и _DeleteProcs.sql, содержащие , соотвественно, полные SQL-скрипты для создания и удаления всех процедур/триггеров/проекций проекта. |
/debug | SMP определяет макро SPM_DEBUG, который можно использовать для условной трансляции Например: ifdef({SPM_DEBUG}, {SELECT 'Debug mode' AS mode}) |
/m4:<M4 command line option> | Передает в M4 параметр командной строки. Можно задавать более одной опции /m4 |
Как настроить MultiEdit для работы с SPM
Предполагается, что на Вашем компьютере установлен MultiEdit 8 для Windows. Последовательность действий по настройке может быть следующей.
- В меню "Tools" выбираем пункт "Customize...". В открывшемся дилоговом окне переходим на закладку "Customize" и нажимаем кнопку "Filename extensions...".
- В открывшемся диалоге редактирования добавьте в поле "Extension(s)" к расширению SQL еще SQM и SQH.
- Нажмите кнопку "Compiler/Program setup...". В открывшемся диалоге нажмите "Insert". В поле "Description" напишите, например, "SPM macroprocessor". В поле "Command" введите название командного файла для запуска компиляции, например "compile.bat". Использование командного файла с одним названием позволит производить запуск SPM из MultiEdit независимо от названия проекта. Далее необходимо установить следующие значения опций: "Working directory" - "Source file", "Exe Type" - "Win32 console", "Show" - "Normal" и установить флаги "Save all files" и "Reload file". После этого нажимаем кнопку "..." для выбора "Program Type".
- В открывшемся диалоге нажимаем "Insert". Заполняем поля: "Type" - "SPM", "Exe file" - "spm.exe", в группе "Error" поле "File" - "error.log". Остальные поля не заполняем. Нажимаем "ОК".
- В диалоге "Compiler/Program type" выбираем созданный "SPM" и нажимаем "Select".
- В диалоге "Compiler/Program Type" нажимем "OK".
- В диалоге "Compiler/Program" выбираем созданный "SPM macroprocessor" и нажимаем "Done".
- В диалоге "Edit Filename Extension Setup" нажимем "OK". Если у вас уже были открыты файлы, то на появившийся вопрос "Reset extension configuration in currently loaded files" (перустановить конфигурацию для загруженных файлов) отвечаем утвердительно "Yes".
- В диалоге "Filename extension setup" нажимаем "Close".
- В диалоге "Customize" нажимаем "ОК".
Теперь, если выбрать пункт "Execute compiler..." из меню "Tools" (он также настраивается на горячую клавишу, я предпочитаю общую настройку для Multi Edit - "Borland IDE emulation"), то будет произведен вызов командного файла compile.bat, который запустит SPM с именем текущего проекта, в каталоге которого вы редактируете файлы. Если в процессе работы SPM произошли ошибки, то внизу откроется окно, в котором Вы увидите содержимое файла error.log. Если этого не произошло в первый раз автоматически, надо открыть окно просмотра ошибок нажав на панели статуса в правом нижнем углу самую правую кнопку.
Как настроить FAR Manager
Для работы с FAR потребуется установленный модуль Colorer. Открываем файл C:\Program Files\Far\Plugins\Colorer\hrc\proto.hrc, находим в нем элемент <prototype name="sql" и значение
<filename>/\.sql$/i</filename>
меняем на
<filename>/\.(sql|sqh|sqm)$/i</filename>
Перестартуем FAR, теперь файлы с макросами имеют подсветку SQL-синтаксиса
Как скомпилировать
В состав дистрибутива входят все необходимые сторонние исходные файлы и библиотеки, так что больше ничего вам загружать и устанавливать не придется. Для компиляции вам потребуется MS Visual C++ 7 из состава VS.Net. Файлы проекта включены в дистрибутив. Для компиляции в IDE просто откройте проект и постройте исполняемый файл.
По умолчанию строится версия с англоязычным интерфейсом. Если вы хотите изменить язык на русский, то просто добавьте в опции препроцессора директиву RUSSIAN. Это можно сделать в диалоге "Project settings": на закладке "С/С++" выберите из списка категорию "Preprocessor" и в поле "Preprocessor definitions" добавьте RUSSIAN.
Пример
Хороший способ ознакомиться с SPM - тестовый пример. Пример, сделаный для MS SQL 7/2000, предполагает наличие демонстрационной базы данных pubs на сервере. Примеры для Interbase и FireBird 1 используют демонстрационную БД employee.gdb.
Информация об изменениях и версиях
В дистрибутив помимо исходных файлов и исполняемого модуля (EXE) включаются файлы:
version.txt | содержит номер версии SPM |
changes.txt | содержит последовательный хронологический лист регистрации изменений |
template.prj template.ru.prj |
содержит шаблон файла проекта |
license.txt | лицензионная информация |
Загрузить
Загрузить дистрибутив SPM (версия 2.0.16)
Прикрепленный файл | Размер |
---|---|
![]() | 326.63 KB |