Commit c50b411
fix: ensure schema exists before migrate and cleanAndMigrate (#3)
* fix: ensure schema exists before migrate and cleanAndMigrate
Migrator.cleanAndMigrate() and Migrator.migrate() failed unrecoverably
when the configured schema did not exist: isSchemaEmpty conflated
"schema empty" with "schema missing", so cleanAndMigrate skipped the
recreate branch and migrate() then issued an unqualified CREATE TYPE
that Postgres rejected with "no schema has been selected to create in".
Establish the invariant that the configured schema must exist before
any entry point runs. A new autoCreateSchema: Boolean = true
constructor flag drives CREATE SCHEMA IF NOT EXISTS at the start of
migrate() and cleanAndMigrate(); set to false for least-privilege
roles lacking the CREATE privilege.
A secondary 5-arg constructor preserves binary compatibility with the
0.1.0 signature for Java callers, pre-compiled binaries, and reflective
callers using the old arity. Reflection in NomadPlugin now selects the
primary constructor by maximum arity so it remains deterministic with
both constructors present.
The sbt plugin gains nomadSchema (default "public") and
nomadAutoCreateSchema (default true) settings, achieving parity with
the library constructor instead of hard-coding values.
Scripted test coverage extended on H2 and Postgres: Test 7 asserts the
exact PG error surfaces when the opt-out is used (pinning the original
bug symptom), and a canonical Test 9 replays the verbatim repro from
the bug report (DROP SCHEMA public CASCADE then cleanAndMigrate) plus
a second invocation proving the fix is idempotent against the
self-perpetuating nature of the original failure.
* test: share NixOS-aware Postgres bootstrap between both EmbeddedPostgres instances
Test 9 was started with a bare EmbeddedPostgres.start(), bypassing the
NOMAD_PG_TARBALL resolver applied to the first instance. On NixOS, the
fallback to zonky's bundled generic-Linux binaries failed with the
dynamic-linker error from stub-ld. Extract the bootstrap into
startEmbeddedPostgres() and route both instances through it.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix: probe schema existence before CREATE SCHEMA in autoCreateSchema path
Postgres checks ACL_CREATE on the database before IF NOT EXISTS short-
circuits in CREATE SCHEMA, so the previous unconditional CREATE SCHEMA
IF NOT EXISTS regressed least-privilege roles holding USAGE on a pre-
existing schema but lacking CREATE on the database — for these callers,
the 0.1.0 path that simply migrated against an existing schema would
fail under 0.1.1 with a permission error even when no creation is
actually needed.
Probe via information_schema.schemata (readable by PUBLIC, no privilege
required) and only issue CREATE SCHEMA on the missing-schema path. The
no-op case for an already-existing schema now costs a single SELECT
against a system view and demands no extra privilege, restoring the
0.1.0 privilege model for the common case while keeping the self-heal
behavior intact when the schema is genuinely absent.
Add Test 10 in clean-and-migrate-postgres exercising the regression
directly: a freshly created role with USAGE+CREATE on a pre-existing
schema and no CREATE on the database successfully runs migrate() with
the default autoCreateSchema=true.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix: absorb concurrent-bootstrap race in ensureSchemaExists with IF NOT EXISTS
The probe-then-create sequence is TOCTOU-racy on cold start of a fresh
database from horizontally scaled apps: two processes can both observe
the schema as missing via the probe, then race the CREATE, and the
loser fails with 'schema already exists'.
Restore IF NOT EXISTS on the create branch only. The probe still filters
out the existing-schema case, so least-privilege roles with USAGE on a
pre-existing schema remain unaffected — the ACL_CREATE check IF NOT
EXISTS triggers is only reached when the schema was actually missing
at probe time, where forward progress already demands CREATE on the
database.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: ericksosan <erickdev03@gmail.com>
Co-authored-by: Angel Blanco <novamage@magaran.com>
Co-authored-by: Angel Blanco <angel.softworks@gmail.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>1 parent 60d39d6 commit c50b411
5 files changed
Lines changed: 300 additions & 12 deletions
File tree
- core/src/main/scala/nomad
- sbt-plugin/src
- main/scala/nomad/sbt
- sbt-test/nomad
- clean-and-migrate-postgres/src/main/scala
- clean-and-migrate/src/main/scala
- migrate-custom-schema/src/main/scala
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
19 | 19 | | |
20 | 20 | | |
21 | 21 | | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
22 | 31 | | |
23 | 32 | | |
24 | 33 | | |
25 | 34 | | |
26 | 35 | | |
27 | 36 | | |
28 | | - | |
| 37 | + | |
| 38 | + | |
29 | 39 | | |
30 | 40 | | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
31 | 52 | | |
32 | 53 | | |
33 | 54 | | |
| |||
68 | 89 | | |
69 | 90 | | |
70 | 91 | | |
| 92 | + | |
71 | 93 | | |
72 | 94 | | |
73 | 95 | | |
| |||
187 | 209 | | |
188 | 210 | | |
189 | 211 | | |
| 212 | + | |
190 | 213 | | |
191 | 214 | | |
192 | 215 | | |
| |||
524 | 547 | | |
525 | 548 | | |
526 | 549 | | |
| 550 | + | |
| 551 | + | |
| 552 | + | |
| 553 | + | |
| 554 | + | |
| 555 | + | |
| 556 | + | |
| 557 | + | |
| 558 | + | |
| 559 | + | |
| 560 | + | |
| 561 | + | |
| 562 | + | |
| 563 | + | |
| 564 | + | |
| 565 | + | |
| 566 | + | |
| 567 | + | |
| 568 | + | |
| 569 | + | |
| 570 | + | |
| 571 | + | |
| 572 | + | |
| 573 | + | |
| 574 | + | |
| 575 | + | |
| 576 | + | |
| 577 | + | |
| 578 | + | |
| 579 | + | |
| 580 | + | |
| 581 | + | |
| 582 | + | |
| 583 | + | |
| 584 | + | |
527 | 585 | | |
528 | 586 | | |
529 | 587 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
293 | 293 | | |
294 | 294 | | |
295 | 295 | | |
| 296 | + | |
| 297 | + | |
296 | 298 | | |
297 | 299 | | |
298 | 300 | | |
| |||
306 | 308 | | |
307 | 309 | | |
308 | 310 | | |
| 311 | + | |
| 312 | + | |
309 | 313 | | |
310 | 314 | | |
311 | 315 | | |
| |||
330 | 334 | | |
331 | 335 | | |
332 | 336 | | |
| 337 | + | |
| 338 | + | |
333 | 339 | | |
334 | 340 | | |
335 | 341 | | |
| |||
348 | 354 | | |
349 | 355 | | |
350 | 356 | | |
351 | | - | |
352 | | - | |
| 357 | + | |
| 358 | + | |
353 | 359 | | |
354 | 360 | | |
355 | 361 | | |
| |||
370 | 376 | | |
371 | 377 | | |
372 | 378 | | |
| 379 | + | |
| 380 | + | |
373 | 381 | | |
374 | 382 | | |
375 | 383 | | |
| |||
388 | 396 | | |
389 | 397 | | |
390 | 398 | | |
391 | | - | |
392 | | - | |
| 399 | + | |
| 400 | + | |
393 | 401 | | |
394 | 402 | | |
395 | 403 | | |
| |||
450 | 458 | | |
451 | 459 | | |
452 | 460 | | |
| 461 | + | |
| 462 | + | |
453 | 463 | | |
454 | 464 | | |
455 | 465 | | |
| |||
539 | 549 | | |
540 | 550 | | |
541 | 551 | | |
542 | | - | |
543 | | - | |
| 552 | + | |
| 553 | + | |
544 | 554 | | |
545 | 555 | | |
546 | 556 | | |
| |||
Lines changed: 152 additions & 5 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
5 | | - | |
6 | | - | |
7 | | - | |
8 | | - | |
9 | | - | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
| |||
18 | 18 | | |
19 | 19 | | |
20 | 20 | | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
21 | 24 | | |
22 | 25 | | |
23 | 26 | | |
| |||
151 | 154 | | |
152 | 155 | | |
153 | 156 | | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
154 | 301 | | |
155 | 302 | | |
156 | 303 | | |
| |||
Lines changed: 36 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
110 | 110 | | |
111 | 111 | | |
112 | 112 | | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
113 | 149 | | |
114 | 150 | | |
115 | 151 | | |
0 commit comments