🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
202 lines
4.5 KiB
Markdown
Executable File
202 lines
4.5 KiB
Markdown
Executable File
---
|
|
name: migrations
|
|
description: RSX database migrations with raw SQL enforcement, forward-only philosophy, and automatic normalization. Use when creating database tables, understanding migration workflow, or troubleshooting Schema builder violations.
|
|
---
|
|
|
|
# RSX Database Migrations
|
|
|
|
## Philosophy
|
|
|
|
RSX enforces a forward-only migration strategy with raw SQL:
|
|
|
|
1. **Forward-only** - No rollbacks, no `down()` methods
|
|
2. **Raw SQL only** - Direct MySQL statements, no Schema builder
|
|
3. **Fail loud** - Migrations must succeed or fail with clear errors
|
|
4. **Snapshot safety** - Development requires database snapshots
|
|
|
|
---
|
|
|
|
## Schema Builder is Prohibited
|
|
|
|
All migrations **must** use `DB::statement()` with raw SQL:
|
|
|
|
```php
|
|
// ✅ CORRECT
|
|
DB::statement("CREATE TABLE products (
|
|
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
|
name VARCHAR(255) NOT NULL,
|
|
price DECIMAL(10,2) NOT NULL DEFAULT 0.00
|
|
)");
|
|
|
|
// ❌ WRONG - Schema builder prohibited
|
|
Schema::create('products', function (Blueprint $table) {
|
|
$table->id();
|
|
$table->string('name');
|
|
});
|
|
```
|
|
|
|
**Prohibited**: `Schema::create()`, `Schema::table()`, `Schema::drop()`, `Blueprint`, `$table->` chains
|
|
|
|
---
|
|
|
|
## Development Workflow
|
|
|
|
```bash
|
|
# 1. Create migration
|
|
php artisan make:migration:safe create_products_table
|
|
|
|
# 2. Write migration with raw SQL
|
|
|
|
# 3. Run migrations (auto-snapshot in development)
|
|
php artisan migrate
|
|
```
|
|
|
|
In development mode, `migrate` automatically:
|
|
- Creates database snapshot before running
|
|
- Commits on success (regenerates constants, recompiles bundles)
|
|
- Auto-rollbacks on failure (database restored to pre-migration state)
|
|
|
|
---
|
|
|
|
## Automatic Normalization
|
|
|
|
The system auto-normalizes types after migration. You can write simpler SQL:
|
|
|
|
| You Write | System Converts To |
|
|
|-----------|-------------------|
|
|
| `INT` | `BIGINT` |
|
|
| `TEXT` | `LONGTEXT` |
|
|
| `FLOAT` | `DOUBLE` |
|
|
| `TINYINT(1)` | Preserved (boolean) |
|
|
|
|
**Auto-added columns** (don't include manually):
|
|
- `created_at TIMESTAMP(3)`
|
|
- `updated_at TIMESTAMP(3)`
|
|
- `created_by BIGINT`
|
|
- `updated_by BIGINT`
|
|
|
|
---
|
|
|
|
## Migration Examples
|
|
|
|
### Simple Table (Recommended)
|
|
|
|
```php
|
|
public function up()
|
|
{
|
|
DB::statement("
|
|
CREATE TABLE products (
|
|
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
|
name VARCHAR(255) NOT NULL,
|
|
description TEXT,
|
|
price DECIMAL(10,2) NOT NULL DEFAULT 0.00,
|
|
stock_quantity INT NOT NULL DEFAULT 0,
|
|
is_active TINYINT(1) NOT NULL DEFAULT 1,
|
|
category_id INT NULL,
|
|
INDEX idx_category (category_id),
|
|
INDEX idx_active (is_active)
|
|
)
|
|
");
|
|
}
|
|
```
|
|
|
|
**Notes**:
|
|
- `INT` becomes `BIGINT` automatically
|
|
- `TEXT` becomes `LONGTEXT` automatically
|
|
- `created_at`/`updated_at` added automatically
|
|
- `TINYINT(1)` preserved for booleans
|
|
|
|
### Adding Columns
|
|
|
|
```php
|
|
public function up()
|
|
{
|
|
DB::statement("
|
|
ALTER TABLE products
|
|
ADD COLUMN sku VARCHAR(50) NULL AFTER name,
|
|
ADD COLUMN weight DECIMAL(8,2) NULL,
|
|
ADD INDEX idx_sku (sku)
|
|
");
|
|
}
|
|
```
|
|
|
|
### Foreign Keys
|
|
|
|
```php
|
|
public function up()
|
|
{
|
|
DB::statement("
|
|
ALTER TABLE orders
|
|
ADD CONSTRAINT fk_orders_customer
|
|
FOREIGN KEY (customer_id) REFERENCES customers(id)
|
|
ON DELETE CASCADE
|
|
");
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Required Table Structure
|
|
|
|
**Every table MUST have**:
|
|
|
|
```sql
|
|
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY
|
|
```
|
|
|
|
This is non-negotiable. Use SIGNED (not UNSIGNED) for easier future migrations.
|
|
|
|
---
|
|
|
|
## Foreign Key Columns
|
|
|
|
Foreign key columns **must match** the referenced column type exactly:
|
|
|
|
```sql
|
|
-- If users.id is BIGINT, then:
|
|
user_id BIGINT NULL -- ✅ Matches
|
|
|
|
-- Column names ending in _id are assumed to be foreign keys
|
|
```
|
|
|
|
---
|
|
|
|
## Debug/Production Workflow
|
|
|
|
```bash
|
|
# In debug or production mode (RSX_MODE=debug or production)
|
|
php artisan migrate
|
|
```
|
|
|
|
In debug/production mode:
|
|
- No snapshot protection (source code is read-only)
|
|
- Schema normalization still runs
|
|
- Constants and bundles NOT regenerated
|
|
|
|
Ensure migrations are thoroughly tested in development first.
|
|
|
|
---
|
|
|
|
## Validation
|
|
|
|
The migration validator automatically checks for:
|
|
- Schema builder usage
|
|
- `down()` methods (auto-removed)
|
|
- Proper SQL syntax
|
|
|
|
Violations show clear error messages with remediation advice.
|
|
|
|
---
|
|
|
|
## Troubleshooting
|
|
|
|
| Error | Solution |
|
|
|-------|----------|
|
|
| "Found forbidden Schema builder usage" | Replace with `DB::statement()` |
|
|
| "Validation failed" | Check migration for prohibited patterns |
|
|
| Foreign key constraint fails | Ensure column types match exactly |
|
|
|
|
## More Information
|
|
|
|
Details: `php artisan rsx:man migrations`
|