Przejdź do treści
Biblioteka skilli
Dane i analityka · Nauka i wyjaśnianie

postgresql-patterns

/postgresql-patterns

Podpowiada funkcje silnika PostgreSQL: typy JSONB, tablice, zakresy, domeny, okna, CTE, wyszukiwanie tekstu i PL/pgSQL.

Repozytorium
agents ↗
Licencja
MIT
Ostatnia zmiana repozytorium
09.11.2026

Ocena i bezpieczeństwo

100/ 100Klasa: dobry
Format25 / 25
Frontmatter z nazwą i opisem, poprawna nazwa, opis do 1024 znaków, nazwa zgodna z folderem.
Odkrywalność25 / 25
Opis mówi, kiedy użyć skilla, ma sensowną długość i jest w 3. osobie.
Treść35 / 35
Co najmniej 150 słów i do 500 linii, nagłówki, listy kroków, przykłady albo kod.
Higiena15 / 15
Bez zaślepek typu TODO, bez ścieżek Windows, z licencją.
Ryzykobrak sygnałów w skanie
Pliki w paczce
2
Skrypty
0
Komentarze HTML
0
Adresy URL w SKILL.md
0
Przestarzałość

Brak sygnałów. Repozytorium zmienione 09.11.2026, bez odwołań do wycofanych modeli i API.

Licencja

MIT, otwarta: można używać i zmieniać, z zachowaniem informacji o autorze.

Co robi i kiedy

Podpowiada funkcje silnika PostgreSQL: typy JSONB, tablice, zakresy, domeny, okna, CTE, wyszukiwanie tekstu i PL/pgSQL.

Oryginalny opis (EN)

PostgreSQL engine and language features - advanced data types (JSONB, arrays, ranges, geometric, custom types/domains/ENUM), extensions, window functions, CTEs, full-text search, PL/pgSQL, and error reporting (RAISE / SQLSTATE). Use when writing PostgreSQL DDL/DML that should use engine-specific capabilities or writing PL/pgSQL error messages.

Jak działa

  1. When to activate
  2. Formatting
  3. JSONB
  4. Arrays
  5. Custom types, domains & enums
  6. Range types
  7. Geometric types
  8. Window functions & analytics
  9. CTEs (including recursive)
  10. Full-text search
Sekcje z nagłówków SKILL.md, w oryginale · 311 linii, 1 772 słów
Podgląd SKILL.md
---
name: postgresql-patterns
description: PostgreSQL engine and language features - advanced data types (JSONB, arrays, ranges, geometric, custom types/domains/ENUM), extensions, window functions, CTEs, full-text search, PL/pgSQL, and error reporting (RAISE / SQLSTATE). Use when writing PostgreSQL DDL/DML that should use engine-specific capabilities or writing PL/pgSQL error messages.
license: MIT
metadata:
  author: rainingdaemons/agents
  version: "1.0"
  source: Generated from PostgreSQL v16, following PostgreSQL Coding Conventions and the PostgreSQL Style Guide.
---

# PostgreSQL Patterns

PostgreSQL-the-engine guidance: the data types, functions, extensions, and SQL/PL-pgSQL features that are unique to PostgreSQL. This skill owns **what PostgreSQL can do**. Query planning and indexing strategy live in `postgresql-optimization`; schema/normalization/constraints in `database-design`.

> **This repo overrides the generic examples below.** Follow `internal/conventions/DATABASE_CONVENTIONS.md`: `UUID PRIMARY KEY DEFAULT gen_random_uuid()`, `TIMESTAMPTZ`, soft deletes via `is_deleted`, money as `BIGINT`. The examples here use those types already.

## When to activate

- Choosing an engine-specific data type (JSONB, arrays, ranges, geometric, custom types)
- Using window functions, CTEs, or full-text search
- Enabling or calling an extension
- Writing PL/pgSQL functions or triggers
- Writing PL/pgSQL error messages (`RAISE`, SQLSTATE codes)

## Formatting

- Indent SQL and PL/pgSQL with 4 spaces per level (like the tables in this skill); never mix tabs and spaces in one file.
- Keep lines readable within ~80 columns; break long `SELECT` lists and `CREATE TABLE` column definitions one item per line.
- Follow BSD-style brace/`BEGIN … END` placement: each block's `BEGIN`/`END` on its own line.
- The strongest rule is local consistency: **make new SQL look like the SQL around it**. Align columns only if the file already does.
- Never comment with `//`; use `--` for line comments and `/* … */` for blocks.

## JSONB

Prefer JSONB over JSON (it is stored decomposed and indexable). Query with containment/path operators, not text casting.

```sql
CREATE TABLE orders (
    id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
    data jsonb NOT NULL DEFAULT '{}',
    created_at timestamptz NOT NULL DEFAULT now()
);

-- Indexable containment query
SELECT * FROM orders WHERE data @> '{"status": "shipped"}';

-- Path extraction
SELECT data #>> '{user,role}' FROM orders;

-- Containment + path filter
SELECT * FROM orders
WHERE data @> '{"type": "login"}'
  AND data #>> '{user,role}' = 'admin';

-- Aggregate JSON
SELECT jsonb_agg(data) FROM orders WHERE data ? 'user_id';
```

- Keep JSONB structured and validated with `CHECK` constraints where the shape is fixed.
- For query performance of JSONB (GIN index, `@>` vs `->>`), see `postgresql-optimization`.

## Arrays

```sql
CREATE TABLE posts (
    id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
    tags text[],
    category_ids integer[]
);

SELECT * FROM posts WHERE 'postgresql' = ANY(tags);            -- membership
SELECT * FROM posts WHERE tags && ARRAY['database', 'sql'];    -- overlap
SELECT * FROM posts WHERE array_length(tags, 1) > 3;
SELECT array_agg(DISTINCT c) FROM posts, unnest(category_ids) AS c;
```

Prefer a normalized join table when you need referential integrity or frequent joins on the elements; arrays suit small, unordered, read-mostly sets.

## Custom types, domains & enums

```sql
CREATE TYPE order_status AS ENUM ('pending', 'processing', 'shipped', 'delivered', 'cancelled');

CREATE TYPE address_type AS (
    street text,
    city text,
    postal_code text,
    country text
);

CREATE DOMAIN email_address AS text
    CHECK (VALUE ~* '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$');

CREATE TABLE customers (
    id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
    email email_address NOT NULL,
    address address_type,
    status order_status DEFAULT 'pending'
);
```

- Define enums **before** the tables that reference them.
- Domains package a reusable `CHECK`; use them instead of repeating the same constraint.
- Enum values are versioned with migrations — adding values is a minor change; removing/renaming is breaking.

## Range types

```sql
CREATE TABLE reservations (
    id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
    room_id integer,
    reservation_period tstzrange,
    price_range numrange
);

-- Overlap query
SELECT * FROM reservations
WHERE reservation_period && tstzrange('2024-07-20', '2024-07-25');

-- Prevent overlapping reservations (needs GiST; see postgresql-optimization)
ALTER TABLE reservations
ADD CONSTRAINT no_overlap
EXCLUDE USING gist (room_id WITH =, reservation_period WITH &&);
```

## Geometric types

```sql
CREATE TABLE locations (
    id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
    name text,
    coordinates point,
    coverage circle,
    service_area polygon
);

SELECT name FROM locations
WHERE coordinates <-> point(40.7128, -74.0060) < 10;   -- distance
```

## Window functions & analytics

```sql
SELECT
    product_id,
    sale_date,
    amount,
    SUM(amount)  OVER (PARTITION BY product_id ORDER BY sale_date)                                  AS running_total,
    AVG(amount)  OVER (PARTITION BY product_id ORDER BY sale_date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS moving_avg,
    DENSE_RANK() OVER (PARTITION BY EXTRACT(month FROM sale_date) ORDER BY amount DESC)             AS monthly_rank,
    LAG(amount, 1) OVER (PARTITION BY product_id ORDER BY sale_date)                                AS prev_amount
FROM sales;
```

## CTEs (including recursive)

```sql
-- Recursive query for hierarchical data
WITH RECURSIVE category_tree AS (
    SELECT id, name, parent_id, 1 AS level
    FROM categories
    WHERE parent_id IS NULL

    UNION ALL

    SELECT c.id, c.name, c.parent_id, ct.level + 1
    FROM categories c
    JOIN category_tree ct ON c.parent_id = ct.id
)
SELECT * FROM category_tree ORDER BY level, name;
```

CTEs are for readability and recursion. Whether a CTE is inlined or materialized (and the performance implications) is covered in `postgresql-optimization`.

## Full-text search

```sql
CREATE TABLE documents (
    id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
    title text,
    content text,
    search_vector tsvector
);

UPDATE documents
SET search_vector = to_tsvector('english', title || ' ' || content);

SELECT *
FROM documents
WHERE search_vector @@ plainto_tsquery('english', 'postgresql database');

-- Ranked results
SELECT *, ts_rank(search_vector, plainto_tsquery('postgresql')) AS rank
FROM documents
WHERE search_vector @@ plainto_tsquery('postgresql')
ORDER BY rank DESC;
```

A `GIN` index on `search_vector` is required for speed — see `postgresql-optimization`.

## Extensions

```sql
CREATE EXTENSION IF NOT EXISTS "pgcrypto";    -- gen_random_uuid(), crypt(), gen_salt()
CREATE EXTENSION IF NOT EXISTS "unaccent";    -- accent-insensitive text
CREATE EXTENSION IF NOT EXISTS "pg_trgm";     -- trigram similarity / LIKE indexes

SELECT gen_random_uuid();
SELECT crypt('password', gen_salt('bf'));     -- password hashing
SELECT similarity('postgresql', 'postgersql');
```

Use `IF NOT EXISTS`, and only extensions the deployment actually provides.

## PL/pgSQL functions & triggers

```sql
-- Keep the trigger body minimal; let the WHEN clause gate it.
CREATE OR REPLACE FUNCTION update_modified_time()
RETURNS trigger AS $$
BEGIN
    NEW.updated_at = now();
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER update_modified_time_trigger
    BEFORE UPDATE ON products
    FOR EACH ROW
    WHEN (OLD.* IS DISTINCT FROM NEW.*)   -- fire only on real changes
    EXECUTE FUNCTION update_modified_time();
```

- Prefer set-based SQL over row-by-row loops in functions.
- Use `RETURNS trigger` functions for audit/`updated_at` maintenance.

## Error reporting (`RAISE`) and message style

`RAISE` is the SQL-level equivalent of the server's `ereport`: same three-part message model, same style guide. Pick a real severity (`DEBUG`, `LOG`, `INFO`, `NOTICE`, `WARNING`, `EXCEPTION`); `EXCEPTION` aborts the statement, the others return normally.

```sql
-- User-facing: short lowercase primary message + DETAIL (facts) + HINT (fix).
RAISE EXCEPTION 'order total cannot be negative'
    USING ERRCODE = '23514',
          DETAIL  = format('Order %s has line totals summing to %s.', p_order_id, v_total),
          HINT    = 'Correct the order items and retry.';

-- Retryable failure: past tense, include the underlying reason.
RAISE WARNING 'could not lock order row %: %', p_order_id, SQLERRM
    USING HINT = 'Retry the transaction.';

-- Impossible branch: internal message, no translation/hint needed.
RAISE EXCEPTION 'unrecognized order status: %', v_status
    USING ERRCODE = '22023';
```

Message rules (from PostgreSQL's error message style guide):

- **Primary message**: short, factual, lowercase first letter, no trailing period, never `!`. No implementation details or function names — say what the code was trying to do.
- **DETAIL**: the facts (offending value, object kind). **HINT**: what to do to fix it, even if it does not always apply. Both are complete sentences, capitalized, each ending with a period.
- **Always state the reason.** `could not open file x` is wrong; `could not open file x: permission denied` is right.
- **Past vs present tense**: `could not …` when retrying might succeed; `cannot …` when it is permanently impossible.
- **Active voice**, no `I`; the program is not human. Avoid contractions (`cannot`, not `can't`).
- **Name the object type**: "relation %s", "column %s", "data type %s" — not bare `foo.bar`.
- **Quote embedded names and user-supplied values** that may contain words; do not quote operators or the output of helpers that already quote.
- **Set `ERRCODE`** (SQLSTATE) on every exception you raise; it is the machine-readable contract clients rely on (see `api/` error mapping).
- **Word choice**: replace `unable` with `cannot`/`could not`, `bad`/`illegal` with the actual defect, `unknown` with `unrecognized` (and include the value), and `non-negative` with `greater than or equal to zero`. Spell words out (specification, authentication, statistics, parentheses).
- **Formatting-neutral text**: no tabs, no trailing newline; clients and the log wrap lines. A `\n` may separate paragraphs only.
- In `RAISE`, `%` consumes the next argument and `%%` is a literal percent sign (`%s` is not a `RAISE` placeholder — use `format()` in `DETAIL`/`HINT` if you need typed formatting). `SQLERRM` and `SQLSTATE` expose the caught error's message and code.

## Documenting SQL

When documenting a function, query, or migration (in comments or a spec), follow PostgreSQL's own reference-page layout — a fixed section order so readers always find the parts.

Order: **Synopsis → Description → Parameters → Outputs → Notes → Examples → See Also** (add **Compatibility** for standards/portability notes; **History** only if there are milestones).

```sql
-- Function: order_total(order_id)
--
-- Synopsis:  order_total(p_order_id uuid) RETURNS bigint
-- Returns:   sum of line totals in the smallest currency unit (CLP); NULL if the order has no items.
--
-- Notes:     Money is stored as bigint (see DATABASE_CONVENTIONS); no rounding here.
--            Uses the order_items(order_id) index.
--
-- Example:   SELECT order_total('00000000-0000-0000-0000-000000000000');
CREATE FUNCTION order_total(p_order_id uuid) RETURNS bigint AS $$
    SELECT sum(unit_price * quantity) FROM order_items WHERE order_id = p_order_id;
$$ LANGUAGE sql STABLE;
```

- Keep the *what* in the code; put the *why* (caveats, invariants, security, performance) in **Notes**.
- One runnable **Example** beats a paragraph.

## Checklist

- [ ] JSONB used (not JSON) and queried with `@>` / `#>>`, not `::text LIKE`
- [ ] Arrays only for small read-mostly sets; join tables for relational data
- [ ] Enums defined before use; constraints/domains replace repeated `CHECK`s
- [ ] Range/geometric types used where they fit; exclusion constraints for overlaps
- [ ] Window functions / CTEs used instead of hand-rolled procedural loops
- [ ] FTS via `tsvector` + matched query functions
- [ ] Extensions created with `IF NOT EXISTS` and actually available
- [ ] PL/pgSQL kept set-based; trigger `WHEN` clauses avoid needless fires
- [ ] SQL/PL-pgSQL indented 4 spaces, ~80 columns, matching the surrounding file; no `//` comments
- [ ] `RAISE` messages: lowercase short primary text, complete-sentence DETAIL/HINT, stated reason, `ERRCODE` set
- [ ] Error wording follows the style guide (active voice, correct tense, no "unable"/"bad"/"illegal"/contractions)
- [ ] Functions/migrations documented in Synopsis → Description → Parameters → Outputs → Notes → Examples order
- [ ] Repo rules from `internal/conventions/DATABASE_CONVENTIONS.md` respected (UUID PKs, `TIMESTAMPTZ`, `is_deleted`, money as `BIGINT`)

## Boundaries

- **Index strategy, `EXPLAIN`, planner, pagination, VACUUM, `pg_stat_statements`** → `postgresql-optimization`
- **Schema/normalization, keys, constraints, migrations, RLS/security, retention** → `database-design`
- **Repo-specific schema rules** → `internal/conventions/DATABASE_CONVENTIONS.md`

## References

- `references/postgresql16_coding_conventions.md` — *PostgreSQL 16, Chapter 56: Coding Conventions* (formatting, `ereport`/`elog` severity and auxiliary fields, error message style guide, C/PL conventions). Source of the formatting and `RAISE` message rules above.
Pliki w paczce (2)
  • SKILL.md 13 KB
  • references/postgresql16_coding_conventions.md 26 KB

Wersje

W bazie nie ma innych skilli o nazwie postgresql-patterns.

Migawka bazy z 13.11.2026 · wersja paczki 7a8a0651ee60 (skrót SHA-256 całej paczki)

Pobrania w ostatnich 30 dniach: 0 · ranking

Zgłoś problem z tym skillem: szkodliwa treść, błędny opis albo prośba autora o usunięcie.

Podobne skille

  • 90postgresql
    Wspiera projekt schematu PostgreSQL, optymalizację zapytań, indeksowanie i administrację: JSONB, partycjonowanie, RLS, CTE, funkcje okna i EXPLAIN ANALYZE.
  • 100postgresql
    Pomaga projektować schematy, pisać wydajne zapytania, zarządzać indeksami i obsługiwać bazy PostgreSQL z JSONB, wyszukiwaniem pełnotekstowym, funkcjami okna, CTE, row-level security i replikacją.
  • 84analyze-postgresql-schema
    Analizuje schemat PostgreSQL i tworzy raport w Markdown: tabele, wyzwalacze, typy, kod PL/pgSQL i zależności.
  • 100postgresql
    Pomaga projektować schematy PostgreSQL, optymalizować zapytania, indeksować i administrować: JSONB, partycjonowanie, RLS, CTE, funkcje okna, EXPLAIN ANALYZE i pule połączeń.
  • 100postgresql
    Obsługuje bazę PostgreSQL: zapytania SQL, indeksy, ograniczenia i wydajność, w tym JSONB, funkcje okna, rekurencyjne CTE, row level security, wyszukiwanie pełnotekstowe, partycjonowanie, pgBouncer i replikację.
  • 100postgresql-jsonb-unstructured-data
    Przechowuje, indeksuje i przeszukuje dokumenty półustrukturalne w PostgreSQL przez operatory JSONB i wyrażenia ścieżek.

Uwagi i zgłoszenia

Wiadomość trafi do Bartosza Sokolińskiego. Adres e-mail jest potrzebny tylko do odpowiedzi. Szczegóły w polityce prywatności.