Internal Model Representation
Internal Model Representation
As the CLI tool for making, squashing, merging, applying and reverting migrations is only written once because it is able to utilize our declarative migration format, for making migrations, it is required to include a step in your building pipeline to generate intermediate json files that represent the current model state.
The resulting JSON should live in the root of your project
directory. The cli tools assumes the JSON file has the name
.models.json.
Intermediate JSON representation
This is an example of the intermediate representation:
{
"Models": [
{
"Name": "foo",
"SourceDefinedAt": {
"File": "/path/to/source/file.rs",
"Line": 140,
"Column": 1
},
"Fields": [
{
"Name": "foo",
"Type": "varchar",
"SourceDefinedAt": {
"File": "/path/to/source/file.rs",
"Line": 142,
"Column": 4
},
"Annotations": [
{
"Type": "primary_key"
},
{
"Type": "not_null"
},
{
"Type": "index"
},
{
"Type": "max_length",
"Value": 255,
"Column": 4
}
]
}
]
}
]
}
Explanation
Models
The Name of a model should be already in the correct table name format.
This is enforced by the linter.
SourceDefinedAt is an optional object that specifies the file the
model originates from as well as the line number of the start of the
model definition. If the key SourceDefinedAt is found, File and Line
must be there as well.
Fields is an array of the model fields. See Fields
{
"Name": "table_name",
"SourceDefinedAt": {
"File": "/path/to/source/file.rs",
"Line": 140,
"Column": 1
},
"Fields": []
}
Fields
Fields represent a column in the database.
Name must be in the correct column name format. For further
information, see linter.
Type must be one of the allowed database types.
SourceDefinedAt is an optional object that specifies the file the
field originates from as well as the line number of the start of the
field definition. If the key SourceDefinedAt is found, File and Line
must be there as well.
Annotation is an array of possible annotations.
{
"Name": "foo",
"Type": "varchar",
"SourceDefinedAt": {
"File": "/path/to/source/file.rs",
"Line": 142,
"Column": 4
},
"Annotations": []
}
Annotations
Annotations must always have a key named Type with a possible
annotation type.
Depending on the type, it may be required to add a Value key.
The type of Value is depending on the annotation type.
E.g. max_length is using a value of type integer.
choices on the other hand uses a value of type array of strings.
Annotation types
| Annotation name | Value required | Value type |
|---|---|---|
auto_create_time |
||
auto_update_time |
||
autoincrement |
||
choices |
array of strings | |
default |
See default | |
index |
depends | See index |
max_length |
integer | |
not_null |
||
primary_key |
||
unique |
default
One of [string, number, bool]. Default types for varbinary should be encoded using hex strings.
Index
If index is used without a value, a new index is created on the column.
If a composite index is desired, the Name and Priority fields are required:
The Name attribute is only used to determine which indexes should be
considered as composite by checking if the Name is used more than once
in the same model.
The Priority attribute is used to determine the order in which the fields
are placed when creating the index. This can have an impact on performance.
The lower the number, the more important is the field. More significant fields
get placed first at index creation.
If two fields have the same priority, the order in the Fields array is used
to determine the order in the index. The order of the Fields array should
map in the best case to the order of placement in the source code.
Database types
| Type name | Additional notes |
|---|---|
varchar |
max_length annotation is required |
binary |
|
int16 |
|
int32 |
|
int64 |
|
float_number |
|
double_number |
|
boolean |
|
date |
|
datetime |
|
timestamp |
|
time |
|
choices |
choices annotation is required |