docs/01-usage.markdown @ f7ad73357ed9 default tip
Add some documentation
| author | Steve Losh <steve@stevelosh.com> |
|---|---|
| date | Thu, 11 Apr 2024 08:39:29 -0400 |
| parents | 6b27e5b734d8 |
| children | (none) |
Usage ===== DBvolve is a lightweight library for evolving a database schema over time. It might be called a "database migration library" except that "migrations" are round-trip, and DBvolve intentionally does not support backwards migrations. [TOC] ## Overview DBvolve is a relatively light-weight schema update mechanism for SQL databases. Updates ("evolutions") are raw SQL files stored in a single directory with a particular naming scheme, e.g.: evolutions/ 000-initial-tables.sql 001-add-products-table.sql 002-insert-more-product-types.sql 003-merge-name-fields.sql When run, DBvolve will ensure that a table called `dbvolve` exists in your database to track which evolutions have been applied. This table will be locked before running any evolutions to ensure that multiple clients can attempt to run evolutions at the same time, e.g. when restarting a web server. DBvolve will compare the list of already-run evolutions from the `dbvolve` table to the evolution files found in the directory and run any with a higher ID than the last currently-applied evolution. A transaction will be used when running these evolutions. If any evolutions fail to apply, the transaction will be rolled back. Note that this is *one* transaction for *all* pending evolutions, so if you have three evolutions to run and the second evolution fails, *none* of the three will be applied. You must not begin, commit, or rollback transactions in your evolutions. This is not checked. There is intentionally no support for backwards evolutions. If you need to undo something, write a new evolution and roll forward. ## Installation/Loading The core `dbvolve` system contains only the main API. You will also need to load a second `dbvolve/…` system that adds support for your particular database client. Currently the following database clients are supported: * `dbvolve/postmodern` * `dbvolve/sqlite` So if you want to e.g. use DBvolve to run schema evolutions against a Postgres database, your project's `.asd` might look something like this: :depends-on (… :dbvolve :dbvolve/postmodern) ## Evolution Files All schema evolutions must be kept in a single directory. Any files ending in `sql` or `dbvolve` (reserved for future use) will be considered to be evolutions, and must have names of the form `<integer>-<name>.sql`, e.g.: evolutions/ 000-initial-tables.sql 001-add-products-table.sql 002-insert-more-product-types.sql 003-merge-name-fields.sql Evolution IDs must start from 0 and there must be no gaps or duplicates (DBvolve will verify this before running). ## API The main API is the `dbvolve:evolve` function, which takes a database client object and a path to an evolutions directory: (defvar *db* (sqlite:connect "db.sqlite")) (dbvolve:evolve *db* "path/to/evolutions/") `evolve` is a generic function that will dispatch to the appropriate method based on the class of the database client object it receives — you must ensure that the appropriate DBvolve client support system (e.g. `dbvolve/sqlite`) has been loaded in advance. This single function is pretty much the extent of the API. How you want to use it is up to you. One way might be to write a little wrapper script to invoke it manually when you need to. Or if you're writing a web application server, you could have the server run `evolve` every time it starts up — the table locking will ensure that servers will see a consistent database state even if you restart many of them at the same time. ## New Clients If you want to add support for another database client, look at the code in `src/postmodern.lisp` and `src/sqlite.lisp` to get an idea of what you need to do. If it's a relatively common database client that others might find useful please consider sending a pull request.