Skip to content

Commit 89920b4

Browse files
mnoconjulitafalconduszaadriendupuis
authored
Documented try_catch (and sql: execute) in migrations (#3060)
* Added doc for try_catch and sql in migrations * Vale suggestions * Vale suggestion * Added missing code block * Review feedback * Apply suggestions from code review Co-authored-by: julitafalcondusza <117284672+julitafalcondusza@users.noreply.github.com> * Improved example and clarified migration and migratoin step usage * Removed RN enties --------- Co-authored-by: julitafalcondusza <117284672+julitafalcondusza@users.noreply.github.com> Co-authored-by: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com>
1 parent e149aef commit 89920b4

3 files changed

Lines changed: 87 additions & 0 deletions

File tree

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
-
2+
type: sql
3+
mode: execute
4+
query:
5+
-
6+
driver: mysql
7+
sql: 'INSERT INTO test_table (test_value) VALUES ("foo");'
8+
-
9+
driver: sqlite
10+
sql: 'INSERT INTO test_table (test_value) VALUES ("foo");'
11+
-
12+
driver: postgresql
13+
sql: "INSERT INTO test_table (test_value) VALUES ('foo');"
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
-
2+
type: try_catch
3+
mode: execute
4+
allowed_exceptions:
5+
- Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException
6+
stop_after_first_exception: true
7+
steps:
8+
-
9+
type: language
10+
mode: create
11+
metadata:
12+
languageCode: ger-DE
13+
name: German
14+
enabled: true

docs/content_management/data_migration/importing_data.md

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,14 @@ The following data migration step modes are available:
7474
| `user` | &#10004; | &#10004; | | | |
7575
| `user_group` | &#10004; | &#10004; | &#10004; | | |
7676

77+
Additionally, the following special migration types are available:
78+
79+
| `type` | `execute` |
80+
|------------------------|:---------:|
81+
| `repeatable` | &#10004; |
82+
| `sql` | &#10004; |
83+
| `try_catch` | &#10004; |
84+
7785
### Repeatable steps
7886

7987
You can run a set of one or more similar migration steps multiple times by using the special `repeatable` migration type.
@@ -122,6 +130,58 @@ Then, you can use `faker()` in expressions, for example:
122130

123131
This step generates field values with fake personal names.
124132

133+
### SQL migrations
134+
135+
You can execute raw SQL queries directly in migrations by using the `sql` migration type.
136+
Use it for custom database operations that don't fit into standard entity migrations, such as creating custom tables or performing bulk updates.
137+
138+
Each query requires a `driver` property that specifies which database system the query is for.
139+
The migration system automatically filters queries and executes only those matching your current database driver.
140+
141+
```yaml
142+
[[= include_file('code_samples/data_migration/examples/sql_execute.yaml') =]]
143+
```
144+
145+
The supported database drivers are:
146+
147+
- `mysql` - MySQL/MariaDB
148+
- `postgresql` - PostgreSQL
149+
- `sqlite` - SQLite
150+
151+
You can define queries for multiple database drivers in a single migration step.
152+
The system executes only the queries that match your configured database platform.
153+
If no matching queries are found, the migration throws an error.
154+
155+
!!! caution
156+
157+
SQL migrations bypass the content model abstraction layer and directly modify the database.
158+
Use them with caution and ensure your queries are compatible with your target database system.
159+
160+
### Error handling with try-catch
161+
162+
You can wrap one or more migration steps with a `try_catch` step to handle exceptions gracefully.
163+
164+
Use it for migration steps that may fail under specific conditions but should not halt the entire migration process.
165+
166+
For example, you can ensure a language creation migration step succeeds even if the language already exists.
167+
If the migration step fails for this reason, the exception is suppressed, allowing the remaining migrations to proceed without interruption.
168+
169+
A `try_catch` migration requires the `steps` property and accepts optional `allowed_exceptions` and `stop_after_first_exception` settings.
170+
171+
Default values are:
172+
173+
- `allowed_exceptions`: empty list
174+
- `stop_after_first_exception`: `true`
175+
176+
```yaml
177+
[[= include_file('code_samples/data_migration/examples/try_catch_step.yaml') =]]
178+
```
179+
180+
When an exception is thrown within a `try_catch` step, it's compared against the list of `allowed_exceptions`.
181+
If the exception matches, it's caught and the migration step continues or stops depending on the `stop_after_first_exception` configuration setting.
182+
The migration step is marked as successful and the migration process continues.
183+
Non-matching exceptions throw immediately, halting the migration process and returning an error.
184+
125185
### Expression syntax
126186

127187
You can use [Symfony expression syntax]([[= symfony_doc =]]/reference/formats/expression_language.html) in data migrations, like in [repeatable steps](#repeatable-steps), where you can use it to generate varied content in migration steps.

0 commit comments

Comments
 (0)