Skip to content

Commit f69edb4

Browse files
committed
Split about into separate subtopics for migrations and seeds.
1 parent 7f81cba commit f69edb4

4 files changed

Lines changed: 317 additions & 253 deletions

File tree

PSql.Deploy/en-US/PSql.Deploy.dll-help.xml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,9 @@
220220
</command:returnValues>
221221

222222
<maml:relatedLinks>
223+
<maml:navigationLink>
224+
<maml:linkText>Get-Help about_PSql_Deploy_Migrations</maml:linkText>
225+
</maml:navigationLink>
223226
<maml:navigationLink>
224227
<maml:linkText>Get-Help about_PSql_Deploy</maml:linkText>
225228
</maml:navigationLink>
@@ -548,6 +551,9 @@
548551
</command:returnValues>
549552

550553
<maml:relatedLinks>
554+
<maml:navigationLink>
555+
<maml:linkText>Get-Help about_PSql_Deploy_Migrations</maml:linkText>
556+
</maml:navigationLink>
551557
<maml:navigationLink>
552558
<maml:linkText>Get-Help about_PSql_Deploy</maml:linkText>
553559
</maml:navigationLink>
@@ -858,6 +864,9 @@
858864
</command:returnValues>
859865

860866
<maml:relatedLinks>
867+
<maml:navigationLink>
868+
<maml:linkText>Get-Help about_PSql_Deploy_Seeds</maml:linkText>
869+
</maml:navigationLink>
861870
<maml:navigationLink>
862871
<maml:linkText>Get-Help about_PSql_Deploy</maml:linkText>
863872
</maml:navigationLink>

PSql.Deploy/en-US/about_PSql_Deploy.help.txt

Lines changed: 0 additions & 253 deletions
Original file line numberDiff line numberDiff line change
@@ -78,256 +78,3 @@ Most PSql.Deploy cmdlets accept a -Target parameter to specify one or more
7878
target databases on which to operate.
7979

8080
TODO: Expand
81-
82-
83-
Migrations
84-
----------
85-
86-
A migration is a SQL script that evolves a target database's schema from its
87-
current version to the next version.
88-
89-
Each subdirectory of {source-directory}\Migrations containing a _Main.sql file
90-
is a migration. The name of the subdirectory is the name of the migration.
91-
The _Main.sql file is the entry point for the migration.
92-
93-
PSql.Deploy's Invoke-SqlMigrations cmdlet applies (runs) each migration exactly
94-
once per target database. After applying a migration, the cmdlet records the
95-
migration's state in a table in the target database. Future invocations of
96-
the cmdlet for the same target database will read the table and skip any
97-
migrations that have already been applied. Thus the Invoke-SqlMigrations
98-
cmdlet is idempotent: invoked multiple times against the same target database,
99-
the cmdlet applies only new migrations and does nothing to a fully-migrated
100-
database.
101-
102-
The Get-SqlMigrations cmdlet lists the migrations found in a source directory
103-
or applied to a target database.
104-
105-
When multiple migrations are present in the source directory but not yet
106-
applied to a target database, The Invoke-SqlMigrations cmdlet applies them in a
107-
specific order: from least to greatest by case-insensitive ordinal comparison
108-
of the migrations' names. It is therefore important to choose a migration
109-
naming scheme carefully to fit the development workflow of the database. See
110-
below for examples of migration naming schemes.
111-
112-
Once applied to a target database, a migration should be considered immutable.
113-
The Invoke-SqlMigrations cmdlet computes a hash of all .sql files within the
114-
migration directory and subdirectories, recursively. The cmdlet stores this
115-
hash as part of the migration state in the target database. If a subsequent
116-
invocation finds that the computed hash is different from the stored hash, the
117-
cmdlet detects that the migration has been modified after application. The
118-
cmdlet then reports a validation error and aborts without applying any
119-
migrations. To resolve the error, either revert the changes to the migration,
120-
or update the hash value stored in all target databases (not recommended).
121-
122-
Migrations named _Begin and _End, if present, are 'pseudo-migrations' that
123-
receive special treatment. Invoke-SqlMigrations executes _Begin before any
124-
other migrations and _End after all other migrations. Furthermore, the cmdlet
125-
does not record the state of these migrations in the target database. They
126-
execute every time the cmdlet runs against a target database and has at least
127-
one other migration to apply. _Begin is useful for connection setup tasks such
128-
as setting the transaction isolation level. _End is a good place to perform
129-
cleanup that must occur after every migration session.
130-
131-
PSql.Deploy supports 'up', or forward, migrations only. It does not support
132-
'down' migrations that would revert the database to some prior schema. Many
133-
migration activities are inherently destructive -- dropping a table, for
134-
example. The work to make those activities reversible is often much more
135-
complex than the work of the activities themselves, all to enable a feature
136-
that in practice is seldom used. Thus PSql.Deploy takes the position that
137-
'down' migrations are not worth the effort. If a database schema must revert
138-
to a prior state, then author a new migration that makes the necessary changes,
139-
or restore the database from a backup. Use automated testing to find migration
140-
problems early, before they reach production.
141-
142-
Phases
143-
144-
To facilitate zero- and low-downtime deployments, PSql.Deploy splits deployment
145-
into three logical phases: Pre, Core, and Post. Each phase represents a
146-
different moment within a deployment process. Each SQL statement within a
147-
migration executes in exactly one of these phases. One migration can contain
148-
statements for multiple phases. The purposes of the phases are as follows:
149-
150-
Pre
151-
This phase occurs before deployment of the workloads that use the target
152-
database, perhaps while previously deployed workloads are still running.
153-
Migration statements in this phase should make the database compatible with
154-
the upcoming workload deployment but should retain compatibility with any
155-
existing workloads.
156-
157-
Core
158-
This phase occurs at some arbitrary point between the Pre and Post phases.
159-
PSql.Deploy interprets statements within this phase as requiring downtime,
160-
explicitly breaking a zero-downtime deployment schenario. Migration
161-
statements in this phase should make the database compatible with newly
162-
deployed workloads and need not retain compatibility with any previously
163-
deployed workloads. This phase is also suitable for deployment scenarios
164-
where downtime is not a concern.
165-
166-
Post
167-
This phase occurs after deployment of the workloads that use the target
168-
database, while those workloads are running. Migration statements in this
169-
phase should finalize or clean up after the changes made in earlier phases
170-
while retaining compatibility with the deployed workloads.
171-
172-
Dependencies
173-
174-
PSql.Deploy enables one migration to declare a dependency on another migration.
175-
The Invoke-SqlMigrations cmdlet handles a dependency in one of two ways. If
176-
the required migration has been applied fully to a target database, then the
177-
dependency is satisfied already, and the cmdlet applies the depending migration
178-
normally to that target database. If neither the required migration nor the
179-
requiring migration has been applied yet to a target database, then the cmdlet
180-
moves Pre and Post statements into the Core phase as required to satisfy the
181-
dependency and preserve the guarantees that the cmdlet makes about the order of
182-
migration statements. Note that this makes dependency resolution incompatible
183-
with zero-downtime deployment scenarios, because Core entails downtime.
184-
185-
Ordering Guarantees
186-
187-
The Invoke-SqlMigrations cmdlet makes the following guarantees about the order
188-
of migration statement execution:
189-
190-
- A migration's Pre-phase statements are guaranteed to execute after all
191-
previous migrations' Pre-phase statements.
192-
193-
- A migration's Core-phase statements are guaranteed to execute after all
194-
previous migrations' Core-phase statements.
195-
196-
- A migration's Post-phase statements are guaranteed to execute after all
197-
previous migrations' Post-phase statements.
198-
199-
- If migration B depends on migration A, then A's Post-phase statements are
200-
guaranteed to execute before B's Pre-phase statements.
201-
202-
Example 1: No dependencies
203-
204-
These migrations:
205-
1 │ Pre Core Post
206-
2 │ Pre Core Post
207-
3 │ Pre Core Post
208-
4 │ Pre Core Post
209-
5 │ Pre Core Post
210-
211-
Yield this order operations:
212-
│ Pre │ Core │ Post │
213-
══╪════════════════════╪══════════════════════════╪══════════════════════════╡
214-
1 │ Pre │ Core │ Post │
215-
2 │ Pre │ Core │ Post │
216-
3 │ Pre │ Core │ Post │
217-
4 │ Pre │ Core │ Post │
218-
5 │ Pre │ Core │ Post │
219-
Time──>
220-
221-
Example 2: One dependency
222-
223-
These migrations:
224-
1 │ Pre Core Post
225-
2 │ Pre Core Post <──╮
226-
3 │ Pre Core Post │
227-
4 │ Pre Core Post ───╯ Migration 4 depends on Migration 2
228-
5 │ Pre Core Post
229-
230-
Yield this order operations:
231-
│ Pre │ Core │ Post │
232-
══╪═════════════╪════════════════════════════════════════════╪════════════════╡
233-
1 │ Pre │ Core Post │ │
234-
2 │ Pre │ Core ^^^^ Post │ │
235-
3 │ Pre │ Core ^^^^ │ Post │
236-
4 │ │ Pre Core │ Post │
237-
5 │ │ ^^^ Pre Core │ Post │
238-
Time──> ^^^
239-
240-
Magic Comments
241-
242-
A migration may contain 'magic comments', which are special comments that the
243-
Invoke-SqlMigrations cmdlet interprets as directives. The cmdlet supports the
244-
following magic comments:
245-
246-
--# PRE
247-
Causes subsequent SQL text to execute in the Pre phase.
248-
249-
--# CORE
250-
Causes subsequent SQL text to execute in the Core phase.
251-
252-
--# POST
253-
Causes subsequent SQL text to execute in the Post phase.
254-
255-
--# REQUIRES: <migration-name> ...
256-
Declares a dependency on one or more migrations.
257-
258-
Example Migration Naming Schemes
259-
260-
Here are some example migration naming schemes:
261-
262-
- Numeric, zero-padded: 0001, 0002, 0003, ...
263-
Pros: simple
264-
Cons: requires coordination if multiple people author migrations
265-
concurrently; requires new scheme if next number exceeds planned width
266-
Best for: solo projects or teams with a single migration author where the
267-
versioning scheme is unknown or subject to change
268-
269-
- Version, zero-padded: v01.00.00, v01.00.01, v01.01.00, v02.00.00, ...
270-
Pros: descriptive; aligned with versioning
271-
Cons: requires coordination if multiple people author migrations
272-
concurrently; tricky if a version number exceeds planned width
273-
Best for: solo projects or teams with a single migration author where the
274-
versioning scheme is known and unlikely to change
275-
276-
- Date and description: 2025-08-15-Initial, 2025-08-18-AddUsersTable, ...
277-
Pros: descriptive; requires less coordination for multiple authors
278-
Cons: need to keep migration name up-to-date during authoring
279-
Best for: teams with multiple migration authors
280-
281-
- Date and work item number: 2025-08-15-00042, 2025-08-18-00123, ...
282-
Pros: requires less coordination for multiple authors
283-
Cons: need to keep migration name up-to-date during authoring; requires
284-
knowing work item numbers
285-
Best for: teams with multiple migration authors where it is useful to
286-
associate migrations with work items, pull requests, etc.
287-
288-
Squashes
289-
290-
A long-lived project with frequent schema changes will accumulate a large
291-
number of migrations over time. For such projects, it is sometimes useful to
292-
delete old migrations and instead use a create script that creates a database
293-
already migrated to that poitn in time. This is known as a 'squash'. Create
294-
scripts are outside the scope of PSql.Deploy, but PSql.Deploy supports squashes
295-
by not caring about completed migrations that are no longer present in the
296-
source directory. Nevertheless, there are two rules that must be oserved when
297-
performing a squash:
298-
299-
1. The oldest unsquashed migration must be same age or older than the oldest
300-
backup that is likely to be restored.
301-
302-
1. The oldest unsquashed migration must be same age or older than the create
303-
script.
304-
305-
TODO: Describe this better when more brain cells are available.
306-
307-
308-
Seeds
309-
-----
310-
311-
A seed is a SQL script that populates a target database with data.
312-
313-
Each subdirectory of {source-directory}\Seeds containing a _Main.sql file is a
314-
seed. The name of the subdirectory is the name of the seed. The _Main.sql
315-
file is the entry point for the seed.
316-
317-
Seeds support several magic comments for organizing code into modules with dependencies:
318-
319-
--# MODULE: name [topic ...]
320-
Starts a new module with the specified name, optionally declaring provided
321-
topics.
322-
323-
--# PROVIDES: topic [topic ...]
324-
Indicates that the current module provides the specified topics.
325-
326-
--# REQUIRES: topic [topic ...]
327-
Indicates that the current module requires the specified topics.
328-
329-
--# WORKER: all|any
330-
Specifies worker execution mode. 'all' means the module executes on all
331-
workers; 'any' means it executes on any single worker.
332-
333-
TODO: Describe seeds here.

0 commit comments

Comments
 (0)