@jgamaraalv/ts-dev-kit 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +24 -0
- package/.claude-plugin/plugin.json +24 -0
- package/CHANGELOG.md +24 -0
- package/LICENSE +21 -0
- package/README.md +128 -0
- package/agents/accessibility-pro.md +139 -0
- package/agents/api-builder.md +110 -0
- package/agents/code-reviewer.md +190 -0
- package/agents/database-expert.md +138 -0
- package/agents/debugger.md +241 -0
- package/agents/docker-expert.md +51 -0
- package/agents/multi-agent-coordinator.md +378 -0
- package/agents/nextjs-expert.md +136 -0
- package/agents/performance-engineer.md +138 -0
- package/agents/playwright-expert.md +126 -0
- package/agents/react-specialist.md +97 -0
- package/agents/security-scanner.md +105 -0
- package/agents/test-generator.md +221 -0
- package/agents/typescript-pro.md +253 -0
- package/agents/ux-optimizer.md +93 -0
- package/docs/rules/orchestration.md.template +126 -0
- package/package.json +28 -0
- package/skills/bullmq/SKILL.md +225 -0
- package/skills/bullmq/references/flows-and-schedulers.md +186 -0
- package/skills/bullmq/references/job-types-and-options.md +163 -0
- package/skills/bullmq/references/patterns.md +273 -0
- package/skills/bullmq/references/production.md +308 -0
- package/skills/composition-patterns/SKILL.md +58 -0
- package/skills/composition-patterns/references/architecture-avoid-boolean-props.md +87 -0
- package/skills/composition-patterns/references/architecture-compound-components.md +107 -0
- package/skills/composition-patterns/references/patterns-children-over-render-props.md +77 -0
- package/skills/composition-patterns/references/patterns-explicit-variants.md +87 -0
- package/skills/composition-patterns/references/react19-no-forwardref.md +37 -0
- package/skills/composition-patterns/references/state-context-interface.md +194 -0
- package/skills/composition-patterns/references/state-decouple-implementation.md +96 -0
- package/skills/composition-patterns/references/state-lift-state.md +126 -0
- package/skills/conventional-commits/SKILL.md +148 -0
- package/skills/docker/SKILL.md +55 -0
- package/skills/docker/references/compose-configs.md +95 -0
- package/skills/docker/references/monorepo-dockerfile.md +111 -0
- package/skills/drizzle-pg/SKILL.md +202 -0
- package/skills/drizzle-pg/references/advanced.md +299 -0
- package/skills/drizzle-pg/references/migrations.md +214 -0
- package/skills/drizzle-pg/references/queries.md +321 -0
- package/skills/drizzle-pg/references/relations.md +272 -0
- package/skills/drizzle-pg/references/schema-pg.md +256 -0
- package/skills/drizzle-pg/references/sql-operator.md +215 -0
- package/skills/fastify-best-practices/SKILL.md +143 -0
- package/skills/fastify-best-practices/references/hooks-and-lifecycle.md +122 -0
- package/skills/fastify-best-practices/references/plugins-and-encapsulation.md +137 -0
- package/skills/fastify-best-practices/references/request-reply-errors.md +189 -0
- package/skills/fastify-best-practices/references/routes-and-handlers.md +134 -0
- package/skills/fastify-best-practices/references/server-and-options.md +127 -0
- package/skills/fastify-best-practices/references/typescript-and-logging.md +223 -0
- package/skills/fastify-best-practices/references/validation-and-serialization.md +190 -0
- package/skills/ioredis/SKILL.md +51 -0
- package/skills/ioredis/references/advanced-patterns.md +312 -0
- package/skills/ioredis/references/cluster-sentinel.md +280 -0
- package/skills/ioredis/references/connection-options.md +187 -0
- package/skills/ioredis/references/core-api.md +179 -0
- package/skills/nextjs-best-practices/SKILL.md +194 -0
- package/skills/nextjs-best-practices/references/async-patterns.md +84 -0
- package/skills/nextjs-best-practices/references/bundling.md +192 -0
- package/skills/nextjs-best-practices/references/data-patterns.md +310 -0
- package/skills/nextjs-best-practices/references/debug-tricks.md +127 -0
- package/skills/nextjs-best-practices/references/directives.md +74 -0
- package/skills/nextjs-best-practices/references/error-handling.md +237 -0
- package/skills/nextjs-best-practices/references/file-conventions.md +152 -0
- package/skills/nextjs-best-practices/references/font.md +175 -0
- package/skills/nextjs-best-practices/references/functions.md +116 -0
- package/skills/nextjs-best-practices/references/hydration-error.md +86 -0
- package/skills/nextjs-best-practices/references/image.md +184 -0
- package/skills/nextjs-best-practices/references/metadata.md +305 -0
- package/skills/nextjs-best-practices/references/parallel-routes.md +299 -0
- package/skills/nextjs-best-practices/references/route-handlers.md +154 -0
- package/skills/nextjs-best-practices/references/rsc-boundaries.md +168 -0
- package/skills/nextjs-best-practices/references/runtime-selection.md +40 -0
- package/skills/nextjs-best-practices/references/scripts.md +148 -0
- package/skills/nextjs-best-practices/references/self-hosting.md +210 -0
- package/skills/nextjs-best-practices/references/suspense-boundaries.md +67 -0
- package/skills/owasp-security-review/SKILL.md +98 -0
- package/skills/owasp-security-review/references/a01-broken-access-control.md +78 -0
- package/skills/owasp-security-review/references/a02-security-misconfiguration.md +81 -0
- package/skills/owasp-security-review/references/a03-supply-chain-failures.md +65 -0
- package/skills/owasp-security-review/references/a04-cryptographic-failures.md +82 -0
- package/skills/owasp-security-review/references/a05-injection.md +106 -0
- package/skills/owasp-security-review/references/a06-insecure-design.md +76 -0
- package/skills/owasp-security-review/references/a07-authentication-failures.md +83 -0
- package/skills/owasp-security-review/references/a08-integrity-failures.md +72 -0
- package/skills/owasp-security-review/references/a09-logging-alerting-failures.md +76 -0
- package/skills/owasp-security-review/references/a10-exceptional-conditions.md +131 -0
- package/skills/postgresql/SKILL.md +50 -0
- package/skills/postgresql/references/ddl-schema.md +300 -0
- package/skills/postgresql/references/indexes.md +257 -0
- package/skills/postgresql/references/jsonb.md +261 -0
- package/skills/postgresql/references/performance.md +291 -0
- package/skills/postgresql/references/psql-cli.md +153 -0
- package/skills/postgresql/references/queries.md +287 -0
- package/skills/postgresql/references/transactions.md +280 -0
- package/skills/react-best-practices/SKILL.md +110 -0
- package/skills/react-best-practices/references/advanced-patterns.md +91 -0
- package/skills/react-best-practices/references/async-patterns.md +233 -0
- package/skills/react-best-practices/references/bundle-optimization.md +201 -0
- package/skills/react-best-practices/references/client-patterns.md +178 -0
- package/skills/react-best-practices/references/js-performance.md +210 -0
- package/skills/react-best-practices/references/rendering-performance.md +209 -0
- package/skills/react-best-practices/references/rerender-optimization.md +316 -0
- package/skills/react-best-practices/references/server-performance.md +274 -0
- package/skills/service-worker/SKILL.md +195 -0
- package/skills/service-worker/references/api-reference.md +114 -0
- package/skills/service-worker/references/caching-strategies.md +202 -0
- package/skills/service-worker/references/push-and-sync.md +261 -0
- package/skills/typescript-conventions/SKILL.md +51 -0
- package/skills/ui-ux-guidelines/SKILL.md +105 -0
- package/skills/ui-ux-guidelines/references/accessibility-and-interaction.md +74 -0
- package/skills/ui-ux-guidelines/references/forms-content-checklist.md +126 -0
- package/skills/ui-ux-guidelines/references/layout-typography-animation.md +95 -0
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# A10:2025 Mishandling of Exceptional Conditions
|
|
2
|
+
|
|
3
|
+
- [What to look for](#what-to-look-for)
|
|
4
|
+
- [Prevention checklist](#prevention-checklist)
|
|
5
|
+
- [Code patterns](#code-patterns)
|
|
6
|
+
- [Key CWEs](#key-cwes)
|
|
7
|
+
|
|
8
|
+
New category for 2025. 24 CWEs, 2.95% avg incidence, 769K+ occurrences.
|
|
9
|
+
|
|
10
|
+
## What to look for
|
|
11
|
+
|
|
12
|
+
**Failing open:**
|
|
13
|
+
|
|
14
|
+
- Error conditions that grant access instead of denying it
|
|
15
|
+
- Try/catch blocks that silently continue on auth/authz errors
|
|
16
|
+
- Default case in permission checks grants access
|
|
17
|
+
- Missing `else` or `default` clause assumes success
|
|
18
|
+
- Transaction failures that leave partial state (not rolled back)
|
|
19
|
+
|
|
20
|
+
**Information leakage via errors:**
|
|
21
|
+
|
|
22
|
+
- Stack traces exposed in HTTP responses
|
|
23
|
+
- Database error messages revealing schema/query details
|
|
24
|
+
- Internal file paths exposed in error messages
|
|
25
|
+
- Technology/version information in error responses
|
|
26
|
+
- Different error responses for different failure modes (enables enumeration)
|
|
27
|
+
|
|
28
|
+
**Unchecked return values:**
|
|
29
|
+
|
|
30
|
+
- Function return values ignored (especially security-critical functions)
|
|
31
|
+
- Promise rejections not handled (unhandledRejection)
|
|
32
|
+
- Null/undefined not checked before use
|
|
33
|
+
- Database query results assumed to always return data
|
|
34
|
+
|
|
35
|
+
**Resource leaks on error:**
|
|
36
|
+
|
|
37
|
+
- File handles not closed in error paths
|
|
38
|
+
- Database connections not released on exception
|
|
39
|
+
- Memory not freed after error conditions
|
|
40
|
+
- Locks not released in exceptional paths
|
|
41
|
+
|
|
42
|
+
**Missing error handling:**
|
|
43
|
+
|
|
44
|
+
- No global exception handler / error middleware
|
|
45
|
+
- Empty catch blocks (`catch (e) {}`)
|
|
46
|
+
- Generic catch-all that swallows specific errors
|
|
47
|
+
- No error boundary in React (uncaught render errors crash the app)
|
|
48
|
+
- Missing `finally` blocks for cleanup
|
|
49
|
+
|
|
50
|
+
**Rate limiting and resource exhaustion:**
|
|
51
|
+
|
|
52
|
+
- No limits on request size, file upload size, query complexity
|
|
53
|
+
- No timeouts on external service calls
|
|
54
|
+
- No circuit breakers for failing dependencies
|
|
55
|
+
- Unlimited concurrent operations lead to resource exhaustion
|
|
56
|
+
|
|
57
|
+
## Prevention checklist
|
|
58
|
+
|
|
59
|
+
- [ ] Implement a global exception handler / error middleware
|
|
60
|
+
- [ ] Fail closed — deny access on any error in auth/authz paths
|
|
61
|
+
- [ ] Roll back entire transactions on failure; never leave partial state
|
|
62
|
+
- [ ] Return generic error messages to users; log detailed errors server-side
|
|
63
|
+
- [ ] Use consistent error response format across the application
|
|
64
|
+
- [ ] Check all return values from security-critical functions
|
|
65
|
+
- [ ] Handle all Promise rejections (`.catch()` or `try/catch` with `await`)
|
|
66
|
+
- [ ] Clean up resources in `finally` blocks (connections, file handles, locks)
|
|
67
|
+
- [ ] Never use empty catch blocks — at minimum, log the error
|
|
68
|
+
- [ ] Add error boundaries in React for graceful UI degradation
|
|
69
|
+
- [ ] Set rate limits, request size limits, and timeouts everywhere
|
|
70
|
+
- [ ] Add circuit breakers for external service calls
|
|
71
|
+
- [ ] Centralize error handling — one pattern across the entire application
|
|
72
|
+
- [ ] Aggregate repeated identical errors into statistics above a threshold
|
|
73
|
+
- [ ] Test error paths: stress testing, fault injection, chaos engineering
|
|
74
|
+
|
|
75
|
+
## Code patterns
|
|
76
|
+
|
|
77
|
+
**Bad — Failing open:**
|
|
78
|
+
|
|
79
|
+
```js
|
|
80
|
+
let isAdmin = false;
|
|
81
|
+
try {
|
|
82
|
+
isAdmin = await checkAdminRole(userId);
|
|
83
|
+
} catch (e) {
|
|
84
|
+
// silently continue — isAdmin stays false... or does it?
|
|
85
|
+
}
|
|
86
|
+
// If checkAdminRole throws after setting isAdmin = true...
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**Good — Failing closed:**
|
|
90
|
+
|
|
91
|
+
```js
|
|
92
|
+
let isAdmin;
|
|
93
|
+
try {
|
|
94
|
+
isAdmin = await checkAdminRole(userId);
|
|
95
|
+
} catch (e) {
|
|
96
|
+
logger.error("Admin check failed", { userId, error: e });
|
|
97
|
+
throw new ForbiddenError("Access denied");
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
**Bad — Empty catch:**
|
|
102
|
+
|
|
103
|
+
```js
|
|
104
|
+
try {
|
|
105
|
+
await riskyOperation();
|
|
106
|
+
} catch (e) {}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
**Good — Log and handle:**
|
|
110
|
+
|
|
111
|
+
```js
|
|
112
|
+
try {
|
|
113
|
+
await riskyOperation();
|
|
114
|
+
} catch (e) {
|
|
115
|
+
logger.error("riskyOperation failed", { error: e });
|
|
116
|
+
throw new InternalError("Operation failed");
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Key CWEs
|
|
121
|
+
|
|
122
|
+
| CWE | Name | Common in |
|
|
123
|
+
| --- | ------------------------------------------------- | ------------------------ |
|
|
124
|
+
| 209 | Error Message Containing Sensitive Info | API error responses |
|
|
125
|
+
| 636 | Not Failing Securely (Failing Open) | Auth error paths |
|
|
126
|
+
| 248 | Uncaught Exception | Missing try/catch |
|
|
127
|
+
| 252 | Unchecked Return Value | Ignored function results |
|
|
128
|
+
| 476 | NULL Pointer Dereference | Missing null checks |
|
|
129
|
+
| 754 | Improper Check for Unusual Conditions | Edge cases not handled |
|
|
130
|
+
| 755 | Improper Handling of Exceptional Conditions | Generic catch-all |
|
|
131
|
+
| 703 | Improper Check/Handling of Exceptional Conditions | Missing error handling |
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: postgresql
|
|
3
|
+
description: "PostgreSQL 16+ reference for writing queries, designing schemas, managing indexes, and optimizing performance. Use when: (1) writing SQL queries (SELECT, INSERT, UPDATE, DELETE, CTEs, window functions, subqueries), (2) designing or altering table schemas (CREATE TABLE, constraints, sequences, data types), (3) choosing or creating indexes (B-tree, GIN, GiST, BRIN, partial, expression), (4) managing transactions and isolation levels (BEGIN/COMMIT, savepoints, MVCC), (5) working with JSONB data and jsonpath, (6) analyzing query performance with EXPLAIN ANALYZE, or (7) using the psql CLI."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# PostgreSQL 16+ Reference
|
|
7
|
+
|
|
8
|
+
Version: **16+**. All syntax is standard; most features apply to PostgreSQL 13+.
|
|
9
|
+
|
|
10
|
+
## Quick patterns
|
|
11
|
+
|
|
12
|
+
```sql
|
|
13
|
+
-- Check running queries
|
|
14
|
+
SELECT pid, state, wait_event_type, query FROM pg_stat_activity WHERE state != 'idle';
|
|
15
|
+
|
|
16
|
+
-- Explain a slow query
|
|
17
|
+
EXPLAIN (ANALYZE, BUFFERS, FORMAT TEXT) SELECT ...;
|
|
18
|
+
|
|
19
|
+
-- List table sizes
|
|
20
|
+
SELECT relname, pg_size_pretty(pg_total_relation_size(oid)) FROM pg_class
|
|
21
|
+
WHERE relkind = 'r' ORDER BY pg_total_relation_size(oid) DESC;
|
|
22
|
+
|
|
23
|
+
-- Kill a blocking query
|
|
24
|
+
SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE pid = <pid>;
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Reference files
|
|
28
|
+
|
|
29
|
+
Load the relevant file when working on a specific topic:
|
|
30
|
+
|
|
31
|
+
| Topic | File | When to read |
|
|
32
|
+
| -------------------------------------- | -------------------------------------------------------- | -------------------------------------- |
|
|
33
|
+
| SELECT, JOINs, CTEs, window functions | [references/queries.md](references/queries.md) | Writing or debugging any query |
|
|
34
|
+
| CREATE TABLE, ALTER TABLE, constraints | [references/ddl-schema.md](references/ddl-schema.md) | Designing or modifying schemas |
|
|
35
|
+
| Index types, creation, strategy | [references/indexes.md](references/indexes.md) | Adding indexes or fixing slow queries |
|
|
36
|
+
| Transactions, savepoints, isolation | [references/transactions.md](references/transactions.md) | Concurrency, locking, isolation issues |
|
|
37
|
+
| JSONB operators, GIN, jsonpath | [references/jsonb.md](references/jsonb.md) | Working with JSON/JSONB columns |
|
|
38
|
+
| EXPLAIN output, VACUUM, stats | [references/performance.md](references/performance.md) | Query tuning or performance analysis |
|
|
39
|
+
| psql meta-commands | [references/psql-cli.md](references/psql-cli.md) | Working interactively in psql |
|
|
40
|
+
|
|
41
|
+
## Key non-obvious facts
|
|
42
|
+
|
|
43
|
+
- Every statement runs in a transaction. Without `BEGIN`, each statement auto-commits.
|
|
44
|
+
- `jsonb` stores parsed binary (faster queries); `json` stores raw text (exact input preserved). Prefer `jsonb`.
|
|
45
|
+
- `LIKE 'foo%'` can use B-tree; `LIKE '%foo'` cannot — use `pg_trgm` GIN for suffix search.
|
|
46
|
+
- `CREATE INDEX CONCURRENTLY` avoids table lock but cannot run inside a transaction block.
|
|
47
|
+
- `EXPLAIN` without `ANALYZE` shows the planner's _estimate_. Always use `EXPLAIN (ANALYZE, BUFFERS)` for real data.
|
|
48
|
+
- Null values are stored in indexes by B-tree (unlike some other databases). `IS NULL` can use an index.
|
|
49
|
+
- `SERIAL`/`BIGSERIAL` are shorthand for sequence + default; prefer `GENERATED ALWAYS AS IDENTITY` (SQL standard).
|
|
50
|
+
- Default isolation level is **Read Committed**. `SERIALIZABLE` prevents all anomalies but may abort transactions.
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
# PostgreSQL DDL & Schema Reference
|
|
2
|
+
|
|
3
|
+
## Table of Contents
|
|
4
|
+
|
|
5
|
+
1. [Data types cheatsheet](#data-types)
|
|
6
|
+
2. [CREATE TABLE](#create-table)
|
|
7
|
+
3. [Constraints](#constraints)
|
|
8
|
+
4. [ALTER TABLE](#alter-table)
|
|
9
|
+
5. [Sequences & identity](#sequences)
|
|
10
|
+
6. [Schemas & namespaces](#schemas)
|
|
11
|
+
7. [Views & materialized views](#views)
|
|
12
|
+
8. [Partitioning](#partitioning)
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Data types
|
|
17
|
+
|
|
18
|
+
| Category | Types | Notes |
|
|
19
|
+
| -------------- | ---------------------------------------------------- | --------------------------------------------------------- |
|
|
20
|
+
| Integer | `smallint` (2B), `integer`/`int` (4B), `bigint` (8B) | Use `bigint` for PKs on large tables |
|
|
21
|
+
| Auto-increment | `GENERATED ALWAYS AS IDENTITY` | Preferred over `SERIAL` |
|
|
22
|
+
| Decimal | `numeric(p,s)` / `decimal(p,s)` | Exact; use for money. `real`/`double precision` are float |
|
|
23
|
+
| Text | `text` (unlimited), `varchar(n)`, `char(n)` | `text` = `varchar` without limit; prefer `text` |
|
|
24
|
+
| Boolean | `boolean` | Values: `true`/`false`, `'t'`/`'f'`, `1`/`0` |
|
|
25
|
+
| Dates | `date`, `time`, `timestamp`, `timestamptz` | Always use `timestamptz` for app timestamps |
|
|
26
|
+
| Interval | `interval` | e.g., `INTERVAL '3 days'`, `INTERVAL '1 hour 30 min'` |
|
|
27
|
+
| UUID | `uuid` | Use `gen_random_uuid()` (pgcrypto) for default |
|
|
28
|
+
| JSON | `json`, `jsonb` | Use `jsonb` — binary, indexable, faster queries |
|
|
29
|
+
| Arrays | `int[]`, `text[]` | e.g., `ARRAY['a','b']` or `'{a,b}'::text[]` |
|
|
30
|
+
| Geometric | `point`, `line`, `polygon`, `circle` | Use PostGIS for serious geo work |
|
|
31
|
+
| Network | `inet`, `cidr`, `macaddr` | |
|
|
32
|
+
| Bytea | `bytea` | Binary data |
|
|
33
|
+
| Enum | `CREATE TYPE mood AS ENUM ('happy','sad')` | Fast equality, no range ops |
|
|
34
|
+
| Composite | `CREATE TYPE address AS (street text, city text)` | |
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## CREATE TABLE
|
|
39
|
+
|
|
40
|
+
```sql
|
|
41
|
+
CREATE TABLE users (
|
|
42
|
+
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
|
43
|
+
email text NOT NULL UNIQUE,
|
|
44
|
+
username text NOT NULL CHECK (length(username) >= 3),
|
|
45
|
+
status text NOT NULL DEFAULT 'active' CHECK (status IN ('active','inactive','banned')),
|
|
46
|
+
role text NOT NULL DEFAULT 'user',
|
|
47
|
+
metadata jsonb NOT NULL DEFAULT '{}',
|
|
48
|
+
created_at timestamptz NOT NULL DEFAULT NOW(),
|
|
49
|
+
updated_at timestamptz NOT NULL DEFAULT NOW()
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
-- With composite primary key
|
|
53
|
+
CREATE TABLE order_items (
|
|
54
|
+
order_id bigint NOT NULL REFERENCES orders(id) ON DELETE CASCADE,
|
|
55
|
+
product_id bigint NOT NULL REFERENCES products(id),
|
|
56
|
+
quantity integer NOT NULL CHECK (quantity > 0),
|
|
57
|
+
price numeric(10,2) NOT NULL,
|
|
58
|
+
PRIMARY KEY (order_id, product_id)
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
-- Partitioned table
|
|
62
|
+
CREATE TABLE logs (
|
|
63
|
+
id bigint GENERATED ALWAYS AS IDENTITY,
|
|
64
|
+
created_at timestamptz NOT NULL,
|
|
65
|
+
payload jsonb
|
|
66
|
+
) PARTITION BY RANGE (created_at);
|
|
67
|
+
|
|
68
|
+
-- IF NOT EXISTS
|
|
69
|
+
CREATE TABLE IF NOT EXISTS config (key text PRIMARY KEY, value text);
|
|
70
|
+
|
|
71
|
+
-- LIKE (copy structure)
|
|
72
|
+
CREATE TABLE users_archive (LIKE users INCLUDING ALL);
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Constraints
|
|
78
|
+
|
|
79
|
+
### Check constraints
|
|
80
|
+
|
|
81
|
+
```sql
|
|
82
|
+
-- Inline
|
|
83
|
+
amount numeric NOT NULL CHECK (amount > 0)
|
|
84
|
+
|
|
85
|
+
-- Named (easier to drop/identify)
|
|
86
|
+
amount numeric NOT NULL CONSTRAINT positive_amount CHECK (amount > 0)
|
|
87
|
+
|
|
88
|
+
-- Table-level (multi-column)
|
|
89
|
+
ALTER TABLE orders ADD CONSTRAINT valid_date_range CHECK (end_date > start_date);
|
|
90
|
+
|
|
91
|
+
-- Drop
|
|
92
|
+
ALTER TABLE orders DROP CONSTRAINT valid_date_range;
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### NOT NULL
|
|
96
|
+
|
|
97
|
+
```sql
|
|
98
|
+
-- Add NOT NULL (requires a default or no existing NULLs)
|
|
99
|
+
ALTER TABLE users ALTER COLUMN phone SET NOT NULL;
|
|
100
|
+
|
|
101
|
+
-- Remove NOT NULL
|
|
102
|
+
ALTER TABLE users ALTER COLUMN phone DROP NOT NULL;
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### UNIQUE constraints
|
|
106
|
+
|
|
107
|
+
```sql
|
|
108
|
+
-- Single column (inline)
|
|
109
|
+
email text UNIQUE
|
|
110
|
+
|
|
111
|
+
-- Named single column
|
|
112
|
+
email text CONSTRAINT unique_email UNIQUE
|
|
113
|
+
|
|
114
|
+
-- Composite unique (table-level only)
|
|
115
|
+
ALTER TABLE user_roles ADD CONSTRAINT unique_user_role UNIQUE (user_id, role_id);
|
|
116
|
+
|
|
117
|
+
-- Unique index (same effect, more control)
|
|
118
|
+
CREATE UNIQUE INDEX ON users (lower(email)); -- case-insensitive unique email
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Primary keys
|
|
122
|
+
|
|
123
|
+
```sql
|
|
124
|
+
-- Inline
|
|
125
|
+
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY
|
|
126
|
+
|
|
127
|
+
-- Table-level (composite)
|
|
128
|
+
PRIMARY KEY (tenant_id, user_id)
|
|
129
|
+
|
|
130
|
+
-- Add PK after creation
|
|
131
|
+
ALTER TABLE old_table ADD PRIMARY KEY (id);
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Foreign keys
|
|
135
|
+
|
|
136
|
+
```sql
|
|
137
|
+
-- Basic
|
|
138
|
+
REFERENCES other_table(id)
|
|
139
|
+
|
|
140
|
+
-- Named with actions
|
|
141
|
+
CONSTRAINT fk_user
|
|
142
|
+
FOREIGN KEY (user_id)
|
|
143
|
+
REFERENCES users(id)
|
|
144
|
+
ON DELETE CASCADE -- also: SET NULL, SET DEFAULT, RESTRICT, NO ACTION
|
|
145
|
+
ON UPDATE CASCADE
|
|
146
|
+
DEFERRABLE INITIALLY DEFERRED -- check at COMMIT time, not row-by-row
|
|
147
|
+
|
|
148
|
+
-- Add after creation
|
|
149
|
+
ALTER TABLE orders ADD CONSTRAINT fk_customer
|
|
150
|
+
FOREIGN KEY (customer_id) REFERENCES customers(id) ON DELETE RESTRICT;
|
|
151
|
+
|
|
152
|
+
-- Drop
|
|
153
|
+
ALTER TABLE orders DROP CONSTRAINT fk_customer;
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Exclusion constraints (PostGIS / ranges)
|
|
157
|
+
|
|
158
|
+
```sql
|
|
159
|
+
-- No overlapping reservations for the same room
|
|
160
|
+
ALTER TABLE reservations ADD CONSTRAINT no_overlap
|
|
161
|
+
EXCLUDE USING GIST (room_id WITH =, period WITH &&);
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## ALTER TABLE
|
|
167
|
+
|
|
168
|
+
```sql
|
|
169
|
+
-- Add column
|
|
170
|
+
ALTER TABLE users ADD COLUMN avatar_url text;
|
|
171
|
+
ALTER TABLE users ADD COLUMN score integer NOT NULL DEFAULT 0;
|
|
172
|
+
|
|
173
|
+
-- Drop column
|
|
174
|
+
ALTER TABLE users DROP COLUMN avatar_url;
|
|
175
|
+
ALTER TABLE users DROP COLUMN avatar_url CASCADE; -- also drops dependencies
|
|
176
|
+
|
|
177
|
+
-- Rename column
|
|
178
|
+
ALTER TABLE users RENAME COLUMN username TO handle;
|
|
179
|
+
|
|
180
|
+
-- Change type
|
|
181
|
+
ALTER TABLE users ALTER COLUMN score TYPE bigint;
|
|
182
|
+
ALTER TABLE users ALTER COLUMN score TYPE numeric USING score::numeric;
|
|
183
|
+
|
|
184
|
+
-- Set/drop default
|
|
185
|
+
ALTER TABLE users ALTER COLUMN status SET DEFAULT 'active';
|
|
186
|
+
ALTER TABLE users ALTER COLUMN status DROP DEFAULT;
|
|
187
|
+
|
|
188
|
+
-- Rename table
|
|
189
|
+
ALTER TABLE users RENAME TO accounts;
|
|
190
|
+
|
|
191
|
+
-- Add/drop schema
|
|
192
|
+
ALTER TABLE users SET SCHEMA archive;
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## Sequences & identity
|
|
198
|
+
|
|
199
|
+
```sql
|
|
200
|
+
-- Modern: GENERATED ALWAYS AS IDENTITY (SQL standard, preferred)
|
|
201
|
+
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY
|
|
202
|
+
-- Override allowed only with OVERRIDING SYSTEM VALUE:
|
|
203
|
+
INSERT INTO t (id, name) OVERRIDING SYSTEM VALUE VALUES (999, 'admin');
|
|
204
|
+
|
|
205
|
+
-- GENERATED BY DEFAULT AS IDENTITY (allows override without keyword)
|
|
206
|
+
id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY
|
|
207
|
+
|
|
208
|
+
-- Old: SERIAL (shorthand, still common)
|
|
209
|
+
id serial PRIMARY KEY -- int + sequence
|
|
210
|
+
id bigserial PRIMARY KEY -- bigint + sequence
|
|
211
|
+
|
|
212
|
+
-- Manual sequence
|
|
213
|
+
CREATE SEQUENCE order_number_seq START 1000 INCREMENT 1;
|
|
214
|
+
SELECT nextval('order_number_seq');
|
|
215
|
+
SELECT currval('order_number_seq');
|
|
216
|
+
SELECT setval('order_number_seq', 5000);
|
|
217
|
+
|
|
218
|
+
-- Reset identity sequence after bulk insert
|
|
219
|
+
ALTER TABLE users ALTER COLUMN id RESTART WITH 1;
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
## Schemas
|
|
225
|
+
|
|
226
|
+
```sql
|
|
227
|
+
CREATE SCHEMA analytics;
|
|
228
|
+
CREATE TABLE analytics.events (...);
|
|
229
|
+
|
|
230
|
+
-- Search path (which schemas to look in, in order)
|
|
231
|
+
SET search_path TO myapp, public;
|
|
232
|
+
SHOW search_path;
|
|
233
|
+
|
|
234
|
+
-- Grant
|
|
235
|
+
GRANT USAGE ON SCHEMA analytics TO readonly_role;
|
|
236
|
+
GRANT SELECT ON ALL TABLES IN SCHEMA analytics TO readonly_role;
|
|
237
|
+
ALTER DEFAULT PRIVILEGES IN SCHEMA analytics GRANT SELECT ON TABLES TO readonly_role;
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## Views & materialized views
|
|
243
|
+
|
|
244
|
+
```sql
|
|
245
|
+
-- View
|
|
246
|
+
CREATE OR REPLACE VIEW active_users AS
|
|
247
|
+
SELECT * FROM users WHERE status = 'active';
|
|
248
|
+
|
|
249
|
+
-- Updatable views (automatically updatable if simple enough)
|
|
250
|
+
CREATE VIEW recent_orders AS SELECT * FROM orders WHERE created_at > NOW() - INTERVAL '30 days';
|
|
251
|
+
|
|
252
|
+
-- Materialized view (cached snapshot)
|
|
253
|
+
CREATE MATERIALIZED VIEW daily_stats AS
|
|
254
|
+
SELECT DATE_TRUNC('day', created_at) AS day, COUNT(*) FROM events GROUP BY 1;
|
|
255
|
+
|
|
256
|
+
-- Refresh (blocks reads by default)
|
|
257
|
+
REFRESH MATERIALIZED VIEW daily_stats;
|
|
258
|
+
|
|
259
|
+
-- Refresh without locking (needs unique index)
|
|
260
|
+
CREATE UNIQUE INDEX ON daily_stats (day);
|
|
261
|
+
REFRESH MATERIALIZED VIEW CONCURRENTLY daily_stats;
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
---
|
|
265
|
+
|
|
266
|
+
## Partitioning
|
|
267
|
+
|
|
268
|
+
```sql
|
|
269
|
+
-- Create parent table
|
|
270
|
+
CREATE TABLE metrics (
|
|
271
|
+
id bigint GENERATED ALWAYS AS IDENTITY,
|
|
272
|
+
recorded_at timestamptz NOT NULL,
|
|
273
|
+
value numeric
|
|
274
|
+
) PARTITION BY RANGE (recorded_at);
|
|
275
|
+
|
|
276
|
+
-- Create monthly partitions
|
|
277
|
+
CREATE TABLE metrics_2025_01 PARTITION OF metrics
|
|
278
|
+
FOR VALUES FROM ('2025-01-01') TO ('2025-02-01');
|
|
279
|
+
CREATE TABLE metrics_2025_02 PARTITION OF metrics
|
|
280
|
+
FOR VALUES FROM ('2025-02-01') TO ('2025-03-01');
|
|
281
|
+
|
|
282
|
+
-- Default partition (catches anything not matched)
|
|
283
|
+
CREATE TABLE metrics_default PARTITION OF metrics DEFAULT;
|
|
284
|
+
|
|
285
|
+
-- List partitioning
|
|
286
|
+
CREATE TABLE orders (id bigint, region text, ...) PARTITION BY LIST (region);
|
|
287
|
+
CREATE TABLE orders_br PARTITION OF orders FOR VALUES IN ('BR', 'PT');
|
|
288
|
+
CREATE TABLE orders_us PARTITION OF orders FOR VALUES IN ('US', 'CA');
|
|
289
|
+
|
|
290
|
+
-- Detach (fast, non-blocking) / Attach partition
|
|
291
|
+
ALTER TABLE metrics DETACH PARTITION metrics_2025_01 CONCURRENTLY;
|
|
292
|
+
ALTER TABLE metrics ATTACH PARTITION metrics_archive
|
|
293
|
+
FOR VALUES FROM ('2020-01-01') TO ('2025-01-01');
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
Key partitioning facts:
|
|
297
|
+
|
|
298
|
+
- Partition key column cannot be NULL (goes to DEFAULT partition).
|
|
299
|
+
- Indexes must be created on each partition separately (or on the parent to cascade).
|
|
300
|
+
- `PARTITION PRUNING` happens automatically at query time when the WHERE clause matches the partition key.
|