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 работает по следующему сценарию.

  1. Для всех sqm-файлов выполняется вызов макропроцессора m4 с выводом результата в одноименный файл, но с расширением *.sql. Если в процессе работы произошли ошибки, они выводятся в файл Error.log и на этом работа прекращается.
  2. Осуществляется последовательная трансляция объектов (хранимых процедур, триггеров, функций и проекций (view)) из полученных sql-файлов. Если в процессе работы произошли ошибки, они выводятся в файл Error.log и на этом работа прекращается. Для MS SQL Server используется его расширения интерфейса ODBC, которые показывают подробные сведения о месте и содержании ошибки в транслируемом коде.
  3. 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. Последовательность действий по настройке может быть следующей.

  1. В меню "Tools" выбираем пункт "Customize...". В открывшемся дилоговом окне переходим на закладку "Customize" и нажимаем кнопку "Filename extensions...".
  2. В открывшемся диалоге редактирования добавьте в поле "Extension(s)" к расширению SQL еще SQM и SQH.
  3. Нажмите кнопку "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".
  4. В открывшемся диалоге нажимаем "Insert". Заполняем поля: "Type" - "SPM", "Exe file" - "spm.exe", в группе "Error" поле "File" - "error.log". Остальные поля не заполняем. Нажимаем "ОК".
  5. В диалоге "Compiler/Program type" выбираем созданный "SPM" и нажимаем "Select".
  6. В диалоге "Compiler/Program Type" нажимем "OK".
  7. В диалоге "Compiler/Program" выбираем созданный "SPM macroprocessor" и нажимаем "Done".
  8. В диалоге "Edit Filename Extension Setup" нажимем "OK". Если у вас уже были открыты файлы, то на появившийся вопрос "Reset extension configuration in currently loaded files" (перустановить конфигурацию для загруженных файлов) отвечаем утвердительно "Yes".
  9. В диалоге "Filename extension setup" нажимаем "Close".
  10. В диалоге "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" и значение

&lt;filename&gt;/\.sql$/i&lt;/filename&gt;

меняем на

&lt;filename&gt;/\.(sql|sqh|sqm)$/i&lt;/filename&gt;

Перестартуем 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)

Прикрепленный файлРазмер
Package icon SPM_full.zip326.63 KB