SPM (SQL Programming Macroprocessor). Создайте свой предметный язык - 2.

Назначение

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

Обе проблемы могут быть решены введением над SQL макроязыка. А поможет нам в этом достаточно простая утилита SPM (SQL Programming Macroprocessor), основанная на фактически стандартном для UNIX-среды макропроцессоре GNU m4.

Принципы работы

На входе имеем исходники в виде программного кода на процедурном расширении SQL. Так как мы используем макросы, то необходимо давать файлам расширения, отличные от *.SQL, используемого для выходных файлов. Пусть, например, это будут расширения *.SQM для файлов исходников и *.SQH для файлов макроопределений.

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

На втором этапе полученные файлы транслируются на сервер БД при помощи прилагаемой к любой СУБД утилиты типа iSQL.exe или сливаются в единый SQL-скрипт, полезный в дальнейшем для развертывания


Рис.1. Принципы работы SPM

Файл проекта

Кроме исходников потребуется файл, в котором содержится:

  • информация о вызове m4
  • информация об утилите iSQL для трансляции выходного файла в СУБД
  • информация о расположении файлов макроопределений (если они находятся, например, в общей директории)
  • информация об исходных файлах включая расположение и управляющие опции (транслировать, включать в итоговый скрипт...)

Такой файл в виде XML называется файлом проекта и по умолчанию имеет расширение *.spm2. Вот пример файла проекта:

<?xml version="1.0" encoding="utf-8"?>
<spm2>
  <m4Info>
    <application>%M4_BIN%\m4.exe</application>
  </m4Info>
 
  <!-- Interactive SQL (ISQL) tool info -->
  <isqlInfo>
    <!-- ISQL should return exit code to check errors.
         You can use system or custom environement variables like %MyVar%, %PATH% etc.
         Variable #FILE_NAME# is used as name for currently processed source file (see section sourceFiles)
    -->
    <commandLine>osql -b -n -S%SERVER_NAME% -d%DATABASE_NAME% -E -i#FILE_NAME#</commandLine>
  </isqlInfo>
 
  <!-- Paths to search included files (usually common macro definitions) -->
  <includes>
    <include>..\..\..\Include</include>
  </includes>
 
  <sourceFiles>
  <!-- Default file settings (change if need): 
       compile = "true"
       script = "true"
  -->
    <file compile="false" script="false">CreateCatalog.sqm</file>
    <file>Utils.sqm</file>
    <file>SalesForecast.sqm</file>
  </sourceFiles>
</spm2>

Макроязык и примеры

Подробное описание макроязыка и настроек m4 приводятся на его основном сайте . По умолчанию, SPM использует минимально необходимые опции для запуска макропроцессора, но вы можете добавить к ним свои, используя секцию m4info в файле проекта или передавая SPM опции для m4  в командной строке.

Разнообразные макроопределения можно найти в прилагающихся примерах файлах *.SQH. Например, в директории \sample\Include файл SqlUnit.sqh содержит необходимые макросы для весьма простой организации модульного тестирования (см. подробную статью по ссылке). Поэтому ниже мы приведем только несколько простых макросов, чтобы было понятно, о чем ведется речь.

Простой макрос:
define({RC_ERROR}, {-1})

Макрос с параметрами, вызывающий другой макрос:
define({ReturnIfError}, {if ($1 != RC_SUCCESS) return RC_ERROR})

Макрос с параметрами, вызывающий другой макрос с параметрами.

define({RaiseSysError}, {raiserror($1, SYS_ERROR_SEVERITY, 1)})
define({CheckReturnError}, {if ($1 != RC_SUCCESS) BEGIN RaiseSysError({'Error status returned. ifelse($2,{},{},$2)'}) END})

Как запустить

Прежде всего необходимо загрузить дистрибутивный пакет (ссылка в конце страницы) и распаковать его дистрибутив в созданный каталог, например C:\Utils\SPM2.

Для работы с сервером БД вам необходимо как минимум установить ее клиентскую часть и знать о существовании консоли iSQL. Для MS SQL Server утилита iSQL не поддерживается, рекомендуется использовать sqlcmd и osql.

Перейдите в каталог SQL-проекта (в котором лежит главный файл проекта *.spm2). Например, используйте прилагающиеся примеры из директории Samples Выполните из командной строки запуск:

spm2[.exe] <файл проекта> [опции]

Опции запуска приведены ниже в таблице.

Опция Назначение
/script SMP только обрабатывает исходные файлы и создает результирующий скрипт с именем <файл проекта>.SQL, не транслируя код на сервер.
/build SPM транслирует все файлы на сервер независимо от того, изменялся текст или нет (аналог Rebuild All в различных средах разработки)
/debug SMP определяет макро SPM_DEBUG, который можно использовать для условной трансляции в коде, например:ifdef({SPM_DEBUG}, {SELECT 'Debug mode' AS mode})
/m4: Передает в M4 параметр командной строки. Можно задавать более одной опции /m4

Как настроить 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-синтаксиса.

Информация об изменениях и версиях

В дистрибутив помимо исходных файлов и исполняемого модуля (EXE) включаются файлы:

changes.txt хронологический лист регистрации изменений
license.txt лицензионная информация
Прикрепленный файлРазмер
Package icon SPM2_full.zip406.34 KB

Комментарии

Идея давно и

Идея давно и успешно эксплуатируемая компанией "Заказные информационные системы", они на данной технологии даже клиентов пишут. См - http://www.custis.ru/html/custis-libs.htm, то что вы описываете у них фигурирует как CustIS SQL Tools

Изображение пользователя Serguei_Tarassov.

Давно

Не знаю, насколько давно использует упомянутая компания (судя по версии оракла - давно, дальнейших им успехов), а мы успешно используем подход с 1996 года. См. историю.

Изображение пользователя ipanshin.

На самом деле

На самом деле сам подход с бородой. Аналогичным образом построен AMDASM - AMD assembler фирмы AMD, который использовался для построения языка ассемблера для разнообразных процессоров и микроконтроллеров, и процессоров цифровой обработки сигналов. У меня гдето даже исходники на с есть.

Изображение пользователя Serguei_Tarassov.

Макроассемблер

Макроассемблеру вообще лет чуть меньше, чем программированию на ассемблере. 1950-е гг, примерно.

Вопросик есть

даже несколько :)
Преамбула:
Как пользователь конкурирующего продукта GOLDS подтверждаю полезность макроподстановок в SQL коде. Такие средства "малой механизации" существенно экономят время и делают исходные тексты более понятными.
Кроме того, такой макроязык по определению самодокументирующийся - можно посмотреть определение любой макроподстановки.
С другой стороны, есть опасность возникновения "диалектов", когда разработчики начинают писать собственные частные макросы. На больших проектах обязательно нужно иметь выделенного "инструментальщика" для доработки макросов. Остальные должны их только использовать.

Вопросы:
1. Из описания вытекает, что SPM - чистый макропроцессор. Однако при работе с БД, нужно иметь возможность генерировать скрипты на изменение, если объект в исходном файле изменен (alter ...). Как решается такая задача?
2. Из примера файла описания проекта не понятно, что будет на выходе - 3 .sql файла или один? Есть возможность управлять выходом?

Изображение пользователя Serguei_Tarassov.

Ответы

1. SPM не занимается сравнением БД (варианты: БД и SQL-скрипта, двух SQL-скриптов) для генерации некоего результирующего SQL-скрипта разности (diff). Это отдельная нетривиальная задачка, инструментов для частных ее решений много (гуголь: database difference).

2. На выходе по одному SQL-скрипту на каждый исходный SQM-файл плюс генерируется общий SQL-скрипт, в который все SQL-скрипты включаются согласно описанию в файле проекта.

Подредактируй заголовок

Надо заголовок поправить. Фраза "Создайте свой проблемный язык" - вопринимается, как сделайте себе головную боль :).