{"id":15308104,"url":"https://github.com/danielmorell/sqlxm","last_synced_at":"2026-05-04T03:34:53.256Z","repository":{"id":57648035,"uuid":"399788627","full_name":"danielmorell/sqlxm","owner":"danielmorell","description":"A simple Go database migration runner for sqlx.","archived":false,"fork":false,"pushed_at":"2022-01-03T13:55:35.000Z","size":83,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-27T14:47:05.683Z","etag":null,"topics":["database","go","migrations","sqlx"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/danielmorell.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-08-25T11:08:07.000Z","updated_at":"2022-05-25T20:26:48.000Z","dependencies_parsed_at":"2022-08-25T08:22:44.457Z","dependency_job_id":null,"html_url":"https://github.com/danielmorell/sqlxm","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/danielmorell/sqlxm","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danielmorell%2Fsqlxm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danielmorell%2Fsqlxm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danielmorell%2Fsqlxm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danielmorell%2Fsqlxm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/danielmorell","download_url":"https://codeload.github.com/danielmorell/sqlxm/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danielmorell%2Fsqlxm/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32593944,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-03T22:12:39.696Z","status":"online","status_checked_at":"2026-05-04T02:00:06.625Z","response_time":58,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["database","go","migrations","sqlx"],"created_at":"2024-10-01T08:13:57.039Z","updated_at":"2026-05-04T03:34:53.222Z","avatar_url":"https://github.com/danielmorell.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# sqlx migrator (sqlxm)\n\nsqlxm runs a set of migrations against a DB. It is designed to work with the popular \n[sqlx](https://github.com/jmoiron/sqlx) package by Jason Moiron.\n\n## Features\n\n**Idempotent** One of the critical things required in DB schema changes is ensuring the changes are made once. sqlxm\nwill run each migration once.\n\n**Data Migrations** Because it is common for schema changes to also require data changes, sqlxm will let you run any SQL\nquery you want. You read that right. If you can write a SQL query sqlxm can run it.\n\n**Migration Integrity** The accidental editing of SQL migration statements can introduce subtle bugs into an \napplication. To prevent this sqlxm validates the integrity of every previously run query against its current \nversion using a checksum.\n\n## Best Practices\n\n**Run on startup.** For most applications the best time to run your DB migrations is on start up.\n\n**Don't remove old migrations.** As your application ages and changes the number of migrations will grow. Since they \nonly need to be run once on your production database it may be tempting to prune some of them. However, it is \nrecommended that you keep them. This makes creating new development, testing, or staging environments reproducible,\ndeterministic and consistent with production. \n\n## Installation\n\nIt is not too complicated.\n\n```\n$ go get github.com/danielmorell/sqlxm\n```\n\n## Basic Usage\n\nThere are three basic functions that set up sqlx migrator and start running your migrations.\n\n1. `sqlxm.New()` creates a new `sqlxm.Migrator` instance that can be used to track and run migrations.\n2. `Migrator.AddMigration()` creates a new migration to run and keep track of. Migrations are run in the order they are\n   added.\n3. `Migrator.Run()` takes all the previous migrations added with `Migrator.AddMigration()` and makes sure they have been\n   applied to database or applies them.\n\n```go\npackage main\n\nimport (\n\t\"log\"\n\n\t\"github.com/danielmorell/sqlxm\"\n\t\"github.com/jmoiron/sqlx\"\n\t_ \"github.com/lib/pq\"\n)\n\nfunc main() {\n\t// Create DB connection\n\tdb, err := sqlx.Open(\"postgres\", \"user=me dbname=db sslmode=disable\")\n\tif err != nil {\n\t\tlog.Fatalln(err)\n\t}\n\tdefer db.Close()\n\n\t// Create new migrator\n\txm, err := sqlxm.New(db, \"migrations\", \"public\")\n\tif err != nil {\n\t\tlog.Fatalln(err)\n\t}\n\n\t// Add a few migrations\n\txm.AddMigration(\n\t\t// A human-readable key for the migration\n\t\t\"create_user_table\",\n\t\t// A comment to explain what the migration does\n\t\t\"Add the initial user table\",\n\t\t// The migration SQL statement\n\t\t`CREATE TABLE users (\n        \tid         SERIAL \n                CONSTRAINT users_pk PRIMARY KEY,\n\t\t\tusername   VARCHAR(64)  NOT NULL,\n\t\t\temail      VARCHAR(64)  NOT NULL,\n\t\t\tpassword   VARCHAR(128) NOT NULL);\n\t\t\n\t\tCREATE UNIQUE INDEX users_name_uindex ON users (username);`,\n\t)\n\n\txm.AddMigration(\n\t\t\"create_posts_table\",\n\t\t\"Add the initial blog posts table\",\n\t\t`CREATE TABLE posts (\n        \tid     SERIAL \n                CONSTRAINT posts_pk PRIMARY KEY,\n\t\t\tslug   VARCHAR(128)               NOT NULL,\n\t\t\tbody   TEXT                       NOT NULL,\n\t\t\tdate   TIMESTAMP    DEFAULT NOW() NOT NULL,\n            author INT\n                CONSTRAINT posts_users_id_fk\n                    REFERENCES users\n                    ON UPDATE CASCADE ON DELETE RESTRICT);\n\t\n\t\tCREATE UNIQUE INDEX posts_slug_uindex ON posts (slug);`,\n\t)\n\n\t// Run the migrator\n\tmigrationLog, err := xm.Run()\n\tif err != nil {\n\t\tlog.Fatalln(err)\n\t}\n\n\t// Log the results\n\tfor _, l := range migrationLog {\n\t\tlog.Printf(\"%v\", l)\n\t}\n}\n```\n\n## Advanced Usage / Design\n\n### Migration Hashing\n\nsqlxm creates a hash of the migration statement and arguments. This ensures that any change to the migration query\nitself or any arguments will not go unnoticed. This hash is used as a checksum to validate previously run migrations.\nThis keeps the code you used to run past migrations and the current state of your database from getting out of sync.\n\nYou may be wondering what the rational is for doing this. It would be too easy to accidentally, change a column from\nnullable to `NOT NULL` in an old migration. If a new instance of the DB was created it would have the column as not\nnullable, however, a production DB may allow `NULL` this can introduce bugs into your codebase as production may be\nreturning `NULL` when it is not expected.\n\n### Safe Mode\n\nFor the most part it is recommended that you run migrations in **safe mode**. You do this by simply calling the\n`Migrator.Run()` method. It works a bit like a compile error in Go. If there is a potential to create an error or\nunknown state sqlxm will stop the migration.\n\nsqlxm does this by checking the hash stored in the database with the hash of the migration. If the hash check fails, the\nmigration stops and a hash mismatch error is returned.\n\nIf you want to run the migrations in **unsafe mode**, you can do so by calling `Migrator.RunUnsafe()`.\n\n### Hash Repair\n\nThere are times when non-substantive changes (like indentation) may be made to a migration query. *For the most part,\nchanging migration queries is a bad idea and should be avoided.* But it is recognized that `alter table`\nand `ALTER TABLE` do the same thing but produce a different hash.\n\nIn a scenario where you need to update the hash of the migration, you can use the `Migrator.RepairHash()` method to\nupdate the hash of previous migrations.\n\n**Note:** safe mode will not prevent you from writing `DROP TABLE users` as a migration. It simply validates the\nintegrity of the migration source with the already run migration.\n\n### Backends\n\n**Pre-built backends**\n\n- MySQL - key: `mysql`\n- Postgres - key: `postgres`\n- SQLite - key: `sqlite`\n\nYou can easily write your own backend by implementing the `Backend` interface from the `sqlxm/backends` package.\n\nYou will need to register your custom backend by calling the `RegisterBackend()` function. Then you can tell your\n`Migrator` instance to use that backend by calling the `Migrator.UseBackend()` method and passing in the key for the\nbackend that you registered.\n\nNote: you cannot overwrite an existing backend. However, you can simply specify a new key.\n\nIf you use one of the common database drivers for a DBMS with a pre-build backend, sqlxm should automatically know \nwhat backend to use. This helps reduce the boilerplate needed to run migrations. However, if you are using a special \ndatabase driver you can always call `Migrator.UseBackend()` to specify the backend you want to use.\n\n## Testing\n\nBecause a database connection is required to run tests, I recommend using Docker to run the DB engines.\n\n### Setup Docker\n\n**1. Create `.env` File**\n\nCopy the `.sample.env` file to `.env` and make any needed changes to the values. This `.env` file will be read by both\nDocker and the sqlxm tests.\n\n**2. Start Docker Containers**\n\n```\n$ docker compose up -d\n```\n\n**3. Run the Tests**\n\n```\n$ go test -v\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanielmorell%2Fsqlxm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdanielmorell%2Fsqlxm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanielmorell%2Fsqlxm/lists"}