You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CHANGELOG.md
+8Lines changed: 8 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -7,6 +7,7 @@ GRDB adheres to [Semantic Versioning](https://semver.org/), with one exception:
7
7
8
8
#### 7.x Releases
9
9
10
+
- `7.4.x` Releases - [7.4.0](#740)
10
11
- `7.3.x` Releases - [7.3.0](#730)
11
12
- `7.2.x` Releases - [7.2.0](#720)
12
13
- `7.1.x` Releases - [7.1.0](#710)
@@ -135,6 +136,13 @@ GRDB adheres to [Semantic Versioning](https://semver.org/), with one exception:
135
136
136
137
---
137
138
139
+
## 7.4.0
140
+
141
+
Released March 22, 2025
142
+
143
+
- **New**: Add the MIN and MAX multi-argument SQL functions to the query interface by [@groue](https://github.com/groue) in [#1745](https://github.com/groue/GRDB.swift/pull/1745)
144
+
- **Fixed**: Transaction observers are not impacted by Task Cancellation by [@groue](https://github.com/groue) in [#1747](https://github.com/groue/GRDB.swift/pull/1747). This fixes unexpected `ValueObservation` failures in applications that perform asynchronous writes.
Copy file name to clipboardExpand all lines: GRDB/Documentation.docc/Migrations.md
+47-7Lines changed: 47 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -94,6 +94,26 @@ migrator.registerMigration("Create authors") { db in
94
94
}
95
95
```
96
96
97
+
#### How to Rename a Foreign Key
98
+
99
+
When a migration **renames a foreign key**, make sure the migration runs with `.immediate` foreign key checks, in order to avoid database integrity problems:
100
+
101
+
```swift
102
+
// IMPORTANT: rename foreign keys with immediate foreign key checks.
103
+
migrator.registerMigration("Guilds", foreignKeyChecks: .immediate) { db in
104
+
try db.rename(table: "team", to: "guild")
105
+
106
+
try db.alter(table: "player") { t in
107
+
// Rename a foreign key
108
+
t.rename(column: "teamId", to: "guildId")
109
+
}
110
+
}
111
+
```
112
+
113
+
Note: migrations that run with `.immediate` foreign key checks can not be used to recreated database tables, as described below. When needed, define two migrations instead of one.
114
+
115
+
#### How to Recreate a Database Table
116
+
97
117
When you need to modify a table in a way that is not directly supported by SQLite, or not available on your target operating system, you will need to recreate the database table.
98
118
99
119
For example:
@@ -113,19 +133,39 @@ migrator.registerMigration("Add NOT NULL check on author.name") { db in
113
133
114
134
The detailed sequence of operations for recreating a database table from a migration is:
115
135
116
-
1. When relevant, remember the format of all indexes, triggers, and views associated with table X. This information will be needed in steps 6 and 7 below. One way to do this is to run a query like the following: `SELECT type, sql FROM sqlite_schema WHERE tbl_name='X'`.
136
+
1. When relevant, remember the format of all indexes, triggers, and views associated with table `X`. This information will be needed in steps 6 below. One way to do this is to run the following statement and examine the output in the console:
117
137
118
-
2. Use `CREATE TABLE` to construct a new table "new_X" that is in the desired revised format of table X. Make sure that the name "new_X" does not collide with any existing table name, of course.
138
+
```swift
139
+
try db.dumpSQL("SELECT type, sql FROM sqlite_schema WHERE tbl_name='X'")
140
+
```
119
141
120
-
3. Transfer content from X into new_X using a statement like: `INSERT INTO new_X SELECT ... FROM X`.
142
+
2. Construct a new table `new_X` that isin the desired revised format of table `X`. Make sure that the name `new_X` does not collide with any existing table name, of course.
121
143
122
-
4. Drop the old table X: `DROP TABLE X`.
144
+
```swift
145
+
try db.create(table: "new_X") { t in... }
146
+
```
147
+
148
+
3. Transfer content from `X` into `new_X` using a statement like:
149
+
150
+
```swift
151
+
try db.execute(sql: "INSERT INTO new_X SELECT ... FROM X")
152
+
```
153
+
154
+
4. Drop the old table `X`:
155
+
156
+
```swift
157
+
try db.drop(table: "X")
158
+
```
123
159
124
-
5. Change the name of new_X to X using: `ALTER TABLE new_X RENAME TO X`.
160
+
5. Change the name of `new_X` to `X` using:
161
+
162
+
```swift
163
+
try db.rename(table: "new_X", to: "X")
164
+
```
125
165
126
-
6. When relevant, use `CREATE INDEX`, `CREATE TRIGGER`, and `CREATE VIEW` to reconstruct indexes, triggers, and views associated with table X. Perhaps use the old format of the triggers, indexes, and views saved from step 3 above as a guide, making changes as appropriate for the alteration.
166
+
6. When relevant, reconstruct indexes, triggers, and views associated with table `X`.
127
167
128
-
7. If any views refer to table X in a way that is affected by the schema change, then drop those views using `DROP VIEW` and recreate them with whatever changes are necessary to accommodate the schema change using `CREATE VIEW`.
168
+
7. If any views refer to table `X`in a way that is affected by the schema change, then drop those views using `DROP VIEW` and recreate them with whatever changes are necessary to accommodate the schema change using `CREATE VIEW`.
129
169
130
170
> Important: When recreating a table, be sure to follow the above procedure exactly, in the given order, or you might corrupt triggers, views, and foreign key constraints.
0 commit comments