Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@
"serverless",
"postgresql"
],
"version": "1.6.1"
"version": "1.7.0"
},
{
"category": "deployment",
Expand Down
2 changes: 1 addition & 1 deletion plugins/databases-on-aws/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,5 @@
"license": "Apache-2.0",
"name": "databases-on-aws",
"repository": "https://github.com/awslabs/agent-plugins",
"version": "1.6.1"
"version": "1.7.0"
}
2 changes: 1 addition & 1 deletion plugins/databases-on-aws/.codex-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "databases-on-aws",
"version": "1.6.1",
"version": "1.7.0",
"description": "Expert database guidance for the AWS database portfolio. Design schemas, execute queries, handle migrations, and choose the right database for your workload.",
"author": {
"name": "Amazon Web Services",
Expand Down
12 changes: 6 additions & 6 deletions plugins/databases-on-aws/skills/dsql/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@ Load these files as needed for detailed guidance:

### DDL Migrations:

| Reference | When to Load | Contains |
| --------------------------------------------------------------------------------------------- | ------------------------------------------------------ | --------------------------------------- |
| [ddl-migrations/overview.md](references/ddl-migrations/overview.md) | MUST load for DROP COLUMN, ALTER TYPE, DROP CONSTRAINT | Table recreation pattern, verify & swap |
| [ddl-migrations/column-operations.md](references/ddl-migrations/column-operations.md) | DROP COLUMN, ALTER TYPE, SET/DROP NOT NULL/DEFAULT | Column-level migration patterns |
| [ddl-migrations/constraint-operations.md](references/ddl-migrations/constraint-operations.md) | ADD/DROP CONSTRAINT, MODIFY PRIMARY KEY | Constraint and structural changes |
| [ddl-migrations/batched-migration.md](references/ddl-migrations/batched-migration.md) | Tables exceeding 3,000 rows | Batching patterns, progress tracking |
| Reference | When to Load | Contains |
| --------------------------------------------------------------------------------------------- | ------------------------------------------------------------ | --------------------------------------- |
| [ddl-migrations/overview.md](references/ddl-migrations/overview.md) | MUST load for DROP COLUMN, ALTER TYPE, DROP CONSTRAINT | Table recreation pattern, verify & swap |
| [ddl-migrations/column-operations.md](references/ddl-migrations/column-operations.md) | DROP COLUMN, ALTER TYPE, SET/DROP NOT NULL/DEFAULT | Column-level migration patterns |
| [ddl-migrations/constraint-operations.md](references/ddl-migrations/constraint-operations.md) | ADD/DROP CONSTRAINT, VALIDATE CONSTRAINT, MODIFY PRIMARY KEY | Constraint and structural changes |
| [ddl-migrations/batched-migration.md](references/ddl-migrations/batched-migration.md) | Tables exceeding 3,000 rows | Batching patterns, progress tracking |

### MySQL Migrations:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,59 @@ Step-by-step migration patterns for constraint changes, primary key modification

---

## ADD CONSTRAINT Migration
## ADD CHECK CONSTRAINT (Preferred)

**Goal:** Add a constraint (UNIQUE, CHECK) to an existing table.
**Goal:** Add a CHECK constraint to an existing table without table recreation.

This is the **preferred** approach for CHECK constraints. It avoids full table recreation by adding the constraint as NOT VALID (applies to new rows immediately) and then validating existing rows asynchronously in the background.

> **Note:** This pattern applies to CHECK constraints only. UNIQUE and PRIMARY KEY constraints still require the [Table Recreation Pattern](#add-unique-constraint-migration) below.

### Migration Steps

#### Step 1: Add constraint with NOT VALID

```sql
transact([
"ALTER TABLE target_table ADD CONSTRAINT chk_age CHECK (age >= 0) NOT VALID"
])
```

The constraint applies immediately to all new inserts and updates. Existing rows are not scanned.

#### Step 2: Validate asynchronously

```sql
transact([
"ALTER TABLE ASYNC target_table VALIDATE CONSTRAINT chk_age"
])
-- Returns a job_id
```

#### Step 3: Monitor validation

```sql
-- Option A: Poll job status
readonly_query(
"SELECT * FROM sys.jobs WHERE job_id = '<job_id>'"
)

-- Option B: Block until complete
readonly_query(
"SELECT sys.wait_for_job('<job_id>')"
)
```

### Outcomes

- **Success:** DSQL marks the constraint as VALID. The query planner enforces it for all queries.
- **Failure:** The constraint remains NOT VALID. Existing rows violate the constraint. Fix the data and re-run VALIDATE CONSTRAINT.

---

## ADD UNIQUE CONSTRAINT Migration

**Goal:** Add a UNIQUE constraint to an existing table (requires table recreation).

### Pre-Migration Validation

Expand All @@ -21,13 +71,6 @@ readonly_query(
GROUP BY target_column HAVING COUNT(*) > 1 LIMIT 10"
)
-- MUST ABORT if any duplicates exist

-- For CHECK constraint: validate all rows pass
readonly_query(
"SELECT COUNT(*) as invalid_count FROM target_table
WHERE NOT (check_condition)"
)
-- MUST ABORT if invalid_count > 0
```

### Migration Steps
Expand All @@ -39,7 +82,6 @@ transact([
"CREATE TABLE target_table_new (
id UUID PRIMARY KEY,
email VARCHAR(255) UNIQUE, -- Added UNIQUE constraint
age INTEGER CHECK (age >= 0), -- Added CHECK constraint
other_column TEXT
)"
])
Expand All @@ -49,8 +91,8 @@ transact([

```sql
transact([
"INSERT INTO target_table_new (id, email, age, other_column)
SELECT id, email, age, other_column
"INSERT INTO target_table_new (id, email, other_column)
SELECT id, email, other_column
FROM target_table"
])
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ effortless scaling, multi-region viability, among other advantages.
- MAXIMUM: **24 indexes per table**
- MAXIMUM: **8 columns per index**
- **MUST** verify index is ready before relying on it: `SELECT indisvalid FROM pg_index WHERE indexrelid = 'index_name'::regclass` — queries work but skip the index until `indisvalid = true`
- MUST use **`ALTER TABLE ASYNC ... VALIDATE CONSTRAINT`** for constraint validation: No synchronous validation
- **MUST** add CHECK constraints with `NOT VALID`: `ALTER TABLE t ADD CONSTRAINT c CHECK (expr) NOT VALID`
- Then validate asynchronously: `ALTER TABLE ASYNC t VALIDATE CONSTRAINT c` — returns a `job_id`
- **MUST** monitor via `sys.jobs` or block with `SELECT sys.wait_for_job('job_id')`
- Constraint applies to new rows immediately; existing rows validated in background
- **Asynchronous Execution:** DDL ALWAYS runs asynchronously
- To add a column with DEFAULT or NOT NULL:
1. MUST issue ADD COLUMN specifying only the column name and data type
Expand Down Expand Up @@ -124,10 +129,12 @@ instead implementation:
### Schema Operations

```sql
CREATE INDEX ASYNC idx_name ON table(column); ← ALWAYS ASYNC
ALTER TABLE t ADD COLUMN c VARCHAR(50); ← ONE AT A TIME
ALTER TABLE t ADD COLUMN c2 INTEGER; ← SEPARATE STATEMENT
UPDATE table SET c = 'default' WHERE c IS NULL; ← AFTER ADD COLUMN
CREATE INDEX ASYNC idx_name ON table(column); ← ALWAYS ASYNC
ALTER TABLE t ADD CONSTRAINT c CHECK (age >= 0) NOT VALID; ← NOT VALID required
ALTER TABLE ASYNC t VALIDATE CONSTRAINT c; ← ALWAYS ASYNC
ALTER TABLE t ADD COLUMN c VARCHAR(50); ← ONE AT A TIME
ALTER TABLE t ADD COLUMN c2 INTEGER; ← SEPARATE STATEMENT
UPDATE table SET c = 'default' WHERE c IS NULL; ← AFTER ADD COLUMN
```

### Supported Data Types
Expand Down
Loading