Диаграммы классов UML из PostgreSQL. Часть первая

от автора

Статья продолжает знакомить с функциями для документирования баз данных PostgreSQL. Но на этот раз речь пойдет о специальных функциях, подготавливающих описания диаграмм классов на языке PlantUML.

В качестве основного средства документирования выбрана система управления проектами TRAC с подключенным плагином plantuml.

В первой половине статьи изложены комментарии к реализации функций. Во второй- исходные тексты функций, а также пошаговые инструкции включения PlantUML-скриптов в карточки TRAC, и тестирования этих скриптов на сайте PlantText UML редактора. Тем из читателей, кого интересуют только исходные тексты или пошаговые инструкции, предлагаем сразу перейти к Приложению.

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

Все тексты на PLpgSQL написаны в для версии PosthgreSQL 9.6.

Содержание

  1. Назначение функций

  2. Общая структура функций

  3. Процедура umlpr_TablesScipt_FromArray — Выгрузка из списка таблиц

  4. Процедура umlpr_TablesScipt_ByWhereOption —Выгрузка по условию

  5. Функция umlfn_Table_fromArray —PlantUML-скрипт из списка таблиц

  6. Функция umlfn_Table_AllGroupScript —PlantUML-скрипт по условию

  7. Функция umlfn_Table_Script — PlantUML-скрипт таблицы с атрибутами

  8. Функция umlfn_Attribute_String —PlantUML-скрипт атрибута таблицы

  9. Функция umlfn_Table_LinksFromArray —PlantUML-скрипт связей

  10. ПРИЛОЖЕНИЕ 1.

    1. Создание процедуры umlpr_TablesScipt_FromArray

    2. Создание процедуры umlpr_TablesScipt_ByWhereOption

    3. Создание функции umlfn_Table_fromArray

    4. Создание функции umlfn_Table_AllGroupScript

    5. Создание функции umlfn_Table_Script

    6. Создание функции umlfn_Attribute_String

    7. Создание функции umlfn_Table_LinksFromArray

  11. ПРИЛОЖЕНИЕ 2. Дополнительные материалы

    1. Пошаговая инструкция просмотра диаграмм классов

    2. Пошаговая инструкция создания карточки TRAC

Назначение функций

PlantTest UML class diagram

Рис. 1. Пример диаграммы классов, созданной на языке PlantUML

Функции, описанные в предыдущих статьях, возвращали сведения об объектах баз данных (отношениях(таблицах), атрибутах таблиц, ограничениях (constraints), индексах и т.д.) в форме списков. Эти списки можно включать в документ, описывающий базу данных проекта, в виде таблиц. Но для документирования связей между таблицами списковая форма не слишком наглядна. Другое дело ER-диаграммы или диаграммы классов UML, такие как показана на Рис. 1. Обычно такие диаграммы создаются специальными графическими средствами, такими, например, как ERwin Data Modeler[*1] , Microsoft Visio[*2] , к недостаткам которых можно отнести отсутствие или сложность связи с существующей базой данных. Альтернативой графическим редакторам стала технология создания диаграмм из их текстовых описаний, которые создаются на на языке PlantUML. Эта технология предполагает создание UML за два шага — сначала создается описание или PlantUML-скрипт, который затем загружается в среду, преобразующую его в диаграмму.

Описываемые в этом документе функции предназначены для создания PlantUML-скриптов из данных системных каталогов PostgreSQL. Основной формат создаваемых PlantUML-скриптов соответствует требованиям плагина plantuml для системы управления проектами TRAC[*3] . Дополнительно описываемые функции могут создавать скрипты классической формы без дополнительной обёртки, необходимой для TRAC.

Общая структура функций

Головной функцией, создающей PlantUML-скрипты является umlfn_Table_fromArray. Она преобразует массив названий таблиц (отношений) в PlantUML-скрипт для последующего отображения в форме диаграммы классов UML.

Table_FromArrayUMLStructure

Рис. 2. Структура вызовов функций в процессе создания PlantUML— скрипта

Дополнительно PlantUML-скрипты могут быть созданы функцией umlfn_Table_AllGroupScript, которая по заданному условию формирует массив таблиц из каталога pg_class и вызывает головную функцию umlfn_Table_fromArray.

На Рис. 2 показана схема взаимодействия функций в процессе создания PlantUML-скрипты. На ней основные функции имеют префикс umlfn_или umltf. Остальные функции — вспомогательные, предназначены для доступа и обработки данных из системных каталогов.

Таблица 1 содержит список и краткое назначение основных функций.

FunStructure_Tbl001

Таблица 1. Назначение основных функций

Таблица 2 содержит список и краткое назначение только тех вспомогательных функций, которые не описаны в следующих статьях «Функции для документирования баз данных PostgreSQL»:

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

FunStructure_Tbl002

Таблица 2. Назначение вспомогательных функций

Созданные PlantUML-скрипты могут быть выгружены в текстовый файл.

PlantUML procedures

Рис. 3. Схема взаимодействия основных функций и процедур

Для выгрузки PlantUML-скриптов используются хранимые процедуры, которые вызывают головную или дополнительную функции, а их результат сохраняют в текстовом файле с помощью оператора COPY TO. Схема взаимодействия основных функций и процедур приведена на Рис. 3.

Таблица 3 содержит список и краткое назначение основных процедур.

FunStructure_Tbl003

Таблица 3. Назначение основных процедур

Процедура umlpr_TablesScipt_FromArray

Процедура umlpr_TablesScipt_FromArray выгружает в текстовый файл PlantUML-скрипт, созданный из массива с названиями таблиц функцией umlfn_Table_fromArray.

В качестве основных параметров процедура принимает массив названий таблиц (a_TableNameArray), путь к папке, к которую должен быть выгружен PlantUML-скрипт (a_OutputFolder) и название схемы, в пределах которой они находятся таблицы (a_SchemaName). Дополнительными параметрами являются: «Признак необходимости включения комментария атрибута» (a_NeedAttrDesc) и «Формат возвращаемого PlantUML-скрипта: ‘Trac’ или ‘PlantTest’» (a_Mode).

Название выгружаемого файла имеет один из следующих двух видов:

  1. plantuml_YYYY-MM-DD;

  2. plantuml_YYYY-MM-DD_classic

Файлы с именем второго вида создаются, если параметр a_Mode имеет значение ‘PlantTest’. На месте шаблона ‘YYYY-MM-DD’ в названии указывается дата создания файла, в которой ‘YYYY’ — год, ‘MM’ — порядковый номер месяца в году, ‘DD’ — день в месяце.

COPY_umlpr_Tables_fA_inside001
Скрытый текст
COPY (SELECT unnest FROM unnest(ARRAY[umlfn_Table_FromArray(a_SchemaName::VARCHAR, a_TableNameArray, FALSE,a_Mode)])) TO  ''' || a_OutputFile||'plantuml_'||TO_CHAR(current_date, 'YYYY-MM-DD')|| CASE a_Mode WHEN 'PlantTest' THEN '_classic' ELSE '' END||'.txt'''; 

Рисунок, содержащий оператор COPY выгружающий в текстовый файл PlantUML-скрипт, представляет собой принципиальную схему того, как результат выполнения функции umlfn_Table_fromArray. Но из-за особенностей оператора COPY в формат PlantUML-скрипта приходится внести изменения. Дело в том, что umlfn_Table_fromArray возвращает текстовую переменную, состоящую из не заключённых в кавычки подстрок, а для нормального выполнения оператора COPY наоборот каждая подстрока должна быть заключена в кавычки. При этом, после преобразования исходного формата в массив строк, в выходной файл строки выгружаются уже без кавычек.

COPY_umlpr_Tables_fA_inside002
Скрытый текст
v_PlantUML_Script:= umlfn_Table_FromArray(a_SchemaName::VARCHAR, a_TableNameArray, FALSE,a_Mode); v_PlantUML_Script:= ''''||REPLACE(v_PlantUML_Script,CHR(13)||CHR(10),''', ''')||''''; COPY (SELECT unnest FROM unnest(ARRAY[v_PlantUML_Script])) TO  ''' || a_OutputFile||'plantuml_'||TO_CHAR(current_date, 'YYYY-MM-DD')|| CASE a_Mode WHEN 'PlantTest' THEN '_classic' ELSE '' END||'.txt'''; 

В новой версии рисунка учтена необходимость предварительного заключения всех подстрок PlantUML-скрипта в кавычки. Это преобразование выполняется во второй строке.

PlantUML Scripts

Рис. 4. Пример папки с выгруженными файлами, содержащими PlantUML-скрипты

Рис. 4 демонстрирует вариант папки с файлами, выгруженными процедурой umlpr_TablesScipt_FromArray. Содержание файлов подробно описано в разделе «Функция umlfn_Table_fromArray…»

Процедура umlpr_TablesScipt_ByWhereOption

Процедура umlpr_TablesScipt_ByWhereOption выгружает в текстовый файл PlantUML-скрипт, созданный из массива с названиями таблиц, найденных по заданному параметром условию. Непосредственно PlantUML-скрипт создаётся функцией umlfn_Table_fromArray.

В качестве основных параметров принимает условие поиска таблиц (a_WHEREoption), которое не содержит ключевое слово WHERE, путь к папке, к которую должен быть выгружен PlantUML-скрипт (a_OutputFolder) и название схемы, в пределах которой они находятся таблицы (a_SchemaName). Дополнительными параметрами являются: «Признак необходимости включения комментария атрибута» (a_NeedAttrDesc) и «Формат возвращаемого PlantUML-скрипта: ‘Trac’ или ‘PlantTest’» (a_Mode).

Выполнение процедуры сводится к получению списка (массива) функций по заданному условию с помощью функции admfn_Table_TableNameArray, с последующим вызовом процедуры umlfn_Table_fromArray.

SELECT_uml_Tables_bC_inside
Скрытый текст
SELECT umlpr_TablesScipt_FromArray (admfn_Table_TableNameArray(a_SchemaName,a_WHEREoption), a_OutputFolder, a_SchemaName,v_Mode);

При описании условия выбора таблиц следует учесть названия псевдонимов (aliases) каталогов, которые используются в функции. Так для каталога pg_class используется псевдоним (alias) «tbl», а для каталога pg_namespace — «nsp».

Функция umlfn_Table_fromArray

Функция umlfn_Table_fromArray возвращает PlantUML-скрипт, созданный из массива с названиями таблиц.

В качестве основных параметров функция принимает массив названий таблиц (a_TableNameArray) и название схемы, в пределах которой они созданы (a_SchemaName). Дополнительными параметрами являются: «Признак необходимости включения комментария атрибута» (a_NeedAttrDesc) и «Формат возвращаемого PlantUML-скрипта: ‘Trac’ или ‘PlantTest’» (a_Mode).

SELECT_uml_Tables_fA_inside v2
Скрытый текст
SELECT INTO v_TableGroupScript, v_TableGroupLegendScript STRING_AGG (umlfn_Table_Script(a_SchemaName,tbl.relname,FALSE,cnfn_Table_LowerName(a_TableNameArray),'') AS v_TableGroupScript  '''legend center'''||CHR(13)||CHR(10)||'''<b><i><u>ТАБЛИЦЫ</u></i></b>'''|| CHR(13)||CHR(10)||''' '''|| CHR(13)||CHR(10)|| STRING_AGG (quote_literal('<b>'||UPPER(ftbl.relname)||'</b>'||'- '||COALESCE(dsc.description,''))|| CHR(13)||CHR(10),'')|| '''endlegend'''|| CHR(13)||CHR(10) AS v_TableGroupLegendScript FROM pg_class tbl  INNER JOIN pg_namespace nsp ON tbl.relnamespace = nsp.oid  LEFT OUTER JOIN pg_Description dsc ON tbl.oid=dsc.objoid AND dsc.objsubid=0 WHERE LOWER(nsp.nspname)=LOWER(a_SchemaName) AND tbl.relkind='r' AND tbl.relname !~* E'(raster_|spatial_|geometry_|geography_)'  AND ARRAY[LOWER(tbl.relname)::TEXT] <@ cnfn_Array_LowerCase(a_TableNameArray)::TEXT[] 

Основные данные функция извлекает из записи каталога pg_class, содержащего кроме записей о таблицах еще и, записи о последовательностях, представлениях, материализованных представлениях, составных типах. Поэтому для выбора таблиц используется условие relkind=‘r’.

Дополнительно функция обращается к данным каталогов pg_namespace и pg_description. Первый содержит названия схем базы данных, а второй — комментарии ко всем объектам БД.

Здесь важно обратить внимание на условие objsubid=0. Оно определяет комментарий к таблице, т к. значение поля objoid одинаково как для таблицы, так и для ее атрибутов. Комментарий к атрибуту таблицы содержится в записи, в которой objsubid совпадает с номером этого атрибута.

Кроме того, в условии выбора исключаются таблицы PostgreSQL-расширения (EXTENSION) postgis, а также все элементы исходного массива названий функций переводятся в нижний регистр при помощи вспомогательной функции cnfn_Array_LowerCase.

С помощью оператора SELECT из данных исходных таблиц группируются две части PlantUML-скрипта: v_TableLinksScript— список таблиц с их атрибутами, v_TableGroupLegendScript — легенда предыдущего списка, т.е. названия таблиц с комментариями к ним.

SELECT_uml_Tables_fA_inside 002
Скрытый текст
v_TableLinksScript:=umlfn_Table_LinksFromArray(a_SchemaName, a_TableNameArray); v_TableGroupScript:=v_TableGroupScript ||COALESCE(v_TableLinksScript,'') ||v_TableGroupLegendScript||v_TableGroupScriptSuffix; 

Для описания связей заданных таблиц вызывается функция umlfn_Table_LinksFromArray, которая анализирует внешние ключи заданных таблиц, устанавливает обнаруженные связи, а также обозначает характер этих связей: «*-» — многие к одному, «-*»— один ко многим, «1-1» — один к одному. Таблица 4 содержит описаниие символов связи таблиц из руководства по языку PlantUML.

uml_Tables_fA_Tbl004

Таблица 4. Описание символов связи в документации к PlantUML

Последним оператором все части PlantUML-скрипта соединяются в нужной последовательности. При этом, в начало строки добавляется признак, идентифицирующий PlantUML-скрипт, а в конец полученной строки признак PlantUML-скрипта.

Таблица 5 позволяет представить результат выполнения функции umlfn_Table_fromArray, а также состав его частей.

uml_Tables_fA_Tbl005

Таблица 5. Результат выполнения функции umlfn_Table_FromArray(‘public’::VARCHAR, ‘{Street, StreetType, StreetType, STREETSYNONYM}’::VARCHAR(256)[])
Скрытый текст

Таблица 5 демонстрирует PlantUML-скрипт как набор подстрок, расположенных сверху вниз. В тоже время, в теле хранимых функций и процедур эти подстроки образуют значение одной текстовой (TEXT) переменной, в которой они разделены символами конца строки (CHR(13) — «Возврат каретки» и CHR(10) — «перевод строки»). Иногда текст PlantUML-скрипта необходимо преобразовать в массив подстрок. Этим объясняется то, что каждая отдельная подстрока заключена в одиночные кавычки.

SELECT_uml_Tables_fA_inside 003
v_TableGroupScript:=ARRAY_TO_STRING(cnfn_Array_QuotesWrapperWithout(STRING_TO_ARRAY(v_TableGroupScript, CHR(13)||CHR(10))), CHR(13)||CHR(10)); 

Но на выходе из umlfn_Table_fromArray одиночные кавычки не нужны. Поэтому текст временно преобразуется в массив, в каждом элементе которого убираются начальная и замыкающая кавычки. А затем массив снова преобразуется в строку, помещённую в тестовой переменной.

Обычно функция возвращает PlantUML-скрипт в формате плагина plantuml для системы управления проектами TRAC, но если дополнительный параметр a_Mode имеет значение ‘PlantTest’», то обёртка скрипта ограничивается «@startuml…@enduml». Где @startuml — оператор начала скрипта, @enduml—окончания.

Исходный код функции можно посмотреть здесь.

Функция umlfn_Table_AllGroupScript

Функция umlfn_Table_AllGroupScript возвращает PlantUML-скрипт, созданный таблиц, найденных по заданному параметром условию.

В качестве основных параметров функция принимает условие поиска таблиц (a_WHEREoption), которое не содержит ключевое слово WHERE, и название схемы, в пределах которой будет вестись поиск (a_SchemaName). Дополнительными параметрами являются: «Признак необходимости включения комментария аттрибута» (a_NeedAttrDesc) и «Формат возвращаемого PlantUML-скрипта:‘Trac’ или ‘PlantTest’» (a_Mode).

В теле функции для преобразования условия выборки в массив названий таблиц вызывается функция admfn_Table_TableNameArray и этот массив затем передается в качестве параметра функции umlfn_Table_fromArray, которая уже непосредственно создает PlantUML-скрипт.

SELECT_uml_Tables_AGS_inside
Скрытый текст
v_TableGroupScript:=umlfn_Table_FromArray(a_SchemaName, admfn_Table_TableNameArray(a_SchemaName,a_WHEREoption),a_NeedAttrDesc,v_Mode);

При описании условия выбора таблиц следует учесть названия псевдонимов (aliases) каталогов, которые используются в функции. Так для каталога pg_class используется псевдоним (alias) «tbl», а для каталога pg_namespace«nsp».

Таблица 6 показывает пример результата, возвращаемого функцией при корректном значении параметра a_WHEREoption, в режиме a_Mode=’PlantTest’.

Таблица 6. Результат выполнения функции umlfn_Table_AllGroupScript(‘public’,’tbl.relname ~* E»^Street»’, FALSE, ‘PlantTest’)

uml_Tables_AGS_Tbl006

Таблица 6. Результат выполнения функции umlfn_Table_AllGroupScript(‘public’,’tbl.relname ~* E»^Street»’, FALSE, ‘PlantTest’)

Исходный код функции можно посмотреть здесь.

Функция umlfn_Table_Script

Функция umlfn_Table_fromArray возвращает часть PlantUML-скрипта по названию одной таблицы с её атрибутами.

В качестве основных параметров функция принимает названиие таблицы (a_TableName) и название схемы, в пределах которой они созданы (a_SchemaName). Дополнительными параметрами являются: «Признак необходимости включения комментария аттрибута» (a_NeedAttrDesc) и «Массив таблиц допустимых для поиска внешних ключей таблиц» (a_AllowedTableName).

SELECT_uml_Table_S_inside
Скрытый текст
SELECT '''object '|| a_SchemaName ||'.'||a_TableName||'{'''|| CHR(13)||CHR(10)|| STRING_AGG (umlfn_Attribute_String(oattr.oid, oattr.attnum,a_NeedAttrDesc,a_AllowedTableName),'')|| '''}'''|| CHR(13)||CHR(10) FROM (SELECT tbl.oid, attr.attnum FROM pg_attribute attr  WHERE attr.attrelid=( a_SchemaName ||'.'|| a_TableName)::regclass AND attr.attnum>0 ORDER BY tbl.relname,attr.attnum) oattr; 

Основные данные функция извлекает из записи каталога pg_attribute, который содержит записи с данными об атрибутах таблиц, представлений, материализованных представлений, составных типов и даже функций.

Явное обращение к данным каталогов pg_namespace и pg_class отсутствует благодаря использованию псевдонима regclass, преобразующего квалифицированное имя таблицы в её системный ИД (OID).

Здесь важно обратить внимание на условие attnum>0. Оно определяет наличие типа атрибута в каталоге pg_type типов данных.

С помощью оператора SELECT из данных исходных атрибутов группируется часть PlantUML-скрипта: v_TableScript —таблица со списком её атрибутов. Описание каждого атрибута выполняется функцией umlfn_Attribute_String.

Таблица 7 позволяет представить результат выполния функции umlfn_Table_fromArray, а также состав его частей.

uml_Table_S_Tbl007

Таблица 7. Результат выполнения функции umlfn_Table_Script(‘public’,’Street’,TRUE)

Исходный код функции можно посмотреть здесь.

Функция umlfn_Attribute_String

Функция umlfn_Attribute_String возвращает часть PlantUML-скрипта для одного атрибута по его названию.

В качестве основных параметров функция принимает системный идентификатор (OID) таблицы (a_TableOID) и порядковый номер атрибута в этой таблице (a_AttributeNo). Дополнительными параметрами являются: «Признак необходимости включения комментария атрибута» (a_NeedAttrDesc) и «Массив таблиц допустимых для поиска внешних ключей таблиц» (a_AllowedTableName). При этом значение последнего параметра (a_AllowedTableName) не используется. Как говорится, создан в расчёте на будущее усовершенствование функции.

Основные данные функция получает как результат выполнения другой функции admtf_Attribute_Features, которому передаются значения параметров a_TableOID и a_AttributeNo. Подробное описание этой функции можно найти в документе «Функции для документирования баз данных».

SELECT_uml_Attribute_S_inside
Скрытый текст
SELECT ass.AttString||STRING_AGG(ass.FKString,'') FROM (SELECT TRIM(af.rsa_AttributeName)||':'|| ' '||CASE WHEN af.rsa_Description IS NULL OR NOT a_NeedAttrDesc THEN '' ELSE '(<i>'||af.rsa_Description||'</i>)' END|| ' '||af.rsa_TypeName|| ' '||CASE WHEN af.rsa_isNotNULL THEN 'NOT' ELSE '' END || 'NULL' || ''|| CASE WHEN af.rsa_isAttributePK THEN '(PK'||TRIM(COALESCE(TO_CHAR(af.rsa_ColumnPKNo,'999'),''))||')'  ELSE '' END AS AttString, '(FK'||TRIM(COALESCE(TO_CHAR(af.rsa_ColumnFKNo[af.fkInx],'999'),''))||' '||COALESCE(af.rsa_FKTableName[af.fkInx],'')|| '('||COALESCE(af.rsa_FKTableColumnName[af.fkInx],'')||')'||')' FKString FROM (SELECT iaf.rsa_AttributeName,iaf.rsa_Description,iaf.rsa_TypeName,iaf.rsa_isNotNULL,iaf.rsa_isAttributePK,iaf.rsa_ColumnPKNo, iaf.rsa_isAttributeFK,iaf.rsa_ColumnFKNo,iaf.rsa_FKTableName,iaf.rsa_FKTableColumnName, GENERATE_SUBSCRIPTSs(iaf.rsa_ColumnFKNo, 1) fkInx FROM admtf_Attribute_Features(a_TableOID , a_AttributeNo) iaf) af ORDER BY fkInx) ass GROUP BY  ass AttString; 

Некоторая громоздкость приведенного оператора SELECT вызвана тем, что функция admtf_Attribute_Features, как показывает Таблица 8, возвращает характеристики внешних ключей в виде массивов. Отсюда возникла необходимость использования функции GENERATE_SUBSCRIPTS и последующей группировкой данных о внешнем ключе. Хотя, возможно, от такой группировки следует отказаться в будущем.

uml_Attribute_S_Tbl008

Таблица 8. Характеристики внешнего ключа, возвращаемые функцией admtf_Attribute_Features

Кроме того, при формировании строки с описанием атрибута учитывается значение параметра a_NeedAttrDesc, который указывает на то, добавлять ли в него комментарий к названию атрибута или нет.Остальные данные атрибута просто соединяются в порядке и формате, которые указаны в требования к языку PlantUML.

Таблица 9 содержит пример выполнения функции umlfn_Attribute_String, особенность которого в том, что параметр a_NeedAttrDesc=‘TRUE’, а параметр a_TableOID задан при помощи псевдонима regclass, что более надёжно, чем использовать явное значение OID таблицы, т.к. последний может быть изменён в процессе эксплуатации базы данных.

uml_Attribute_S_Tbl009

Таблица 9. Результат выполнения функции umlfn_Attribute_String(‘public.Street’::REGCLASS, 2::SMALLINT, TRUE)

Исходный код функции можно посмотреть здесь.

Функция umlfn_Table_LinksFromArray

Функция umlfn_Table_LinksFromArray возвращает часть PlantUML-скрипт со списком связей, созданных из массива с названиями таблиц. В качестве основных параметров функция принимает массив названий таблиц (a_TableNameArray) и название схемы, в пределах которой они созданы (a_SchemaName).

Основные данные функция извлекает из записей каталога pg_constraint. Каталог pg_constraint при условии contype=‘f’ содержит записи с характеристиками внешних ключей таблиц, которые связывают записи из каталога pg_class, принадлежащие к типу relkind=‘r’. Для преобразования названия внешний ключей к характеристикам, соответствующей связи таблиц (‘N:1’,‘1:1’) используется функция admfn_Table_LinkSign.

Дополнительно функция обращается к данным каталога pg_namespace, содержащего названия схем базы данных.

SELECT_uml_Table_LfA_inside
Скрытый текст
SELECT STRING_AGG(''''||LOWER(nsp.nspname)||'.'||UPPER(tbl.relname)||' '|| CASE LEFT(ls.*,1) WHEN 'N' THEN '*' ELSE '' END || '--' || CASE  RIGHT(ls.*,1) WHEN 'N' THEN '*' ELSE '' END|| ' '||LOWER(nsp.nspname)||'.'||UPPER(Ftbl.relname)||''''||CHR(13)||CHR(10),'') FROM pg_class tbl  INNER JOIN pg_namespace nsp ON tbl.relnamespace = nsp.oid  INNER JOIN pg_constraint lcon ON lcon.conrelid=tbl.oid INNER JOIN pg_class ftbl ON lcon.confrelid=ftbl.oid INNER JOIN pg_namespace fnsp ON ftbl.relnamespace=fnsp.oid, LATERAL admfn_Table_LinkSign(nsp.nspname,tbl.relname:: VARCHAR(256),lcon.conname:: VARCHAR(256)) ls WHERE LOWER(nsp.nspname)=LOWER(a_SchemaName) AND tbl.relkind='r'  LOWER(fnsp.nspname)=LOWER(a_SchemaName) AND ftbl.relkind='r'  AND lcon.contype ='f' AND ARRAY[tbl.relname::VARCHAR(256)] <@ admfn_Table_LowerName(a_TableNameArray)  AND ARRAY[ftbl.relname::VARCHAR(256)] <@ admfn_Table_LowerName(a_TableNameArray); 

Как видно из приведённого оператора, характеристики связи, возвращаемые функцией admfn_Table_LinkSign, преобразуются так:

  • символ ‘N’ заменяется на ‘*’;

  • ‘1’ — на » (пустую строку);

  • ‘:’ — на ‘—‘.

Связываемые таблицы просто соединяются в порядке, которые указаны в требованиях к языку PlantUML.

Таблица 10 содержит пример выполнения функции umlfn_Table_LinksFromArray.

uml_Table_LfA_Tbl010

Таблица 10. Результат выполнения функции umlfn_Table_LinksFromArray(‘public’, ‘{Street, StreetType, StreetSynonym, StreetTypeSynonym}’)

Исходный код функции можно посмотреть здесь.

ПРИЛОЖЕНИЕ

Создание процедуры umlpr_TablesScipt_FromArray

Комментарии к исходному коду процедуры можно посмотреть здесь.

Скрытый текст
BEGIN TRANSACTION; DROP FUNCTION IF EXISTS umlpr_TablesScipt_FromArray(a_TableNameArray VARCHAR(256)[],a_OutputFolder TEXT,a_Schema VARCHAR(256), a_Mode VARCHAR(20));  /****************************************************************************************************************/ /* Создание файла с описанием таблиц из исходного массива в формате плагина (plantuml)                          */ /****************************************************************************************************************/ CREATE OR REPLACE FUNCTION umlpr_TablesScipt_FromArray (a_TableNameArrayVARCHAR(256)[], /* Исходный массив  таблиц  */ a_OutputFolder TEXT, /* Папка создаваемого файла*/ a_SchemaVARCHAR(256) DEFAULT 'public',/*Схема исходных таблиц*/ a_ModeVARCHAR(20) default 'Trac'/* Формат возвращаемой строки:*/ /* 'Trac' -для  средства управления проектам; */ /*'PlantTest' - для тестирования на сайте*/ /* https://www.planttext.com/  */ )  RETURNS INTEGER AS $BODY$ DECLARE c_SchemaCONSTANT name:='public'; c_NeedAttrDescCONSTANT BOOLEAN:=FALSE;/* Признак необходимости включения комментария аттрибута  */ c_TracModeCONSTANT VARCHAR(50):='Trac'; /*для  средства управления проектам*/ c_PlantTestModeCONSTANT VARCHAR(50):='PlantTest'; /*для тестирования на сайте "https://www.planttext.com/" */  v_SchemaVARCHAR(256); /*Схема исходных таблиц*/ v_ModeVARCHAR(20); /* Формат возвращаемой строки: 'Trac' -для  средства управления проектам;*/ /* 'PlantTest' - для тестирования на сайте https://www.planttext.com/  */ v_Return_Error Integer := 0; /* Код возврата*/ v_OutputFile TEXT; /* Путь и название создаваемого файла*/ v_COPY_StatementTEXT; /* Оператор копирования скрипта в файл*/ v_PlantUML_ScriptTEXT; /* Сгенерированный скрипт*/ v_TableNameArrayVARCHAR(256)[];/* Исходный массив  таблиц  */  BEGIN v_Mode:=COALESCE(a_Mode,c_TracMode); v_Schema:=COALESCE(a_Schema,c_Schema); v_TableNameArray:=a_TableNameArray; v_OutputFile:=TRIM(a_OutputFolder)||'plantuml_'||current_date||CASE v_Mode WHEN c_PlantTestMode THEN '_classic' ELSE '' END||'.txt'; v_PlantUML_Script:= umlfn_Table_FromArray(v_Schema::VARCHAR,v_TableNameArray,c_NeedAttrDesc,v_Mode); v_PlantUML_Script:=''''||REPLACE(v_PlantUML_Script,CHR(13)||CHR(10),''', ''')||''''; v_COPY_Statement='COPY (SELECT unnest FROM unnest(ARRAY['|| v_PlantUML_Script || '])) TO  ''' || v_OutputFile||''''; BEGIN     EXECUTE v_COPY_Statement; EXCEPTION WHEN OTHERS THEN RAISE NOTICE 'ОШИБКА ПУТИ  к папке создаваемого файла. Проверьте правильность значений параметров.               ПАРАМЕТРЫ создания: ******************************************************************** Путь            - "%" Массив таблиц   - "%" Схема           - "%"                                         ***********************************************************',                                        v_OutputFile,v_TableNameArray,v_Schema;                  RETURN -2;                                END; RETURN v_Return_Error;   END   $BODY$  LANGUAGE plpgsql; COMMENT ON FUNCTION umlpr_TablesScipt_FromArray(a_TableNameArray VARCHAR(256)[],a_OutputFolder TEXT,a_Schema VARCHAR(256),a_Mode VARCHAR(20)) IS  'Создание файла с описанием таблиц из исходного массива в формате плагина (plantuml)';  --ROLLBACK TRANSACTION; COMMIT TRANSACTION; SELECT umlpr_TablesScipt_FromArray('{Street,StreetType,StreetTypeSynonym,STREETSYNONYM}'::VARCHAR(256)[], 'D:\plantuml\Scripts\','public','PlantTest' ); SELECT umlpr_TablesScipt_FromArray('{Street,StreetType,StreetTypeSynonym,STREETSYNONYM}'::VARCHAR(256)[], 'D:\plantuml\Scripts\','public'); 

Создание процедуры umlpr_TablesScipt_ByWhereOption

Комментарии к исходному коду процедуры можно посмотреть здесь.

Скрытый текст
BEGIN TRANSACTION; DROP FUNCTION IF EXISTS umlpr_TablesScipt_ByWhereOption(a_WHEREoption VARCHAR(1000),a_OutputFolder TEXT,a_Schema VARCHAR(256), a_Mode VARCHAR(20));  /********************************************************************************************************************/ /* Создание файла с описанием таблиц по условию выбора таблиц из системного каталога в формате плагина (plantuml)   */ /********************************************************************************************************************/ CREATE OR REPLACE FUNCTION umlpr_TablesScipt_ByWhereOption (a_WHEREoptionVARCHAR(1000), /* условие запроса на выбор таблиц из системного каталога  */ a_OutputFolderTEXT, /* Папка создаваемого файла*/ a_SchemaVARCHAR(256) DEFAULT 'public',/*Схема исходных таблиц*/ a_ModeVARCHAR(20) default 'Trac'/* Формат возвращаемой строки: */ /* 'Trac' -для  средства управления проектам;*/ /*'PlantTest' - для тестирования на сайте */ /*https://www.planttext.com/  */ )  RETURNS INTEGER AS $BODY$ DECLARE v_TableNameArrayVARCHAR(256)[]; /* Массив выбранных таблиц  */ v_Return_Error Integer := 0; /* Код возврата */  BEGIN v_TableNameArray:=admfn_Table_TableNameArray(a_Schema,a_WHEREoption); v_Return_Error:=umlpr_TablesScipt_FromArray(v_TableNameArray,a_OutputFolder,a_Schema,a_Mode); RETURN v_Return_Error; END   $BODY$  LANGUAGE plpgsql; COMMENT ON FUNCTION umlpr_TablesScipt_ByWhereOption(a_WHEREoption VARCHAR(1000),a_OutputFolder TEXT,a_Schema VARCHAR(256),a_Mode VARCHAR(20)) IS 'Создание файла с описанием таблиц по условию выбора таблиц из системного каталога в формате плагина (plantuml) ';  --ROLLBACK TRANSACTION; COMMIT TRANSACTION; /*SELECT umlpr_TablesScipt_ByWhereOption('tbl.relname LIKE ''id_districts'' OR tbl.relname LIKE ''id_nps'''::VARCHAR(1000), 'D:\Projects\Enisey GIS\DB\PLpgSQL\Common\DBAdministrate\plantuml\NONScripts\' ); SELECT umlpr_TablesScipt_ByWhereOption('tbl.relname LIKE ''id_districts'' OR tbl.relname LIKE ''id_nps'''::VARCHAR(1000), 'D:\Projects\Enisey GIS\DB\PLpgSQL\Common\DBAdministrate\plantuml\Scripts\' ,'public','Trac'); SELECT umlpr_TablesScipt_ByWhereOption('tbl.relname LIKE ''id_districts'' OR tbl.relname LIKE ''id_nps'''::VARCHAR(1000), 'D:\Projects\Enisey GIS\DB\PLpgSQL\Common\DBAdministrate\plantuml\Scripts\','public','PlantTest'); */ SELECT umlpr_TablesScipt_ByWhereOption('tbl.relname ~* E''^street''', 'D:\Projects\Enisey GIS\DB\PLpgSQL\Common\DBAdministrate\plantuml\Scripts\','public','PlantTest');  SELECT umlpr_TablesScipt_ByWhereOption('tbl.relname ~* E''^street''', 'D:\Projects\Enisey GIS\DB\PLpgSQL\Common\DBAdministrate\plantuml\Scripts\','public','PlantTest'); 

Создание функции umlfn_Table_fromArray

Комментарии к исходному коду функции можно посмотреть здесь.

Скрытый текст
BEGIN TRANSACTION; DROP FUNCTION IF EXISTS umlfn_Table_FromArray (a_SchemaName VARCHAR(100),a_TableNameArray VARCHAR(256)[],a_NeedAttrDesc BOOLEAN,a_Mode VARCHAR(20)); /********************************************************************************************************/ /*  Функция возвращает строку с описанием таблиц из исходного массива в формате плагина (plantuml)  */ /* к Trac — средству управления проектами и отсслеживания ошибок в программном обеспечении. */ /*------------------------------------------------------------------------------------------------------*/ /*ПРИМЕР:umlfn_Table_FromArray('public','{kmed__adres1,kmed_adres,kmed_adreskladr,kmed_adreskladr_temp,kmed_peoplebyidadreshome,kmed_radres,kmed_sadres,kmed_tadres}');*/ /*------------------------------------------------------------------------------------------------------*/ /*{{{*/ /*#!plantuml*/ /*@startuml*/ /*object public.KMED__ADRES1{*/ /*id_adres1 :  (<i>Уникальный код записи в оглавлении </i>) integer NOT NULL (PK1)*/ /*idadres :  (<i>Уникальный код записи адресного элемента (Код адреса) в kmed_ADRES</i>) integer NULL */ /*idparent :  (<i (...)*/ /**/ /********************************************************************************************************/ CREATE OR REPLACE FUNCTION umlfn_Table_FromArray (a_SchemaNameVARCHAR(100) default 'public',/* название схемы базы данных*/ a_TableNameArrayVARCHAR(256)[]default '{}',/* Исходный массив  таблиц  */ a_NeedAttrDescBOOLEAN default false,/* Признак необходимости включения комментария аттрибута  */ a_Mode        VARCHAR(20) default 'Trac'/* Формат возвращаемого PlantUML-скрипта: 'Trac' -для  средства*/ /* управления проектом; 'PlantTest' - для тестирования на сайте */ /* https://www.planttext.com/  */ ) RETURNS  TEXT AS $BODY$ DECLARE c_SchemaName                        CONSTANT VARCHAR(256):='public';/* название схемы базы данных*/ c_TableKind                         CONSTANT CHAR:='r'; c_ForeignKeyKind                    CONSTANT CHAR:='f'; c_TracMode                          CONSTANT VARCHAR(50):='Trac'; /*для  средства управления проектам*/ c_PlantTestMode                     CONSTANT VARCHAR(50):='PlantTest'; /*для тестирования на сайте "https://www.planttext.com/" */ c_TracTableGroupScriptPrefix        CONSTANT VARCHAR(50):='''{{{'''||CHR(13)||CHR(10)||'''#!plantuml'''||CHR(13)||CHR(10)||'''@startuml'''||CHR(13)||CHR(10); /* Начало скрипта описания группы таблиц в режиме 'Trac'*/ c_TracTableGroupScriptSuffix    CONSTANT VARCHAR(50):='''@enduml'''||CHR(13)||CHR(10)||'''}}}'''||CHR(13)||CHR(10)||''' '''||CHR(13)||CHR(10)||'''----'''||CHR(13)||CHR(10); /* Конец скрипта описания группы таблиц  в режиме 'Trac'*/ c_PlantTestTableGroupScriptPrefixCONSTANT VARCHAR(50):='''@startuml'''||CHR(13)||CHR(10); /* Начало скрипта описания группы таблиц  в режиме 'PlantTest'*/ c_PlantTestTableGroupScriptSuffixCONSTANT VARCHAR(50):='''@enduml'''; /* Конец скрипта описания группы таблиц  в режиме 'PlantTest'*/    c_TableGroupLegendPrefix            CONSTANT VARCHAR(100):='''legend center'''||CHR(13)||CHR(10)||'''<b><i><u>ТАБЛИЦЫ</u></i></b>'''||CHR(13)||CHR(10)||''' '''||CHR(13)||CHR(10); /* Начало раздела комментарии к таблицам группы */ c_TableGroupLegendSuffix            CONSTANT VARCHAR(100):='''endlegend'''||CHR(13)||CHR(10); /* Конец раздела комментарии к таблицам группы */  c_TableNameLegendPrefix             CONSTANT VARCHAR(10):='<b>';/* Начало наименования таблицы в комментариях*/  c_TableNameLegendSuffix             CONSTANT VARCHAR(10):='</b>';/* Окончание наименования таблицы в комментариях*/  c_TableDescriptionLegendPrefix  CONSTANT VARCHAR(10):='- ';/* Начало описания таблицы в комментариях*/   c_TableDescriptionLegendSuffix  CONSTANT VARCHAR(10):=CHR(13)||CHR(10);/* Окончание описания таблицы в комментариях*/  c_TableNameDelimiter                CONSTANT VARCHAR(5):='.';  /* Символ-разделитель имени таблицы*/ c_Blank                             CONSTANT VARCHAR(5):=' ';  /* Символ пробела*/ v_Mode                              VARCHAR(20);    /* Формат возвращаемой строки: 'Trac' -для  средства управления*/ /* проектом; 'PlantTest' - для тестирования на сайте */ /* https://www.planttext.com/  */ v_SchemaName                VARCHAR(256);   /* название схемы базы данных*/ v_TableGroupScriptPrefixVARCHAR(50);/* Начало скрипта описания группы таблиц */ v_TableGroupScriptSuffixVARCHAR(50);    /* Конец скрипта описания группы таблиц*/ v_TableGroupScript          TEXT;           /* Формируемый скрипт*/ v_TableLinksScript          TEXT;           /* Формируемый раздел связей таблиц */ v_TableGroupLegendScriptTEXT;           /* Формируемый раздел комментириев к таблицам группы*/ v_TableCount                INTEGER;        /* Счетчик таблиц группы*/ v_TableNameArray            TEXT[];         /* Массив таблиц  */ v_AloneTableName            VARCHAR(256);   /* Название одной из таблиц группы*/ v_TableDescription          TEXT;           /* Описание одной из таблиц группы*/ v_TablesRecord              RECORD;         /* Запись с данными таблицы */ v_TableOID                  OID;            /* ИД таблицы */ v_ProcessedTableNameArray   TEXT[];         /* Массив обработанных таблиц  */ v_TableNameArrayRemainder   TEXT[];         /* Массив необработанных таблиц  */ v_Return_Error              INTEGER := 0;   /* Код возврата*/ --****************************************************************************************************** BEGIN     v_Mode:=COALESCE(a_Mode,c_TracMode);     v_TableGroupScriptPrefix:=CASE v_Mode WHEN c_PlantTestMode THEN  c_PlantTestTableGroupScriptPrefix ELSE c_TracTableGroupScriptPrefix END;     v_TableGroupScriptSuffix:=CASE v_Mode WHEN c_PlantTestMode THEN  c_PlantTestTableGroupScriptSuffix ELSE c_TracTableGroupScriptSuffix END;  v_SchemaName:=COALESCE(a_SchemaName,c_SchemaName); v_TableNameArray:=a_TableNameArray; v_TableNameArray:=cnfn_Array_LowerCase(a_TableNameArray); v_TableNameArray:=string_to_array(REPLACE(REPLACE(array_to_string(v_TableNameArray,','),'''',''),'"',''),','); v_TableGroupScript:=''; v_TableGroupLegendScript:=''; IF COALESCE(v_TableNameArray,'{}')<>'{}' THEN v_TableCount:=0; v_TableGroupScript:=v_TableGroupScriptPrefix; v_TableGroupLegendScript:=c_TableGroupLegendPrefix; FOR v_TablesRecord IN SELECT ftbl.oid AS TableOID,ftbl.relname:: VARCHAR(256) FROM pg_class ftbl  INNER JOIN pg_namespace fnsp ON ftbl.relnamespace = fnsp.oid  LEFT OUTER JOIN pg_Description fdsc ON ftbl.oid=fdsc.objoid AND fdsc.objsubid=0 WHERE LOWER(fnsp.nspname)=LOWER(v_SchemaName) AND ftbl.relkind=c_TableKind AND ftbl.relname !~ '(raster_|spatial_|geometry_|geography_)'  AND ARRAY[LOWER(ftbl.relname)::TEXT] <@ v_TableNameArray  ORDER BY fnsp.nspname,ftbl.relname LOOP v_AloneTableName:=LOWER(v_TablesRecord.relname); v_AloneTableName:=v_TablesRecord.relname;     v_TableCount:=v_TableCount+1; v_TableGroupScript:=v_TableGroupScript|| umlfn_Table_Script(a_SchemaName,v_AloneTableName,a_NeedAttrDesc,v_TableNameArray); SELECT INTO v_TableDescription rs_TableDescription  FROM admtf_Table_Features (a_SchemaName,v_AloneTableName); v_TableGroupLegendScript:=v_TableGroupLegendScript|| quote_literal(c_TableNameLegendPrefix||UPPER(v_AloneTableName)||c_TableNameLegendSuffix|| c_TableDescriptionLegendPrefix||COALESCE(v_TableDescription,''))||c_TableDescriptionLegendSuffix;  v_ProcessedTableNameArray:=array_append(v_ProcessedTableNameArray, v_AloneTableName::TEXT); END LOOP; v_TableGroupLegendScript:=v_TableGroupLegendScript||c_TableGroupLegendSuffix ; v_TableLinksScript:=cnfn_Array_LowerCase(a_SchemaName,v_TableNameArray); v_TableGroupScript:=v_TableGroupScript ||COALESCE(v_TableLinksScript,'') ||v_TableGroupLegendScript||v_TableGroupScriptSuffix;END IF; RETURN v_TableGroupScript; END $BODY$ LANGUAGE plpgsql; COMMENT ON FUNCTION umlfn_Table_FromArray(a_SchemaName VARCHAR(100),a_TableNameArray VARCHAR(256)[],a_NeedAttrDesc BOOLEAN,a_Mode VARCHAR(20)) IS 'Возвращает строку с описанием таблиц массива в формате плагина (plantuml) к Trac'; --ROLLBACK TRANSACTION; COMMIT TRANSACTION; SELECT umlfn_Table_FromArray('public'::VARCHAR,'{ Street,StreetType, STREETSYNONYM }'::VARCHAR(256)[]); 

Создание функции umlfn_Table_AllGroupScript

Комментарии к исходному коду функции можно посмотреть здесь.

Скрытый текст
BEGIN TRANSACTION; DROP FUNCTION IF EXISTS umlfn_Table_AllGroupScript (a_SchemaName VARCHAR(100),a_WHEREoption VARCHAR(1000),a_NeedAttrDesc BOOLEAN,a_Mode VARCHAR(20)); /********************************************************************************************************/ /*  Функция возвращает строку с описанием группы таблиц в формате плагина (plantuml) к Trac — средству */ /*  управления проектами и отслеживания ошибок в программном обеспечении.*/ /*------------------------------------------------------------------------------------------------------*/ /*ПРИМЕР:umlfn_Table_AllGroupScript('public','tbl.relname ~* E''^Street''',FALSE,'Trac');            */ /*------------------------------------------------------------------------------------------------------*/ /*{{{                                                                                                 */ /*#!plantuml                                                                                          */ /*@startuml                                                                                           */ /*object public.STREET{                                                                               */ /*wcrccode : smallint NOT NULL (PK1)                                                                  */ /*localityid : integer NOT NULL (PK2)                                                                 */ /*streetid : smallint NOT NULL (PK3)                                                                  */ /*streettypeacrm : character(8) NULL (FK1 streettype(streettypeacrm))                                 */ /*streetname : character varying(150) NOT NULL                                                        */ /*streettsvector : tsvector NULL                                                                      */ /*streettslitevector : tsvector NULL                                                                  */ /*}                                                                                                   */ /*object public.STREETSYNONYM{                                                                        */ /*wcrccode : smallint NOT NULL (PK1)(FK1 street(wcrccode))                                            */ /*localityid : integer NOT NULL (PK2)(FK2 street(localityid))                                         */ /*streetid : smallint NOT NULL (PK3)(FK3 street(streetid))                                            */ /*synonymid : smallint NOT NULL (PK4)                                                                 */ /*streettypeacrm : character(8) NULL (FK1 streettype(streettypeacrm))                                 */ /*streetsynonymname : character varying(200) NULL                                                     */ /*}                                                                                                   */ /*object public.STREETTYPE{                                                                           */ /*streettypeacrm : character(8) NOT NULL (PK1)                                                        */ /*streettypename : character varying(30) NULL                                                         */ /*}                                                                                                   */ /*object public.STREETTYPESYNONYM{                                                                    */ /*streettypeacrm : character(8) NOT NULL (PK1)(FK1 streettype(streettypeacrm))                        */ /*synonymid : smallint NOT NULL (PK2)                                                                 */ /*streettypesynonymacrm : character varying(15) NULL                                                  */ /*}                                                                                                   */ /*public.STREETSYNONYM *-- public.STREET                                                              */ /*public.STREETSYNONYM *-- public.STREETTYPE                                                          */ /*public.STREET *-- public.STREETTYPE                                                                 */ /*public.STREETTYPESYNONYM *-- public.STREETTYPE                                                      */ /*legend center                                                                                       */ /*<b><i><u>ТАБЛИЦЫ</u></i></b>                                                                        */ /*                                                                                                    */ /*<b>STREET</b>- Список улиц в населенных пунктах                                                     */ /*<b>STREETSYNONYM</b>- Список синонимов назвачний улиц в населенных пунктах                          */ /*<b>STREETTYPE</b>- Справочник типов улиц                                                            */ /*<b>STREETTYPESYNONYM</b>- Справочник синонимов типов улиц                                           */ /*endlegend                                                                                           */ /*@enduml                                                                                             */ /*}}}                                                                                                 */ /*                                                                                                    */ /*----                                                                                                */ /********************************************************************************************************/ CREATE OR REPLACE FUNCTION umlfn_Table_AllGroupScript (a_SchemaNameVARCHAR(100) default 'public',/* название схемы базы данных*/ a_WHEREoptionVARCHAR(1000) default NULL,     /* условие запроса на выбор таблиц из системного каталога */ a_NeedAttrDescBOOLEAN default false,/* Признак необходимости включения комментария аттрибута  */ a_Mode        VARCHAR(20) default 'Trac'/* Формат возвращаемой строки: 'Trac' -для  средства управления проектам; 'PlantTest' - для тестирования на сайте https://www.planttext.com/  */     )   RETURNS  TEXT AS $BODY$ DECLARE c_TracMode          CONSTANT VARCHAR(50):='Trac'; /*для  средства управления проектам*/ c_PlantTestMode     CONSTANT VARCHAR(50):='PlantTest'; /*для тестирования на сайте "https://www.planttext.com/ */ v_Mode              VARCHAR(20); /* Формат возвращаемой строки: 'Trac' -для  средства управления проектам; */ /* 'PlantTest' - для тестирования на сайте https://www.planttext.com/  */ v_TableNameArrayVARCHAR(256)[]; /* Массив выбранных таблиц  */ v_TableGroupScriptTEXT; /* Формируемый скрипт*/ v_Return_Error Integer := 0; /* Код возврата*/   --****************************************************************************************************** BEGIN     v_Mode:=COALESCE(a_Mode,c_TracMode); v_TableGroupScript:=''; v_TableNameArray:=admfn_Table_TableNameArray(a_SchemaName,a_WHEREoption); IF COALESCE(v_TableNameArray,'{}')<>'{}' THEN v_TableGroupScript:=umlfn_Table_FromArray(a_SchemaName,v_TableNameArray,a_NeedAttrDesc,v_Mode); END IF; RETURN v_TableGroupScript; END $BODY$ LANGUAGE plpgsql; COMMENT ON FUNCTION umlfn_Table_AllGroupScript(a_SchemaName VARCHAR(100),a_WHEREoption VARCHAR(1000),a_NeedAttrDesc BOOLEAN,a_Mode VARCHAR(20)) IS 'Возвращает строку строку с описанием группы таблиц в формате плагина (plantuml) к Trac'; --ROLLBACK TRANSACTION; COMMIT TRANSACTION; SELECT umlfn_Table_AllGroupScript('public','tbl.relname ~* E''^Street'''); SELECT umlfn_Table_AllGroupScript('public','tbl.relname ~* E''^Street''',FALSE,'PlantTest');  

Создание функции umlfn_Table_Script

Комментарии к исходному коду функции можно посмотреть здесь.

Скрытый текст
BEGIN TRANSACTION; DROP FUNCTION IF EXISTS umlfn_Table_Script (a_SchemaName name,a_TableName name,a_NeedAttrDesc BOOLEAN,a_AllowedTableName VARCHAR(256)[]); /********************************************************************************************************/ /*  Функция возвращает строку с описанием таблицы в формате плагина (plantuml) к Trac — средству     */ /*  управления проектами и отслеживания ошибок в программном обеспечении.                */ /*------------------------------------------------------------------------------------------------------*/ /*ПРИМЕР:SELECT  umlfn_Table_Script('public','Street',TRUE);                                    */ /*------------------------------------------------------------------------------------------------------*/ /*'object public.STREET{'                                                                             */ /*'wcrccode :  (<i>Код страны</i>) smallint NOT NULL (PK1)(FK1 locality(wcrccode))'*/ /*'localityid :  (<i>ИД населенного пункта</i>) integer NOT NULL (PK2)(FK2 locality(localityid))'*/ /*'streetid :  (<i>ИД улицы населенного пункта</i>) smallint NOT NULL (PK3)'                */ /*'streettypeacrm :  (<i>Акроним типа улицы</i>) character(8) NULL (FK1 streettype(streettypeacrm))' */ /*'streetname :  (<i>Наименование улицы населенного пункта</i>) character varying(150) NOT NULL'      */ /*'streettsvector :  (<i>Расширенные характеристики улицы в населенном пункте, преобразованные в вектор полнотекстового поиска</i>) tsvector NULL '   */ /*'streettslitevector :  (<i>Характеристики улицы в населенном пункте, преобразованные в вектор полнотекстового поиска</i>) tsvector NULL '           */ /*'}'                                                                                                 */ /********************************************************************************************************/ CREATE OR REPLACE FUNCTION umlfn_Table_Script (a_SchemaNameNAME default 'public',/* название схемы базы данных*/ a_TableNameNAME default NULL,/* Название таблицы */  a_NeedAttrDescBOOLEAN default false,/* Признак необходимости включения комментария аттрибута  */ a_AllowedTableNameVARCHAR(256)[]default '{}'/* Массив допустимых для поиска внешних ключей таблиц  */  )   RETURNS  TEXT AS $BODY$ DECLARE c_TableScriptPrefixCONSTANT VARCHAR(10):='''object ';/* Начало скрипта описания таблицы*/ c_AttributeListPrefixCONSTANT VARCHAR(5):='{'''||CHR(13)||CHR(10);/* Начало списка атрибутов */ c_AttributeListSuffixCONSTANT VARCHAR(5):='''}'''||CHR(13)||CHR(10);/* Конец списка атрибутов */ c_TableScriptSuffixCONSTANT VARCHAR(5):=' '||CHR(13)||CHR(10);/* Конец скрипта описания таблицы*/ c_TableNameDelimiterCONSTANT VARCHAR(5):='.';  /* Символ-разделитель имени таблицы*/ c_BlankCONSTANT VARCHAR(5):=' ';  /* Символ пробела*/ v_AttributeScriptTEXT;/* */ v_TableScriptTEXT;/* */ v_Schemaname; v_TableNamename; v_TableOIDOID; v_AttributeNamename; v_AttributeNum SMALLINT; v_AttributeCountINTEGER;/* Счетчик цикла*/ v_Return_Error Integer := 0;  cursor_Attributes CURSOR FOR  SELECT tbl.oid, attr.attnum  FROM pg_attribute attr  INNER JOIN pg_class tbl ON tbl.oid = attr.attrelid  INNER JOIN pg_namespace nsp ON tbl.relnamespace=nsp.oid  WHERE LOWER(nsp.nspname)=LOWER(a_SchemaName) AND LOWER(tbl.relname)=LOWER(a_TableName) AND attr.attnum>0  ORDER BY tbl.relname,attr.attnum;  --****************************************************************************************************** BEGIN v_TableScript:=''; OPEN cursor_Attributes; v_AttributeCount:=0; v_TableScript:=c_TableScriptPrefix || LOWER(a_SchemaName) || c_TableNameDelimiter ||                          CASE WHEN LEFT(TRIM(a_TableName),1) =UPPER(LEFT(TRIM(a_TableName),1))                                     AND SUBSTRING(TRIM(a_TableName) FROM 2) =LOWER(SUBSTRING(TRIM(a_TableName) FROM 2))                                                             THEN UPPER(a_TableName)                             WHEN a_TableName ~ E'[A-ZА-ЯЁ]' THEN '"'||a_TableName||'"'                              ELSE  UPPER(a_TableName) END ||c_AttributeListPrefix; FETCH FIRST FROM cursor_Attributes INTO v_TableOID,v_AttributeNum; WHILE FOUND LOOP v_AttributeCount:=v_AttributeCount+1; v_TableScript:=v_TableScript||COALESCE(umlfn_Attribute_String(v_TableOID,v_AttributeNum,a_NeedAttrDesc,a_AllowedTableName),''); FETCH NEXT  FROM cursor_Attributes INTO v_TableOID,v_AttributeNum; END LOOP; CLOSE cursor_Attributes; v_TableScript:=v_TableScript ||c_AttributeListSuffix; RETURN v_TableScript; END $BODY$ LANGUAGE plpgsql; COMMENT ON FUNCTION umlfn_Table_Script(a_SchemaName name,a_TableName name,a_NeedAttrDesc BOOLEAN,a_AllowedTableName VARCHAR(256)[]) IS 'Возвращает строку с описанием таблицы в формате плагина (plantuml) к Trac'; --ROLLBACK TRANSACTION; COMMIT TRANSACTION; SELECT umlfn_Table_Script('public'::VARCHAR,'Street'); 

Создание функции umlfn_Attribute_String

Комментарии к исходному коду функции можно посмотреть здесь.

Скрытый текст
BEGIN TRANSACTION; DROP FUNCTION IF EXISTS umlfn_Attribute_String (a_TableOID OID,a_AttributeNo SMALLINT,a_NeedAttrDesc BOOLEAN,a_AllowedTableName VARCHAR(256)[]); /***************************************************************************************************************/ /*  Функция возвращает строку с описанием атрибута таблицы в формате плагина (plantuml) к Trac — средству */ /*  управления проектами и отслеживания ошибок в программном обеспечении. */ /*-------------------------------------------------------------------------------------------------------------*/ /* ПРИМЕРЫ:*/ /*ИД_Пользователь : double (PK)*/ /*ИД_Группа : double (FK1)*/ /*ИД_Должность : double (FK2)*/ /*Системное_Имя_Пользователя : varchar2(255) (AK)*/ /*ФИО : varchar2(255)*/ /*Телефоны : varchar2(255)*/ /*Почта : varchar2(100)*/ /*Адрес : varchar2(255)*/ /*Дата_Рождения : date*/ /****************************************************************************************************************/ CREATE OR REPLACE FUNCTION umlfn_Attribute_String (a_TableOIDOID,/* ИД таблицы */ a_AttributeNoSMALLINT,/* Порядковый номер атрибута в таблице*/ a_NeedAttrDescBOOLEAN default false,/* Признак необходимости включения комментария аттрибута  */ a_AllowedTableNameVARCHAR(256)[]default '{}'/* Массив допустимых для поиска внешних ключей таблиц  */   )   RETURNS  TEXT AS $BODY$ DECLARE  c_PrimaryKeyPrefixCONSTANT VARCHAR(5):='(PK';/* Начало опции об участии аттрибута в первичном ключе*/ c_PrimaryKeySuffixCONSTANT VARCHAR(5):=')';/* Окончание опции об участии аттрибута в первичном ключе*/ c_ForeignKeyPrefixCONSTANT VARCHAR(5):='(FK';/* Начало опции об участии аттрибута во внешнем ключе*/ c_ForeignKeySuffixCONSTANT VARCHAR(5):=')';/* Окончание опции об участии аттрибута во внешнем ключе*/ c_DescriptionPrefixCONSTANT VARCHAR(5):='(<i>';/* Начало комментария к атрибуту*/ c_DescriptionSuffixCONSTANT VARCHAR(5):='</i>)';/* Окончание комментария к атрибуту*/ c_EndOfAttributeStringCONSTANT VARCHAR(5):=CHR(13)||CHR(10);  /* Символы окончания строки описания атрибута*/ c_NULLCONSTANT VARCHAR(5):='NULL';/* Строка NULL */ c_NOTCONSTANT VARCHAR(5):='NOT';/* Строка NOT */ c_BlankCONSTANT VARCHAR(5):=' ';/* Символ пробела */ c_AttributeDelimiterCONSTANT VARCHAR(5):=' : '; /* Символ - разделитель названия атрибута и его типа*/ c_ColumnFKList_NDims CONSTANT INTEGER:=1;/* Размерность массива атрибутов внешнего ключа*/ v_NeedAttrDescBOOLEAN;/* Признак необходимости включения комментария аттрибута  */ v_AllowedTableNameVARCHAR(256)[];/* Массив допустимых для поиска внешних ключей таблиц  */ v_Attribute_String TEXT; /* Строка описания атрибута*/ v_AttributeName name;/* Название атрибута*/ v_UserTypeName VARCHAR(256);/* Пользовательский тип атрибута (название домена)*/ v_TypeName VARCHAR(256);/* Тип атрибута*/ v_isNotNULL BOOLEAN;/* Признак недопустимости значения NULL*/ v_isAttributePK BOOLEAN;/* Признак вхождения атрибута в первичный ключ */ v_ColumnPKNo SMALLINT;/* Порядковый номер аттрибута в первичном ключе*/ v_DescriptionTEXT;/* Комментари к аттрибуту */ v_isAttributeFK BOOLEAN;/* Признак вхождения атрибута во внешний ключ */ v_ColumnFKNoARRAYSMALLINT[];/* Массив порядковых номеров атрибута во всех внешних ключах */ v_FKTableNameARRAYname[];/* Массив названий таблиц, на которые сслылаются внешние ключи */ v_FKTableColumnNameARRAY name[];/* Массив названий атрибутов таблицы, на которую сслылается внешний ключи */ v_ColumnFKNoSMALLINT;/* Порядковый номер атрибута текщем внешнем ключе */ v_FKTableName name;/* Название таблицы, на которую сслылается текщий внешний ключ */ v_FKTableColumnName name;/* Название атрибута таблицы, на которую сслылается внешний ключ */ v_ColumnFKIndxINTEGER;/* Текущий индекс масссива атрибутов внешнего ключа*/ v_ColumnFKLBoundINTEGER;/* Нижний индекс масссива атрибутов внешнего ключа*/ v_ColumnFKUBoundINTEGER;/* Верхний индекс масссива атрибутов внешнего ключа*/ v_Return_Error Integer := 0;/* Код возврата*/  --****************************************************************************************************** BEGIN v_Attribute_String:=''; v_AllowedTableName:=COALESCE(a_AllowedTableName,'{}'); v_AllowedTableName:=cnfn_Array_LowerCase(v_AllowedTableName); v_NeedAttrDesc:=COALESCE(a_NeedAttrDesc,false); SELECT INTO v_AttributeName,v_TypeName,v_isNotNULL,v_isAttributePK,v_ColumnPKNo,v_Description,v_isAttributeFK,v_ColumnFKNoARRAY, v_FKTableNameARRAY,v_FKTableColumnNameARRAY   rsa_AttributeName,rsa_TypeName,rsa_isNotNULL,rsa_isAttributePK,rsa_ColumnPKNo,rsa_Description, rsa_isAttributeFK,rsa_ColumnFKNo, rsa_FKTableName,rsa_FKTableColumnName FROM admtf_Attribute_Features(a_TableOID,a_AttributeNo); v_Attribute_String:=TRIM(v_AttributeName)||c_AttributeDelimiter|| CASE WHEN v_Description IS NULL OR NOT v_NeedAttrDesc THEN ''  ELSE c_Blank||c_DescriptionPrefix||v_Description||c_DescriptionSuffix|| c_Blank END || v_TypeName|| c_Blank||CASE WHEN v_isNotNULL THEN c_NOT||c_Blank ELSE '' END || c_NULL || c_Blank || CASE WHEN v_isAttributePK THEN c_PrimaryKeyPrefix||TRIM(COALESCE(TO_CHAR(v_ColumnPKNo,'999'),''))|| c_PrimaryKeySuffix ELSE '' END; IF v_isAttributeFK THEN v_ColumnFKLBound:=array_lower(v_ColumnFKNoARRAY,c_ColumnFKList_NDims); v_ColumnFKUBound:=array_upper(v_ColumnFKNoARRAY,c_ColumnFKList_NDims); v_ColumnFKIndx:=v_ColumnFKLBound; WHILE v_ColumnFKIndx<=v_ColumnFKUBound LOOP v_ColumnFKNo:=v_ColumnFKNoARRAY[v_ColumnFKIndx]; v_FKTableName:=v_FKTableNameARRAY[v_ColumnFKIndx]; v_FKTableColumnName:=v_FKTableColumnNameARRAY[v_ColumnFKIndx]; IF COALESCE(a_AllowedTableName,'{}')='{}' OR ARRAY[v_FKTableName] <@ a_AllowedTableName::NAME[] THEN v_Attribute_String:=v_Attribute_String||c_ForeignKeyPrefix|| TRIM(COALESCE(TO_CHAR(v_ColumnFKNo,'999'),''))|| ' '||COALESCE(v_FKTableName,'')||'('||COALESCE(v_FKTableColumnName,'')||')'|| c_ForeignKeySuffix; END IF; v_ColumnFKIndx:=v_ColumnFKIndx+1; END LOOP; END IF; v_Attribute_String:=quote_literal(v_Attribute_String)||c_EndOfAttributeString; RETURN v_Attribute_String;  END $BODY$ LANGUAGE plpgsql; COMMENT ON FUNCTION umlfn_Attribute_String(a_TableOID OID,a_AttributeNo SMALLINT,a_NeedAttrDesc BOOLEAN,a_AllowedTableName VARCHAR(256)[]) IS 'Возвращает строку с описанием атрибута таблицы в формате плагина (plantuml) к Trac';   --ROLLBACK TRANSACTION; COMMIT TRANSACTION; SELECT * FROM umlfn_Attribute_String('public.Street'::REGCLASS,2::SMALLINT,TRUE); SELECT * FROM generate_series (1,6) inx, LATERAL umlfn_Attribute_String('public.Street'::REGCLASS,inx::SMALLINT,FALSE) ORDER BY inx; 

Создание функции umlfn_Table_LinksFromArray

Комментарии к исходному коду функции можно посмотреть здесь.

Скрытый текст
BEGIN TRANSACTION; DROP FUNCTION IF EXISTS umlfn_Table_LinksFromArray (a_SchemaName VARCHAR(100),a_TableNameArray VARCHAR(256)[]); /************************************************************************************************************/ /*  Функция возвращает строку с описанием связей таблиц из исходного массива в формате плагина (plantuml)   */ /* к Trac — средству управления проектами и отсслеживания ошибок в программном обеспечении.            */ /*----------------------------------------------------------------------------------------------------------*/ /*ПРИМЕР:umlfn_Table_LinksFromArray('public','{Street,StreetType,StreetSynonym,StreetTypeSynonym}');*/ /*----------------------------------------------------------------------------------------------------------*/ /* 'public.STREETSYNONYM *-- public.STREET'                                                                 */ /* 'public.STREETSYNONYM *-- public.STREETTYPE'                                                             */ /* 'public.STREET *-- public.STREETTYPE'                                                                    */ /* 'public.STREETTYPESYNONYM *-- public.STREETTYPE'                                                         */ /************************************************************************************************************/ CREATE OR REPLACE FUNCTION umlfn_Table_LinksFromArray (a_SchemaNameVARCHAR(100) default 'public',/* название схемы базы данных*/ a_TableNameArrayVARCHAR(256)[]default '{}'/* Исходный массив  таблиц  */  )   RETURNS  TEXT AS $BODY$ DECLARE c_SchemaNameCONSTANT VARCHAR(256):='public';/* название схемы базы данных*/ c_TableKindCONSTANT CHAR:='r'; c_ForeignKeyKindCONSTANT CHAR:='f'; c_ManySignCONSTANT CHAR:='N'; c_OneSignCONSTANT CHAR:='1'; c_PlantManySignCONSTANT VARCHAR:='*'; c_PlantOneSignCONSTANT VARCHAR:=''; c_PlantLinkMarkCONSTANT VARCHAR:='--';     c_TableLinksSuffix  CONSTANT VARCHAR(10):=CHR(13)||CHR(10);/* Окончание описания таблицы в комментариях*/  c_TableNameDelimiterCONSTANT VARCHAR(5):='.';  /* Символ-разделитель имени таблицы*/ c_BlankCONSTANT VARCHAR(5):=' ';  /* Символ пробела*/ v_SchemaNameVARCHAR(256);/* название схемы базы данных*/ v_TableLinksScriptTEXT;/* Формируемый скрипт*/ v_TableCountINTEGER;/* Чсетчик таблиц группы*/ v_TableNameArrayTEXT[];/* Массив таблиц  */ v_TableName VARCHAR(256);/* Название одной из таблиц группы*/ v_FTableName VARCHAR(256);/* Название одной из таблиц группы*/ v_TableDescriptionTEXT;/* Описание одной из таблиц группы*/ v_TablesRecordRECORD;/* Запись с данными таблицы */ v_TableOIDOID;/* ИД таблицы */ v_ForeignKeyName VARCHAR(256);/* Название внешнего ключа*/ v_ProcessedTableNameArrayTEXT[];/* Массив обработанных таблиц  */ v_TableNameArrayRemainderTEXT[];/* Массив необработанных таблиц  */ v_LinkSignVARCHAR(5);/* Признак связи по отношения к таклице*/ v_LinkMarkLeftCharVARCHAR;/* Левый символ признака связи*/ v_LinkMarkRightCharVARCHAR;/* Правый символ признака связи*/ v_PlantLinkSignVARCHAR(5); v_Return_Error Integer := 0; --****************************************************************************************************** BEGIN v_SchemaName:=COALESCE(a_SchemaName,c_SchemaName); v_TableNameArray:=cnfn_Array_LowerCase(a_TableNameArray); v_TableLinksScript:=''; IF COALESCE(v_TableNameArray,'{}')<>'{}' THEN v_TableCount:=0; FOR v_TablesRecord IN SELECT tbl.oid AS TableOID,tbl.relname:: VARCHAR(256),ftbl.oid AS FTableOID, Ftbl.relname:: VARCHAR(256) AS Frelname, lcon.oid AS ForeignKeyOID,lcon.conname:: VARCHAR(256) AS ForeignKeyName FROM pg_class tbl  INNER JOIN pg_namespace nsp ON tbl.relnamespace = nsp.oid  LEFT OUTER JOIN pg_Description dsc ON tbl.oid=dsc.objoid AND dsc.objsubid=0 INNER JOIN pg_constraint lcon ON lcon.conrelid=tbl.oid INNER JOIN pg_namespace lnspc ON lcon.connamespace = lnspc.oid INNER JOIN pg_class ftbl ON lcon.confrelid=ftbl.oid INNER JOIN pg_namespace fnsp ON ftbl.relnamespace=fnsp.oid  WHERE LOWER(fnsp.nspname)=LOWER(v_SchemaName) AND ftbl.relkind=c_TableKind  AND lcon.contype =c_ForeignKeyKind AND LOWER(lnspc.nspname)=LOWER(v_SchemaName) AND ftbl.relname !~* E'(raster_|spatial_|geometry_|geography_)' AND ARRAY[tbl.relname::TEXT] <@ v_TableNameArray  AND ARRAY[ftbl.relname::TEXT] <@ v_TableNameArray  ORDER BY COUNT(*) OVER(PARTITION BY nsp.oid,tbl.oid) DESC, nsp.nspname,tbl.relname LOOP v_TableName:=v_TablesRecord.relname; v_FTableName:=v_TablesRecord.Frelname; v_ForeignKeyName:=v_TablesRecord.ForeignKeyName; v_TableCount:=v_TableCount+1; v_LinkSign:=admfn_Table_LinkSign(a_SchemaName,v_TableName,v_ForeignKeyName); v_LinkMarkLeftChar:=LEFT(v_LinkSign,1); v_LinkMarkRightChar:=RIGHT(v_LinkSign,1); v_PlantLinkSign:=CASE v_LinkMarkLeftChar WHEN c_ManySign THEN c_PlantManySign ELSE c_PlantOneSign END ||  c_PlantLinkMark || CASE v_LinkMarkRightChar WHEN c_ManySign THEN c_PlantManySign  ELSE c_PlantOneSign END; v_TableLinksScript:=v_TableLinksScript||''''||LOWER(v_SchemaName)||c_TableNameDelimiter||UPPER(v_TableName)||c_Blank|| v_PlantLinkSign||c_Blank||LOWER(v_SchemaName)||c_TableNameDelimiter||UPPER(v_FTableName)||''''|| c_TableLinksSuffix; v_ProcessedTableNameArray:=array_append(v_ProcessedTableNameArray, v_TableName::TEXT); END LOOP; END IF; RETURN v_TableLinksScript; END $BODY$ LANGUAGE plpgsql; COMMENT ON FUNCTION umlfn_Table_LinksFromArray(a_SchemaName VARCHAR(100),a_TableNameArray VARCHAR(256)[]) IS 'Возвращает строку строку с описанием таблиц массива в формате плагина (plantuml) к Trac'; --ROLLBACK TRANSACTION; COMMIT TRANSACTION; SELECT umlfn_Table_LinksFromArray('public','{Street,StreetType,StreetSynonym,StreetTypeSynonym}'); 

ПРИЛОЖЕНИЕ 2. Дополнительные материалы

Пошаговая инструкция просмотра диаграмм классов

Скрытый текст

Посмотреть, как выглядит диаграмма классов, описанная PlantUML-скриптом можно на сайте PlantText UML editor.

Шаг 1. Перейти по ссылке https://www.planttext.com/ на страницу редактора, как показано на Рис. 5. Установить курсор на заголовке вкладки «File Manager». В открывшемся меню выбрать пункт «Import / Export».

PlantTest UML step01 v2

Рис. 5. Начальный экран PlantText UML editor

Шаг 2. В открывшемся окне «Import/Export» в строке «Import» щёлкнуть левой клавишей мыши на кнопку «Обзор», как показано.

PlantTest UML step02 v2

Рис. 6. Окно вызова загрузки PlantUML-скрипта

Откроется стандартное для Вашей операционной системы окно выбора файла. В Windows 10 оно будет выглядеть примерно так, как показано на Рис. 7.

Выбрать заранее подготовленный скрипт и нажать кнопку «Открыть».

PlantTest UML import file v2

Рис. 7. Выбор PlantUML-скрипта на диске

Здесь выбирается скрипт с окончанием «PlantTest», т.к. он создан в формате готовом для отображения диаграммы классов в PlantText UML editor.

Беды не будет, если выбрать скрипт без такого окончания, т.к. как показано дальше формат скриптов для TRAC содержит дополнительные строчки в начале и в конце скрипта, которые легко удаляются.

Шаг 3. В открывшемся окне «Import/Export» в строке «Import» щёлкнуть левой клавишей мыши на кнопку «Обзор», как показано.

PlantTest UML step03

Рис. 8. Слева загруженный PlantUML-скрипт, справа — соответствующая диаграмма классов

Как видно из Рис. 8 диаграмма классов может быть преобразованы в форматы: PNG, SVG [*5] , TXT.

PlantTest UML PNG

Рис. 9. Диаграмма классов в формате PNG

Как внести изменения в PlantUML-скрипт для TRAC, чтобы увидеть диаграмму классов

PlantText UML editor работает со скриптами, построенными по правилам языка PlantUML, в соответствии с которыми основной текст скрипта должен быть заключён между операторами @startuml и @enduml. В тоже время для встраивания в плагин (plantuml) TRAC вокруг классического текста создается дополнительная оболочка.

PlantTest UML step03_error

Рис. 10. Сообщение об ошибке после загрузки скрипта для TRAC

Для того чтобы PlantText UML editor не воспринимал скрипт как ошибочный, из его текста следует удалить строки выше оператора @startuml и ниже оператора @enduml. Эти строки выделены на Рис. 10.

После удаления экран приобретёт вид, показанный на Рис. 8.

Пошаговая инструкция создания карточки TRAC

Скрытый текст
TRAC-logo

TRAC-logo

Здесь предполагается, что «Система управления проектами TRAC» уже установлена. Тем же, кого интересуют сведения о порядке установки этой системы предлагаем перейти на страницу официального сайта под названием «Руководство по установке Trac».

Вход в установленную на сервере компании систему TRAC выполняется через браузер. Формат URL установленного TRAC может выглядеть так: https://trac.company.ru/. Где вместо «company» указывается домен компании, в которой установлена система TRAC. Поэтому, как показано на Рис. 11, первый шаг представляет собой вход с сиcтему TRAC.

TRAC entrance step01 v2

Рис. 11. Окно входа в систему TRAC

После входа открывается страница проекта, отображающая список проектов компании. Так как вход осуществляется с познавательными целями, то вторым шагом выбирается проект «песочница», предназначенный для изучения возможностей TRAC путём экспериментирования. Смотри Рис. 12.

TRAC projects step02 v2

Рис. 12. Вход в проект «песочница»
TRAC new card step02 v2

Рис. 13 Список карточек проекта и кнопка создания новой карточки

Щелчок на названии проекта левой клавишей мышки, приводит к тому, что на экране появляются список карточек проекта, а также кнопки вызова различных операций над карточками. В данном случает, как показано на Рис. 13, мы создаем новую карточку, нажав на кнопку с соответствующим названием.

TRAC create card step03

Рис. 14. Окно создания карточки проекта

В открывшемся окне для создания новой карточки вводится название карточки в поле «Краткое описание», а в основное окно вставляется текст PlantUML-скрипта. Смотри Рис. 14.

TRAC scripts wrapper

Рис. 15. TRAC- обёртка скрипта

Заметим, что вставляемый скрипт должен быть окружен операторами «обёртки» TRAC. На Рис. 15 эти операторы выделены красным цветом. После нажатия одной из кнопок «Предварительный просмотр» или «Создать карточку» на экране отобразится описанная скриптом диаграмма классов.

TRAC view card step04

Рис. 16. Диаграмма классов в системе TRAC

Цель достигнута — скрипт включен в карточку системы TRAC, в которой отображается диаграмма классов.


ссылка на оригинал статьи https://habr.com/ru/articles/841776/


Комментарии

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *