db-migrate-x 0.2.0 → 0.3.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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/context/alter-table.md +183 -0
- data/context/create-index.md +217 -0
- data/context/create-table.md +170 -0
- data/context/drop-table.md +180 -0
- data/context/getting-started.md +94 -0
- data/context/index.yaml +29 -0
- data/context/migrations.md +98 -0
- data/lib/db/migrate/alter_table.rb +154 -0
- data/lib/db/migrate/create_table.rb +1 -1
- data/lib/db/migrate/drop_index.rb +3 -1
- data/lib/db/migrate/drop_table.rb +3 -1
- data/lib/db/migrate/information_schema.rb +2 -0
- data/lib/db/migrate/migration.rb +55 -0
- data/lib/db/migrate/version.rb +1 -1
- data/readme.md +25 -1
- data/releases.md +9 -0
- data.tar.gz.sig +0 -0
- metadata +17 -13
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0e074cbb0b589d7362ae27ff450ada897cda5fe6f061fabe73f8c67cec13b16e
|
4
|
+
data.tar.gz: 75b1eb715150b5f8c7f26ccdb8b0c692c260876f4f7e110ed28546fe3bf2ba4f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b2c772821a3da23ce85e73175e8597ff6c91f087b4ddc9f11ad9369caa05853d6df705e6d6c816c66300def442a35e157a3af92543016d8179bbc95acd5c6cb5
|
7
|
+
data.tar.gz: f65162f9b2c246dcccaec045ea47f5e5bbe75b75cbc30983eb34a47c39d8b9cb7553e03708e0cfa63d0fa5862e71a502f87c5528505183a6e0bcd354ce8b8ac9
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
@@ -0,0 +1,183 @@
|
|
1
|
+
# Alter Table
|
2
|
+
|
3
|
+
This guide explains how to modify existing database tables using `db-migrate`.
|
4
|
+
|
5
|
+
## Basic Table Alterations
|
6
|
+
|
7
|
+
Use `alter_table` to modify an existing table:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
DB::Migrate.migrate("update_users_table", client) do
|
11
|
+
alter_table :users do
|
12
|
+
add_column :age, "INTEGER"
|
13
|
+
add_column :active, "BOOLEAN DEFAULT TRUE"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
```
|
17
|
+
|
18
|
+
## Adding Columns
|
19
|
+
|
20
|
+
### Basic Column Addition
|
21
|
+
|
22
|
+
```ruby
|
23
|
+
alter_table :users do
|
24
|
+
add_column :email, "TEXT"
|
25
|
+
add_column :phone, "TEXT"
|
26
|
+
end
|
27
|
+
```
|
28
|
+
|
29
|
+
### Columns with Constraints
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
alter_table :users do
|
33
|
+
add_column :email, "TEXT NOT NULL"
|
34
|
+
add_column :age, "INTEGER", default: 0
|
35
|
+
add_column :status, "TEXT", unique: true
|
36
|
+
end
|
37
|
+
```
|
38
|
+
|
39
|
+
## Dropping Columns
|
40
|
+
|
41
|
+
### Basic Column Removal
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
alter_table :users do
|
45
|
+
drop_column :old_field
|
46
|
+
drop_column :deprecated_column
|
47
|
+
end
|
48
|
+
```
|
49
|
+
|
50
|
+
### Safe Column Removal
|
51
|
+
|
52
|
+
Use `if_exists` to avoid errors if the column doesn't exist:
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
alter_table :users do
|
56
|
+
drop_column :maybe_missing_column, if_exists: true
|
57
|
+
end
|
58
|
+
```
|
59
|
+
|
60
|
+
## Renaming Columns
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
alter_table :users do
|
64
|
+
rename_column :full_name, :name
|
65
|
+
rename_column :email_address, :email
|
66
|
+
end
|
67
|
+
```
|
68
|
+
|
69
|
+
## Changing Column Types
|
70
|
+
|
71
|
+
Use `change_column` to modify a column's data type:
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
alter_table :users do
|
75
|
+
change_column :age, "INTEGER"
|
76
|
+
change_column :balance, "DECIMAL(10,2)"
|
77
|
+
end
|
78
|
+
```
|
79
|
+
|
80
|
+
### Database-Specific Behavior
|
81
|
+
|
82
|
+
The gem automatically uses the appropriate syntax for your database:
|
83
|
+
|
84
|
+
**PostgreSQL:**
|
85
|
+
```sql
|
86
|
+
ALTER TABLE users ALTER COLUMN age TYPE INTEGER USING age::INTEGER;
|
87
|
+
```
|
88
|
+
|
89
|
+
**MariaDB/MySQL:**
|
90
|
+
```sql
|
91
|
+
ALTER TABLE users MODIFY COLUMN age INTEGER;
|
92
|
+
```
|
93
|
+
|
94
|
+
## Multiple Operations
|
95
|
+
|
96
|
+
Combine multiple alterations in a single migration:
|
97
|
+
|
98
|
+
```ruby
|
99
|
+
alter_table :users do
|
100
|
+
add_column :middle_name, "TEXT"
|
101
|
+
drop_column :old_field, if_exists: true
|
102
|
+
rename_column :full_name, :name
|
103
|
+
change_column :age, "INTEGER"
|
104
|
+
end
|
105
|
+
```
|
106
|
+
|
107
|
+
## Advanced Examples
|
108
|
+
|
109
|
+
### Data Type Conversions
|
110
|
+
|
111
|
+
```ruby
|
112
|
+
# Convert text to integer with explicit casting
|
113
|
+
alter_table :products do
|
114
|
+
change_column :price_text, "DECIMAL(10,2)"
|
115
|
+
end
|
116
|
+
```
|
117
|
+
|
118
|
+
For PostgreSQL, this automatically includes a `USING` clause for safe conversion.
|
119
|
+
|
120
|
+
### Adding Columns with Complex Defaults
|
121
|
+
|
122
|
+
```ruby
|
123
|
+
alter_table :orders do
|
124
|
+
add_column :order_number, "TEXT NOT NULL",
|
125
|
+
default: "'ORD-' || EXTRACT(epoch FROM NOW())::TEXT"
|
126
|
+
end
|
127
|
+
```
|
128
|
+
|
129
|
+
### Conditional Schema Changes
|
130
|
+
|
131
|
+
```ruby
|
132
|
+
alter_table :users do
|
133
|
+
# Only add column if it doesn't exist
|
134
|
+
unless information_schema.column_exists?(:users, :created_at)
|
135
|
+
add_column :created_at, "TIMESTAMP DEFAULT NOW()"
|
136
|
+
end
|
137
|
+
end
|
138
|
+
```
|
139
|
+
|
140
|
+
## Feature Detection
|
141
|
+
|
142
|
+
The gem uses feature detection to ensure compatibility:
|
143
|
+
|
144
|
+
- **Conditional Operations**: `IF EXISTS` clauses are only used when supported
|
145
|
+
- **Column Modification**: Uses `MODIFY COLUMN` (MariaDB) vs `ALTER COLUMN TYPE` (PostgreSQL)
|
146
|
+
- **Using Clauses**: PostgreSQL's `USING` clause for safe type conversions
|
147
|
+
|
148
|
+
## Best Practices
|
149
|
+
|
150
|
+
### Safe Alterations
|
151
|
+
|
152
|
+
Always use conditional operations when uncertain:
|
153
|
+
|
154
|
+
```ruby
|
155
|
+
alter_table :users do
|
156
|
+
drop_column :deprecated_field, if_exists: true
|
157
|
+
add_column :new_field, "TEXT"
|
158
|
+
end
|
159
|
+
```
|
160
|
+
|
161
|
+
### Incremental Changes
|
162
|
+
|
163
|
+
Make small, focused changes rather than large alterations:
|
164
|
+
|
165
|
+
```ruby
|
166
|
+
# Good: Focused change
|
167
|
+
alter_table :users do
|
168
|
+
add_column :email_verified, "BOOLEAN DEFAULT FALSE"
|
169
|
+
end
|
170
|
+
|
171
|
+
# Better than: Large, complex change
|
172
|
+
alter_table :users do
|
173
|
+
add_column :email_verified, "BOOLEAN DEFAULT FALSE"
|
174
|
+
add_column :phone_verified, "BOOLEAN DEFAULT FALSE"
|
175
|
+
add_column :two_factor_enabled, "BOOLEAN DEFAULT FALSE"
|
176
|
+
drop_column :old_verification_method, if_exists: true
|
177
|
+
rename_column :verification_code, :email_verification_code
|
178
|
+
end
|
179
|
+
```
|
180
|
+
|
181
|
+
### Performance Considerations
|
182
|
+
|
183
|
+
For large tables, consider the performance impact of schema changes, especially when adding `NOT NULL` columns without defaults.
|
@@ -0,0 +1,217 @@
|
|
1
|
+
# Create Index
|
2
|
+
|
3
|
+
This guide explains how to create database indexes using `db-migrate`.
|
4
|
+
|
5
|
+
## Basic Index Creation
|
6
|
+
|
7
|
+
Use `create_index` to add indexes for better query performance:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
DB::Migrate.migrate("add_user_indexes", client) do
|
11
|
+
create_index :users, :email
|
12
|
+
create_index :users, :name
|
13
|
+
end
|
14
|
+
```
|
15
|
+
|
16
|
+
## Composite Indexes
|
17
|
+
|
18
|
+
Create indexes on multiple columns:
|
19
|
+
|
20
|
+
```ruby
|
21
|
+
DB::Migrate.migrate("add_composite_indexes", client) do
|
22
|
+
create_index :orders, [:user_id, :created_at]
|
23
|
+
create_index :user_preferences, [:user_id, :preference_key]
|
24
|
+
end
|
25
|
+
```
|
26
|
+
|
27
|
+
## Index Options
|
28
|
+
|
29
|
+
### Unique Indexes
|
30
|
+
|
31
|
+
Enforce uniqueness at the database level:
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
create_index :users, :email, unique: true
|
35
|
+
create_index :user_preferences, [:user_id, :preference_key], unique: true
|
36
|
+
```
|
37
|
+
|
38
|
+
### Named Indexes
|
39
|
+
|
40
|
+
Specify custom index names:
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
create_index :users, :email, name: "idx_users_email_unique", unique: true
|
44
|
+
create_index :orders, [:user_id, :status], name: "idx_orders_user_status"
|
45
|
+
```
|
46
|
+
|
47
|
+
### Conditional Indexes (PostgreSQL)
|
48
|
+
|
49
|
+
Create partial indexes with conditions:
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
# PostgreSQL-specific conditional index
|
53
|
+
create_index :users, :email,
|
54
|
+
name: "idx_active_users_email",
|
55
|
+
condition: "active = true"
|
56
|
+
```
|
57
|
+
|
58
|
+
## Index Types
|
59
|
+
|
60
|
+
### Standard B-tree Indexes
|
61
|
+
|
62
|
+
Default index type, good for equality and range queries:
|
63
|
+
|
64
|
+
```ruby
|
65
|
+
create_index :users, :created_at # Range queries
|
66
|
+
create_index :users, :status # Equality queries
|
67
|
+
```
|
68
|
+
|
69
|
+
### Database-Specific Index Types
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
# PostgreSQL GIN index for JSONB
|
73
|
+
create_index :documents, :metadata, type: "GIN"
|
74
|
+
|
75
|
+
# PostgreSQL GiST index for geometric data
|
76
|
+
create_index :locations, :coordinates, type: "GiST"
|
77
|
+
|
78
|
+
# Text search indexes
|
79
|
+
create_index :articles, :content, type: "GIN",
|
80
|
+
expression: "to_tsvector('english', content)"
|
81
|
+
```
|
82
|
+
|
83
|
+
## Advanced Examples
|
84
|
+
|
85
|
+
### Functional Indexes
|
86
|
+
|
87
|
+
Create indexes on expressions:
|
88
|
+
|
89
|
+
```ruby
|
90
|
+
# Index on lowercase email for case-insensitive searches
|
91
|
+
create_index :users, nil,
|
92
|
+
name: "idx_users_email_lower",
|
93
|
+
expression: "LOWER(email)"
|
94
|
+
|
95
|
+
# Index on extracted JSON field
|
96
|
+
create_index :documents, nil,
|
97
|
+
name: "idx_documents_title",
|
98
|
+
expression: "metadata->>'title'"
|
99
|
+
```
|
100
|
+
|
101
|
+
### Concurrent Index Creation (PostgreSQL)
|
102
|
+
|
103
|
+
For large tables, create indexes without blocking writes:
|
104
|
+
|
105
|
+
```ruby
|
106
|
+
# Note: This requires special handling and may not be supported
|
107
|
+
# in all migration contexts due to transaction requirements
|
108
|
+
create_index :large_table, :important_column,
|
109
|
+
algorithm: "CONCURRENTLY"
|
110
|
+
```
|
111
|
+
|
112
|
+
## Performance Considerations
|
113
|
+
|
114
|
+
### Index Strategy
|
115
|
+
|
116
|
+
Choose indexes based on your query patterns:
|
117
|
+
|
118
|
+
```ruby
|
119
|
+
# Good: Index frequently queried columns
|
120
|
+
create_index :orders, :user_id # For user's orders
|
121
|
+
create_index :orders, :created_at # For recent orders
|
122
|
+
create_index :orders, :status # For order filtering
|
123
|
+
|
124
|
+
# Composite index for common query combinations
|
125
|
+
create_index :orders, [:user_id, :status] # For user's pending orders
|
126
|
+
```
|
127
|
+
|
128
|
+
### Avoid Over-Indexing
|
129
|
+
|
130
|
+
Don't create unnecessary indexes:
|
131
|
+
|
132
|
+
```ruby
|
133
|
+
# Avoid: Too many single-column indexes
|
134
|
+
create_index :users, :first_name
|
135
|
+
create_index :users, :last_name
|
136
|
+
create_index :users, [:first_name, :last_name] # This composite covers both
|
137
|
+
|
138
|
+
# Better: Strategic composite index
|
139
|
+
create_index :users, [:last_name, :first_name] # Covers both queries
|
140
|
+
```
|
141
|
+
|
142
|
+
## Creating Indexes in Table Definitions
|
143
|
+
|
144
|
+
You can also create indexes when defining tables:
|
145
|
+
|
146
|
+
```ruby
|
147
|
+
create_table :users do
|
148
|
+
primary_key
|
149
|
+
column :email, "TEXT NOT NULL", unique: true, index: true
|
150
|
+
column :name, "TEXT", index: true
|
151
|
+
timestamps
|
152
|
+
|
153
|
+
# Composite indexes
|
154
|
+
index [:email, :created_at]
|
155
|
+
index [:name, :active], name: "idx_active_users_by_name"
|
156
|
+
end
|
157
|
+
```
|
158
|
+
|
159
|
+
## Dropping Indexes
|
160
|
+
|
161
|
+
Remove indexes when they're no longer needed:
|
162
|
+
|
163
|
+
```ruby
|
164
|
+
DB::Migrate.migrate("cleanup_unused_indexes", client) do
|
165
|
+
drop_index :idx_old_user_lookup, if_exists: true
|
166
|
+
drop_index :idx_deprecated_search, if_exists: true
|
167
|
+
end
|
168
|
+
```
|
169
|
+
|
170
|
+
## Feature Detection
|
171
|
+
|
172
|
+
The gem automatically handles database-specific index features:
|
173
|
+
|
174
|
+
- **Conditional Indexes**: Only used when supported (PostgreSQL)
|
175
|
+
- **Index Types**: Database-specific types like GIN, GiST
|
176
|
+
- **IF EXISTS**: Safe index creation/removal when supported
|
177
|
+
|
178
|
+
## Best Practices
|
179
|
+
|
180
|
+
### Index Naming Convention
|
181
|
+
|
182
|
+
Use consistent naming patterns:
|
183
|
+
|
184
|
+
```ruby
|
185
|
+
# Good: Descriptive names
|
186
|
+
create_index :users, :email, name: "idx_users_email"
|
187
|
+
create_index :orders, [:user_id, :status], name: "idx_orders_user_status"
|
188
|
+
|
189
|
+
# Pattern: idx_{table}_{columns}_{suffix}
|
190
|
+
create_index :users, :email, name: "idx_users_email_unique", unique: true
|
191
|
+
```
|
192
|
+
|
193
|
+
### Monitor Index Usage
|
194
|
+
|
195
|
+
Regularly review index effectiveness:
|
196
|
+
|
197
|
+
```sql
|
198
|
+
-- PostgreSQL: Check index usage
|
199
|
+
SELECT schemaname, tablename, indexname, idx_scan
|
200
|
+
FROM pg_stat_user_indexes
|
201
|
+
WHERE idx_scan = 0;
|
202
|
+
|
203
|
+
-- MariaDB: Check index cardinality
|
204
|
+
SHOW INDEX FROM users;
|
205
|
+
```
|
206
|
+
|
207
|
+
### Index Maintenance
|
208
|
+
|
209
|
+
Consider index maintenance in high-traffic applications:
|
210
|
+
|
211
|
+
```ruby
|
212
|
+
# For very large tables, create indexes during low-traffic periods
|
213
|
+
DB::Migrate.migrate("add_large_table_index", client) do
|
214
|
+
# Consider creating this during maintenance windows
|
215
|
+
create_index :large_transaction_table, :created_at
|
216
|
+
end
|
217
|
+
```
|
@@ -0,0 +1,170 @@
|
|
1
|
+
# Create Table
|
2
|
+
|
3
|
+
This guide explains how to create database tables using `db-migrate`.
|
4
|
+
|
5
|
+
## Basic Table Creation
|
6
|
+
|
7
|
+
Use `create_table` to define a new table:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
DB::Migrate.migrate("create_users", client) do
|
11
|
+
create_table :users do
|
12
|
+
primary_key
|
13
|
+
column :name, "TEXT NOT NULL"
|
14
|
+
column :email, "TEXT UNIQUE"
|
15
|
+
timestamps
|
16
|
+
end
|
17
|
+
end
|
18
|
+
```
|
19
|
+
|
20
|
+
## Conditional Table Creation
|
21
|
+
|
22
|
+
Use `create_table?` to create a table only if it doesn't already exist:
|
23
|
+
|
24
|
+
```ruby
|
25
|
+
DB::Migrate.migrate("safe_create_users", client) do
|
26
|
+
create_table? :users do
|
27
|
+
primary_key
|
28
|
+
column :name, "TEXT NOT NULL"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
```
|
32
|
+
|
33
|
+
## Column Definitions
|
34
|
+
|
35
|
+
### Basic Columns
|
36
|
+
|
37
|
+
Define columns with their SQL type:
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
create_table :products do
|
41
|
+
column :name, "TEXT NOT NULL"
|
42
|
+
column :price, "DECIMAL(10,2)"
|
43
|
+
column :description, "TEXT"
|
44
|
+
column :active, "BOOLEAN DEFAULT TRUE"
|
45
|
+
end
|
46
|
+
```
|
47
|
+
|
48
|
+
### Primary Keys
|
49
|
+
|
50
|
+
Add an auto-incrementing primary key:
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
create_table :users do
|
54
|
+
primary_key # Creates 'id' column
|
55
|
+
# Other columns...
|
56
|
+
end
|
57
|
+
|
58
|
+
# Custom primary key name
|
59
|
+
create_table :users do
|
60
|
+
primary_key :user_id
|
61
|
+
# Other columns...
|
62
|
+
end
|
63
|
+
```
|
64
|
+
|
65
|
+
The primary key uses database-appropriate types:
|
66
|
+
- PostgreSQL: `BIGSERIAL PRIMARY KEY`
|
67
|
+
- MariaDB/MySQL: `BIGINT AUTO_INCREMENT PRIMARY KEY`
|
68
|
+
|
69
|
+
### Timestamps
|
70
|
+
|
71
|
+
Add created_at and updated_at columns:
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
create_table :posts do
|
75
|
+
primary_key
|
76
|
+
column :title, "TEXT NOT NULL"
|
77
|
+
timestamps # Adds created_at and updated_at
|
78
|
+
end
|
79
|
+
```
|
80
|
+
|
81
|
+
## Column Options
|
82
|
+
|
83
|
+
### Constraints
|
84
|
+
|
85
|
+
```ruby
|
86
|
+
create_table :users do
|
87
|
+
primary_key
|
88
|
+
column :email, "TEXT NOT NULL", unique: true
|
89
|
+
column :age, "INTEGER", null: false
|
90
|
+
column :status, "TEXT", default: "'active'"
|
91
|
+
end
|
92
|
+
```
|
93
|
+
|
94
|
+
### Indexes
|
95
|
+
|
96
|
+
Create indexes on columns:
|
97
|
+
|
98
|
+
```ruby
|
99
|
+
create_table :users do
|
100
|
+
primary_key
|
101
|
+
column :email, "TEXT NOT NULL", unique: true, index: true
|
102
|
+
column :name, "TEXT", index: true
|
103
|
+
end
|
104
|
+
```
|
105
|
+
|
106
|
+
## Advanced Examples
|
107
|
+
|
108
|
+
### Composite Indexes
|
109
|
+
|
110
|
+
```ruby
|
111
|
+
create_table :user_preferences do
|
112
|
+
primary_key
|
113
|
+
column :user_id, "BIGINT NOT NULL"
|
114
|
+
column :preference_key, "TEXT NOT NULL"
|
115
|
+
column :preference_value, "TEXT"
|
116
|
+
|
117
|
+
# Create composite index
|
118
|
+
index [:user_id, :preference_key], unique: true
|
119
|
+
end
|
120
|
+
```
|
121
|
+
|
122
|
+
### Foreign Key References
|
123
|
+
|
124
|
+
```ruby
|
125
|
+
create_table :posts do
|
126
|
+
primary_key
|
127
|
+
column :user_id, "BIGINT NOT NULL"
|
128
|
+
column :title, "TEXT NOT NULL"
|
129
|
+
column :content, "TEXT"
|
130
|
+
timestamps
|
131
|
+
|
132
|
+
# Note: Foreign key constraints are defined separately
|
133
|
+
# This just creates the reference column
|
134
|
+
end
|
135
|
+
```
|
136
|
+
|
137
|
+
### Database-Specific Types
|
138
|
+
|
139
|
+
```ruby
|
140
|
+
create_table :analytics do
|
141
|
+
primary_key
|
142
|
+
column :event_data, "JSONB" # PostgreSQL
|
143
|
+
column :tags, "JSON" # MariaDB/MySQL
|
144
|
+
column :metadata, "TEXT" # Universal fallback
|
145
|
+
end
|
146
|
+
```
|
147
|
+
|
148
|
+
## Options
|
149
|
+
|
150
|
+
### Drop Existing Table
|
151
|
+
|
152
|
+
Replace an existing table:
|
153
|
+
|
154
|
+
```ruby
|
155
|
+
create_table :users, drop_if_exists: true do
|
156
|
+
primary_key
|
157
|
+
column :name, "TEXT NOT NULL"
|
158
|
+
end
|
159
|
+
```
|
160
|
+
|
161
|
+
### Temporary Tables
|
162
|
+
|
163
|
+
```ruby
|
164
|
+
create_table :temp_data, temporary: true do
|
165
|
+
column :id, "BIGINT"
|
166
|
+
column :data, "TEXT"
|
167
|
+
end
|
168
|
+
```
|
169
|
+
|
170
|
+
Note: Temporary table support depends on your database adapter implementation.
|