--- a/docs/01-usage.markdown Tue Apr 09 14:01:57 2024 -0400
+++ b/docs/01-usage.markdown Thu Apr 11 08:39:29 2024 -0400
@@ -6,3 +6,92 @@
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.
--- a/docs/02-reference.markdown Tue Apr 09 14:01:57 2024 -0400
+++ b/docs/02-reference.markdown Thu Apr 11 08:39:29 2024 -0400
@@ -12,3 +12,20 @@
## Package `DBVOLVE`
+### `EVOLVE` (function)
+
+ (EVOLVE DATABASE EVOLUTIONS-PATH)
+
+Run evolutions at `evolutions-path` against `database`.
+
+ `database` must be a database client object for a supported database client
+ system. Supporting systems (e.g. `dbvolve/sqlite`) must already be loaded.
+
+ Examples:
+
+ (ql:quickload '(:dbvolve :dbvolve/sqlite))
+ (defvar *db* (sqlite:connect "foo.sqlite"))
+ (evolve *db* "path/to/evolutions"))
+
+
+
--- a/docs/03-changelog.markdown Tue Apr 09 14:01:57 2024 -0400
+++ b/docs/03-changelog.markdown Thu Apr 11 08:39:29 2024 -0400
@@ -5,3 +5,6 @@
[TOC]
+## 1.0.0
+
+Initial version with sqlite and Postgres support.
--- a/src/main.lisp Tue Apr 09 14:01:57 2024 -0400
+++ b/src/main.lisp Thu Apr 11 08:39:29 2024 -0400
@@ -121,6 +121,18 @@
evolutions))
(defun evolve (database evolutions-path)
+ "Run evolutions at `evolutions-path` against `database`.
+
+ `database` must be a database client object for a supported database client
+ system. Supporting systems (e.g. `dbvolve/sqlite`) must already be loaded.
+
+ Examples:
+
+ (ql:quickload '(:dbvolve :dbvolve/sqlite))
+ (defvar *db* (sqlite:connect \"foo.sqlite\"))
+ (evolve *db* \"path/to/evolutions\"))
+
+ "
(let* ((path (uiop:parse-native-namestring evolutions-path :ensure-directory t))
(evolutions (find-evolutions path)))
(let ((n (length evolutions)))