From vmkteam-developer
References pgDesigner .pgd XML format and CLI for PostgreSQL schema descriptions. Useful when editing .pgd files or using pgdesigner.io tools.
npx claudepluginhub vmkteam/claude-plugins --plugin vmkteam-developerThis skill uses the workspace's default tool permissions.
Ты — эксперт по формату `.pgd` и CLI **pgDesigner** (pgdesigner.io). Используй это руководство при редактировании PGD-файлов и работе с CLI.
Mandates invoking relevant skills via tools before any response in coding sessions. Covers access, priorities, and adaptations for Claude Code, Copilot CLI, Gemini CLI.
Share bugs, ideas, or general feedback.
Ты — эксперт по формату .pgd и CLI pgDesigner (pgdesigner.io). Используй это руководство при редактировании PGD-файлов и работе с CLI.
.pgd — git-friendly XML-формат pgDesigner для описания схем PostgreSQL. Спецификация: https://pgdesigner.io/docs/pgd-format, валидация: pgd-format.xsd.
schema.table"true" / "false"<pgd version="1" pg-version="18" default-schema="public">
├── <project> — имя, описание, настройки (naming, defaults, linting)
├── <database> — имя БД, кодировка, коллация, шаблон
├── <roles> — роли PostgreSQL
├── <tablespaces> — физические расположения хранения
├── <extensions> — расширения PG
├── <types> — enum, composite, domain, range
├── <sequences> — последовательности
├── <schema name="..."> — схемы (содержат таблицы и индексы)
│ ├── <table> — таблицы
│ │ ├── <column> — колонки
│ │ ├── <pk> — PRIMARY KEY
│ │ ├── <fk> — FOREIGN KEY
│ │ ├── <unique> — UNIQUE
│ │ ├── <check> — CHECK
│ │ ├── <exclude> — EXCLUDE
│ │ ├── <with> — параметры хранения
│ │ ├── <partition-by> — ключ партицирования
│ │ └── <partition> — дочерние партиции
│ └── <index> — индексы (на уровне схемы, НЕ внутри таблиц)
├── <views> — представления (view, materialized-view)
├── <functions> — функции, процедуры, агрегаты
├── <triggers> — триггеры
├── <policies> — RLS-политики
├── <comments> — комментарии к объектам
├── <grants> — привилегии
├── <rules> — правила (deprecated)
└── <layouts> — метаданные отображения (позиции, цвета, группы)
<?xml version="1.0" encoding="UTF-8"?>
<pgd version="1" pg-version="18" default-schema="public">
...
</pgd>
| Атрибут | Обязательный | Описание |
|---|---|---|
version | да | Версия формата (int), текущая: 1 |
pg-version | нет | Целевая версия PostgreSQL (14-18) |
default-schema | нет | Схема по умолчанию, default: "public" |
<project name="myproject" description="My database">
<settings>
<naming convention="snake_case" tables="plural"></naming>
<defaults nullable="true" on-delete="restrict"></defaults>
</settings>
</project>
<column name="email" type="varchar" length="255" nullable="false"
default="''" collation="en_US.utf8" comment="User email"
storage="extended" compression="lz4">
</column>
| Атрибут | Обязательный | Описание |
|---|---|---|
name | да | Имя колонки |
type | да | Тип данных PostgreSQL |
length | нет | Длина (для varchar, char) |
precision | нет | Точность (для numeric) |
scale | нет | Масштаб (для numeric) |
nullable | нет | default: "true". "false" = NOT NULL |
default | нет | SQL-выражение для DEFAULT |
collation | нет | Коллация |
storage | нет | plain, external, extended, main, default |
compression | нет | lz4, pglz, default (PG14+) |
comment | нет | Комментарий к колонке |
<column name="id" type="bigint" nullable="false">
<identity generated="always"></identity>
</column>
<column name="full_name" type="text">
<generated stored="true"><![CDATA[first_name || ' ' || last_name]]></generated>
</column>
smallint, integer, bigint
smallserial, serial, bigserial
numeric, decimal, real, double precision, money
varchar / character varying, char / character, text
date, time, timetz, timestamp, timestamptz, interval
boolean, uuid, json, jsonb, xml, bytea, inet, cidr, macaddr, tsvector, tsquery, bit, varbit
Суффикс []: text[], integer[], jsonb[]
int4range, int8range, numrange, tsrange, tstzrange, daterange
Ссылка по имени: status, или с квалификацией схемы: myschema.status
<enum name="user_status" schema="public">
<label>active</label>
<label>inactive</label>
<label>banned</label>
</enum>
<composite name="address" schema="public">
<field name="street" type="text"></field>
<field name="city" type="varchar" length="100"></field>
</composite>
<domain name="email_addr" schema="public" type="varchar" length="255" default="''">
<check name="email_check"><![CDATA[VALUE ~ '^.+@.+$']]></check>
</domain>
<range name="float_range" schema="public" subtype="float8"></range>
<pk name="pk_users" deferrable="false">
<column name="id"></column>
</pk>
Составной PK:
<pk name="pk_user_roles">
<column name="user_id"></column>
<column name="role_id"></column>
</pk>
<fk name="fk_orders_user" to-table="users"
on-delete="cascade" on-update="no action"
deferrable="false" match="simple">
<column name="user_id" references="id"></column>
</fk>
<unique name="uq_users_email" nulls-distinct="true">
<column name="email"></column>
</unique>
<check name="chk_age"><![CDATA[age >= 0 AND age < 200]]></check>
<exclude name="excl_booking" using="gist">
<element column="room_id" with="="></element>
<element column="period" with="&&"></element>
</exclude>
Важно: индексы определяются на уровне <schema>, а НЕ внутри <table>.
<index name="idx_users_email" table="users" unique="true" using="btree">
<column name="email" order="asc" nulls="last"></column>
</index>
<index name="idx_users_lower_email" table="users" using="btree">
<expression><![CDATA[lower(email)]]></expression>
</index>
<index name="idx_active_users" table="users" using="btree">
<column name="email"></column>
<where><![CDATA[deleted_at IS NULL]]></where>
</index>
<index name="idx_users_email_incl" table="users" unique="true">
<column name="email"></column>
<include>
<column name="name"></column>
</include>
</index>
<table name="events">
<column name="id" type="bigint" nullable="false"></column>
<column name="created_at" type="timestamptz" nullable="false"></column>
<pk name="pk_events">
<column name="id"></column>
<column name="created_at"></column>
</pk>
<partition-by type="range">
<column name="created_at"></column>
</partition-by>
<partition name="events_2024">
<bound>FOR VALUES FROM ('2024-01-01') TO ('2025-01-01')</bound>
</partition>
</table>
| SQL-операция | Что менять в PGD |
|---|---|
CREATE TABLE | Добавить <table> в нужную <schema> |
ALTER TABLE ADD COLUMN | Добавить <column> в существующий <table> |
CREATE INDEX | Добавить <index> в <schema> (НЕ внутрь <table>) |
ALTER TABLE ADD CONSTRAINT | Добавить <pk> / <fk> / <unique> / <check> в <table> |
CREATE TYPE | Добавить <enum> / <composite> / <domain> в <types> |
CREATE FUNCTION | Добавить <function> в <functions> |
Порядок элементов внутри <table>: columns → pk → fk → unique → check → exclude → with → partition-by → partition.
| Аспект | PDD (MicroOLAP) | PGD (pgDesigner) |
|---|---|---|
| Идентификация | Числовые ID | Имена объектов |
| Типы данных | Коды (25, 1043...) | Имена (text, varchar) |
| NOT NULL | NotNull="1" | nullable="false" |
| Индексы | Внутри ENTITY | На уровне schema |
| FK | Отдельная секция REFERENCES | <fk> внутри table |
| Булевы | "0" / "1" | "true" / "false" |
Синтаксис: pgdesigner [command] [flags] <file>
pgdesigner generate schema.pgd # в stdout
pgdesigner generate -o schema.sql schema.pgd # в файл
pgdesigner diff old.pgd new.pgd # ALTER SQL в stdout
pgdesigner diff -f json old.pgd new.pgd # JSON-формат различий
pgdesigner lint schema.pgd # текстовый отчёт
pgdesigner lint -fix schema.pgd # автоисправление
pgdesigner convert schema.pdd -o project.pgd # из MicroOLAP PDD
pgdesigner convert schema.sql -o project.pgd # из pg_dump SQL
pgdesigner convert "postgres://localhost/mydb" -o project.pgd # из живой БД
pgdesigner testdata schema.pgd # 50 строк на таблицу
pgdesigner testdata -seed 42 -rows 100 schema.pgd # воспроизводимые данные
<schema>, не внутри <table><table>: columns → pk → fk → unique → check → excludeschema.table"true" — для NOT NULL явно указывай nullable="false"