gendesign/.claude/rules/sql.md
lekss361 ae0fce3528
refactor(claude): split 700-line CLAUDE.md into path-scoped .claude/rules/ (#188)
Old CLAUDE.md was 700 lines — exceeded Anthropic 200-line recommendation,
adherence degraded under context pressure.

Refactor per research findings:

- CLAUDE.md 700 -> 97 lines (essential only, pointers to rules)
- .claude/rules/{backend,frontend,sql,git-pr,deploy}.md (NEW, path-scoped)
- ~/.claude/CLAUDE.md (NEW, 21 lines) — personal cross-project prefs
- memory/ — deleted 12 feedback files promoted to proper layer (CLAUDE.md
  rules table, .claude/rules/, ~/.claude/CLAUDE.md). 7 remaining = workflow
  details.
- .gitignore: !.claude/agents/, !.claude/rules/ exceptions

Total auto-loaded per session: 97 (CLAUDE.md) + 21 (~/.claude) = 118 lines
vs prior 700. Rules in .claude/rules/ load only when matching paths touched.

Resolves conflict no_self_review vs pre_push_review: now single rule in
git-pr.md Review workflow section (pre-push = local lint; post-push =
external Claude window posting as lekss361).

Code-reviewer feedback applied:
- paths: frontmatter added to git-pr.md
- Auto-merge scope blocked-list now includes .claude/rules/*.md changes
  to prevent self-extending rules without human approval.

Co-authored-by: lekss361 <claudestars@proton.me>
2026-05-15 23:06:33 +03:00

69 lines
2.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
paths: data/sql/**/*.sql
---
# SQL conventions — PostgreSQL 16 / PostGIS 3.4
## File naming
`NN_topic.sql` где NN — следующий sequential номер. Проверка: `ls data/sql/ | sort | tail -5`.
## Structure
```sql
-- Контекст: что делает файл, зачем, порядок применения, dependencies.
BEGIN;
-- DDL здесь (idempotent)
COMMIT;
```
## Idempotency (обязательно)
- `CREATE TABLE IF NOT EXISTS`
- `ALTER TABLE ... ADD COLUMN IF NOT EXISTS`
- `ALTER TABLE ... DROP COLUMN IF EXISTS`
- `CREATE OR REPLACE VIEW`
- `CREATE INDEX IF NOT EXISTS`
- `ON CONFLICT DO NOTHING` для seed data
- `DROP INDEX IF EXISTS` перед `CREATE INDEX` если меняется тип column
## Auto-apply на prod
`data/sql/NN_*.sql` применяются **автоматически** через `deploy.yml` (tracking через `_schema_migrations`). Каждый файл — ровно один раз, по NN order. Idempotency критична.
Если auto-apply падает → deploy exit 1, containers не обновляются. Diagnose: GHA log → "Apply DB migrations". Fix: `psql -f file.sql` через SSH tunnel + `INSERT INTO _schema_migrations (filename) VALUES ('NN_xxx.sql') ON CONFLICT DO NOTHING`.
## Migration order
1. **SQL migration first** (схема) — deploy first
2. **Backend code matching new schema** — deploy second
3. Никогда наоборот — deployed code напорется на несовместимую схему
## psycopg v3 CAST trap
В Python через psycopg v3 / SQLAlchemy `text(...)`:
-`:param::type` — игнорируется парсером
-`CAST(:param AS type)` — canonical
В чистом SQL (`.sql` файл, без bind params) — обычный `::type` работает.
Reference: vault `Pattern_CAST_AS_Type`.
## VIEW dependencies
Перед `ALTER COLUMN type` column'а:
1. Найти зависимые view: `\d+ table_name` или `pg_get_viewdef('view_name'::regclass, true)`
2. `DROP VIEW <dependent>;`
3. `ALTER COLUMN ...;`
4. `CREATE OR REPLACE VIEW <dependent> AS SELECT ...;`
Reference: `93_cad_parcels_geom_multipolygon.sql` (Polygon → MultiPolygon migration).
## Запреты
-`DROP TABLE` / `TRUNCATE` без явного approval пользователя
-Не-idempotent файлы (без `IF EXISTS`) — на случай ре-apply
- ❌ Миграции без `BEGIN...COMMIT` обёртки
- ❌ Hardcoded даты / IDs без комментария почему