Database
Fizz#
Fizz is a common DSL for migrating databases. It tries to be as database-agnostic as possible. This is the default language used by Pop to define database migrations.
Create a Table#
create_table("users") {
t.Column("email", "string", {})
t.Column("twitter_handle", "string", {"size": 50})
t.Column("age", "integer", {"default": 0})
t.Column("admin", "bool", {"default": false})
t.Column("company_id", "uuid", {"default_raw": "uuid_generate_v1()"})
t.Column("bio", "text", {"null": true})
t.Column("joined_at", "timestamp", {})
}
create_table("todos") {
t.Column("user_id", "integer", {})
t.Column("title", "string", {"size": 100})
t.Column("details", "text", {"null": true})
t.ForeignKey("user_id", {"users": ["id"]}, {"on_delete": "cascade"})
}
The id
column doesn’t have to be an integer. For instance, you can use an UUID
type instead:
create_table("users") {
t.Column("id", "uuid", {primary: true})
// ...
}
By default, fizz will generate two timestamp
columns: created_at
and updated_at
.
The t.Column
method takes the following arguments: name of the column, the type of the field, and finally the last argument is any options you want to set on that column.
“Common” Types:#
string
text
timestamp
,time
,datetime
integer
bool
uuid
Any other type passed will be passed straight through to the underlying database.
For example for PostgreSQL you could pass jsonb
and it will be supported, however, SQLite will yell very loudly at you if you do the same thing!
Supported Options:#
primary
- Whether the column is the primary key. To have a composite key look below.example: {"primary": true}
size
- The size of the column. For example if you wanted avarchar(50)
in Postgres you would do:t.Column("column_name", "string", {"size": 50})
. The default value for a string column is 255 (or 191 for MariaDB).scale
,precision
- The scale and the precision for a float column.example: {"scale": 4, "precision": 2}
null
- By default columns are not allowed to benull
.default
- The default value you want for this column. By default this isnull
.default_raw
- The default value defined as a database function.after
- (MySQL Only) Add a column after another column in the table.example: {"after":"created_at"}
first
- (MySQL Only) Add a column to the first position in the table.example: {"first": true}
Disable Auto Timestamps#
create_table("users") {
t.Column("id", "uuid", {primary: true})
// ...
// Disable auto-creation of created_at and updated_at columns
t.DisableTimestamps()
}
or
create_table("users", {timestamps: false}) {
t.Column("id", "uuid", {primary: true})
// ...
}
Drop a Table#
drop_table("table_name")
Rename a Table#
rename_table("old_table_name", "new_table_name")
Add a Column#
add_column("table_name", "column_name", "string", {})
See above for more details on column types and options.
Alter a column#
change_column("table_name", "column_name", "string", {})
Rename a Column#
rename_column("table_name", "old_column_name", "new_column_name")
Drop a Column#
drop_column("table_name", "column_name")
Composite Primary Keys#
t.PrimaryKey("column_1", "column_2")
Please note that the t.PrimaryKey
statement MUST be after the columns definitions.
Add an Index#
Supported Options:#
name
- This defaults totable_name_column_name_idx
unique
Simple Index:#
add_index("table_name", "column_name", {})
Multi-Column Index:#
add_index("table_name", ["column_1", "column_2"], {})
Unique Index:#
add_index("table_name", "column_name", {"unique": true})
Index Names:#
add_index("table_name", "column_name", {}) # name => table_name_column_name_idx
add_index("table_name", "column_name", {"name": "custom_index_name"})
Rename an Index#
rename_index("table_name", "old_index_name", "new_index_name")
Drop an Index#
drop_index("table_name", "index_name")
Add a Foreign Key#
add_foreign_key("table_name", "field", {"ref_table_name": ["ref_column"]}, {
"name": "optional_fk_name",
"on_delete": "action",
"on_update": "action",
})
Supported Options#
name
- This defaults totable_name_ref_table_name_ref_column_name_fk
on_delete
-CASCADE
,SET NULL
, …on_update
Note: on_update
and on_delete
are not supported on CockroachDB yet.
Drop a Foreign Key#
drop_foreign_key("table_name", "fk_name", {"if_exists": true})
Supported Options#
if_exists
- AddsIF EXISTS
condition
Raw SQL#
sql("select * from users;")
Execute an External Command#
Sometimes during a migration you need to shell out to an external command.
exec("echo hello")