{"id":15675136,"url":"https://github.com/gsamokovarov/gloat","last_synced_at":"2025-05-06T23:43:16.559Z","repository":{"id":57486121,"uuid":"87847554","full_name":"gsamokovarov/gloat","owner":"gsamokovarov","description":"Next-gen database migrations framework for Go.","archived":false,"fork":false,"pushed_at":"2018-09-21T08:54:39.000Z","size":72,"stargazers_count":14,"open_issues_count":0,"forks_count":4,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-31T04:11:12.498Z","etag":null,"topics":["golang","migrations","sql"],"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/gsamokovarov.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-04-10T19:04:56.000Z","updated_at":"2024-03-12T06:43:09.000Z","dependencies_parsed_at":"2022-09-18T18:04:31.655Z","dependency_job_id":null,"html_url":"https://github.com/gsamokovarov/gloat","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gsamokovarov%2Fgloat","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gsamokovarov%2Fgloat/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gsamokovarov%2Fgloat/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gsamokovarov%2Fgloat/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gsamokovarov","download_url":"https://codeload.github.com/gsamokovarov/gloat/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252788388,"owners_count":21804280,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["golang","migrations","sql"],"created_at":"2024-10-03T15:57:09.828Z","updated_at":"2025-05-06T23:43:16.540Z","avatar_url":"https://github.com/gsamokovarov.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=right\u003e\n\t\u003ca href=\"https://travis-ci.org/gsamokovarov/gloat\"\u003e\n\t\t\u003cimg src=\"https://travis-ci.org/gsamokovarov/gloat.svg?branch=master\" alt=\"Build Status\" data-canonical-src=\"https://travis-ci.org/gsamokovarov/gloat.svg?branch=master\"\u003e\n\t\u003c/a\u003e\n\u003c/p\u003e\n\n# Gloat /ɡlōt/\n\n\u003e Contemplate or dwell on one's own success or another's misfortune with\n\u003e smugness or malignant pleasure.\n\nGloat is a modular SQL migration library for the Go programming language. Being\na library, gloat can be easily integrated into your application or ORM.\n\n## Library\n\nIf you are using gloat as a library, the main components you'll be dealing with\nare migration, source, store and SQL executor. You'll be using those through the\nmethods on the `Gloat` struct.\n\n```go\ndb, err := sql.Open(\"postgres\", \"connection string\")\nif err != nil {\n\t// Handle the *sql.DB creation error.\n}\n\ngl := gloat.Gloat{\n\tStore:    gloat.NewPostgreSQLStore(db),\n\tSource:   gloat.NewFileSystemSource(\"migrations\"),\n\tExecutor: gloat.NewSQLExecutor(db),\n}\n```\n\n### Migration\n\nMigration holds all the relevant information for a migration. The content of\nthe forward (up) side of a migration, the backward (down) side, a path and\nversion. The version is used to determine the order of which the migrations\nwould be executed. The path is the name in a store.\n\n```go\ntype Migration struct {\n\tUpSQL   []byte\n\tDownSQL []byte\n\tPath    string\n\tVersion int64\n}\n```\n\n### Source\n\nThe `Source` interface represents a source of migration. The most common source\nis the file system.\n\n```go\ntype Source interface {\n\tCollect() (Migrations, error)\n}\n```\n\n\n`gloat.NewFileSystemSource` is a constructor function that creates a source\nthat collects migrations from a folder with the following structure:\n\n```\nmigrations/\n└── 20170329154959_introduce_domain_model\n    ├── down.sql\n    └── up.sql\n```\n\nIn the example above `migrations` is a folder that stores all of the\nmigrations. A migrations itself is a folder with a name in the form of\n`:timestamp_:name` containing `up.sql` and `down.sql` files.\n\nThe `up.sql` file contains the SQL that's executed when a migration is applied:\n\n```sql\nCREATE TABLE users (\n    id    bigserial PRIMARY KEY NOT NULL,\n    name  character varying NOT NULL,\n    email character varying NOT NULL,\n\n    created_at  timestamp DEFAULT CURRENT_TIMESTAMP NOT NULL,\n    updated_at  timestamp DEFAULT CURRENT_TIMESTAMP NOT NULL\n);\n```\n\nWhile `down.sql` is executed when a migration is reverted:\n\n```sql\nDROP TABLE users;\n```\n\nIf the `down.sql` file is not present, we say that a migration is irreversible.\n\n## Store\n\nThe Store is an interface representing a place where the applied migrations are\nrecorded. The common thing is to store the migrations in a database table. The\n`gloat.DatabaseStore` does just that. The `gloat.NewPostgreSQLStore` constructor\nfunction creates such store that records the migration in a table called\n`schema_migrations`. The table is automatically created if it does not exist.\n\n```go\ntype Store interface {\n\tSource\n\n\tInsert(*Migration, StoreExecer) error\n\tRemove(*Migration, StoreExecer) error\n}\n```\n\nThe `Store.Insert` records the migration version in to the `schema_migrations`\ntable, while `Store.Remove` deletes the column with the version from\nthe table. There are the following builtin store constructors:\n\n```go\n// NewPostgreSQLStore creates a Store for PostgreSQL.\nfunc NewPostgreSQLStore(db *sql.DB) Store {}\n\n// NewMySQLStore creates a Store for MySQL.\nfunc NewMySQLStore(db *sql.DB) Store {}\n\n// NewSQLite3Store creates a Store for SQLite3.\nfunc NewSQLite3Store(db *sql.DB) Store {}\n```\n\n### Executor\n\nThe `Executor` interface, well, it executes the migrations. For SQL migrations,\nthere is the `gloat.SQLExecutor` implementation. It's an interface,\nnevertheless, so you can fake it out during testing.\n\n```go\ntype Executor interface {\n\tUp(*Migration, Store) error\n\tDown(*Migration, Store) error\n}\n```\n\nThe executor executes the migration `UpSQL` or `DownSQL` sections.\n\n### Gloat\n\nA `Gloat` binds a migration `Source`, `Store` and `Executor` into one thing, so\nit's easier to `Apply`, and `Revert` migrations.\n\n```go\ngl := gloat.Gloat{\n\tStore:    gloat.NewPostgreSQLStore(db),\n\tSource:   gloat.NewFileSystemSource(\"migrations\"),\n\tExecutor: gloat.NewSQLExecutor(db),\n}\n\n// Applies all of the unapplied migrations.\nif migrations, err := gl.Unapplied(); err == nil {\n\tfor _, migration := range migrations {\n\t\tgl.Apply(migration)\n\t}\n}\n\n// Revert the last applied migration.\nif migration, err := gl.Current(); err == nil {\n\tgl.Revert(migration)\n}\n```\n\nHere is a description for the main Gloat methods.\n\n```go\n// Unapplied returns the unapplied migrations in the current gloat.\nfunc (c *Gloat) Unapplied() (Migrations, error) {}\n\n// Current returns the latest applied migration. Even if no error is returned,\n// the current migration can be nil.\n//\n// This is the case when the last applied migration is no longer available from\n// the source or there are no migrations to begin with.\nfunc (c *Gloat) Current() (*Migration, error) {}\n\n// Apply applies a migration.\nfunc (c *Gloat) Apply(migration *Migration) error {}\n\n// Revert rollbacks a migration.\nfunc (c *Gloat) Revert(migration *Migration) error {}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgsamokovarov%2Fgloat","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgsamokovarov%2Fgloat","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgsamokovarov%2Fgloat/lists"}