golang-migrate

repository·master·Indexed 18 hours ago

https://github.com/golang-migrate/migrate

A database migration tool available as a CLI or Go library. It supports a wide variety of databases and migration sources to manage schema changes, featuring commands for creating, applying, and rolling back migrations.

Tokens
24.9K
Snippets
101
Records
125
Agent score
97%

What's inside golang-migrate

  1. Overview of migrate

    master
    migrate is a database migration tool written in Go that can be used as a CLI or imported as a library. It reads migrations from various sources and applies them to a database using specialized drivers. The core logic is handled by the migrate engine, while drivers remain lightweight and 'dumb', focusing only on executing the migrations provided.
  2. Use Azure MSI Authentication with SQL Server

    master

    You can use Azure Managed Service Identity (MSI) for authentication by setting the useMsi query parameter to true in your connection string.

    Requirements:

    • The application must be running from an Azure VM or an instance with MSI enabled.
    • This feature is not officially supported as it cannot be tested locally.

    Example URL: sqlserver://host/database?useMsi=true

    sqlserver://host/database?useMsi=true
  3. Enable multi-statement mode in PostgreSQL

    master

    By default, migrate executes statements in a way that PostgreSQL wraps multiple statements in a single transaction. This is problematic for commands that cannot run inside a transaction, such as CREATE INDEX CONCURRENTLY.

    To enable multi-statement execution, use the x-multi-statement query parameter in your connection URL. If you do not want to enable this mode, you must place statements like CREATE INDEX CONCURRENTLY in their own separate migration files.

    postgres://user:password@host:port/dbname?x-multi-statement=true
  4. Handle transactions in Neo4j migrations

    master

    When writing Cypher migrations for Neo4j, if you want your queries to be executed within a transaction, you must explicitly wrap your Cypher statements with the :BEGIN and :COMMIT commands within the .up.cypher or .down.cypher files.

    :BEGIN
    
    MATCH (u:User)
    SET u.mood = "Cheery"
    
    :COMMIT
  5. Configure Neo4j migrations with multiple statements

    master

    The Neo4j driver (bolt) does not natively support executing multiple statements in a single query. To enable multiple statements within a single migration file, you must use the x-multi-statement parameter in your database URL.

    When enabled, golang-migrate splits the migration text into separate statements using the semi-colon ; as a delimiter.

    Warning: Do not use x-multi-statement if any of your migration statements contain a semi-colon within a string literal, as this will cause the statement to be incorrectly split.

    While queries should run in a single transaction to prevent partial migrations, this behavior is currently untested.

    neo4j://user:password@host:port/?x-multi-statement=true
  6. Disable implicit transactions in sqlite3

    master

    If your SQLite3 migrations require explicit BEGIN and COMMIT statements, you must disable the driver's default behavior of wrapping migrations in an implicit transaction. This is done by setting the x-no-tx-wrap query parameter to true in your connection string, or by setting NoTxWrap: true in the WithInstance configuration when using the Go API.

    sqlite3://path/to/database?x-no-tx-wrap=true
  7. Create a custom migration source driver using httpfs.PartialDriver

    master

    If you need to implement a custom migration source driver that relies on an http.FileSystem, you can embed httpfs.PartialDriver into your own struct. httpfs.PartialDriver implements most of the source.Driver interface, but requires you to provide the Open(url string) (source.Driver, error) method to complete the implementation. This allows you to define how migration files are located and opened via your specific filesystem logic.

    struct mydriver {
            httpfs.PartialDriver
    }
    
    func (d *mydriver) Open(url string) (source.Driver, error) {
    	var fs http.FileSystem
    	var path string
    	var ds mydriver
    
    	// acquire fs and path from url
    	// set-up ds if necessary
    
    	if err := ds.Init(fs, path); err != nil {
    		return nil, err
    	}
    	return &ds, nil
    }
  8. Enable multiple statements in ClickHouse migrations

    master

    The ClickHouse driver does not natively support executing multiple statements in a single query. To allow multiple statements in a single migration file, append the x-multi-statement=true parameter to your connection URL.

    Important Caveats:

    • Semicolon Splitting: This mode splits the migration text into separately-executed statements using the semicolon ; as a delimiter. You cannot use x-multi-statement if any statement in your migration contains a semicolon within a string literal.
    • No Atomicity: Queries are not executed within a transaction or batch. You are responsible for handling partial migrations if a failure occurs mid-migration.
    `clickhouse://host:port?username=user&password=password&database=clicks&x-multi-statement=true`
  9. Implement database transactions in CockroachDB migrations

    master

    When writing migrations for CockroachDB, you can wrap multiple SQL statements in a transaction using BEGIN; and COMMIT; commands. This ensures that the migration is atomic, similar to PostgreSQL behavior.

    Example .up.sql migration with a transaction:

    BEGIN;
    
    ALTER TABLE example.users ADD COLUMN mood STRING;
    ALTER TABLE example.users ADD CONSTRAINT check_mood CHECK (mood IN ('happy', 'sad', 'neutral'));
    
    COMMIT;
  10. Format database connection URLs

    master

    Database connection strings are specified via URLs. While the format is driver-dependent, it generally follows this pattern:

    dbdriver://username:password@host:port/dbname?param1=true&param2=false

    Important: Any reserved URL characters must be percent-encoded. This includes characters like !, #, $, %, &, ', (, ), *, +, ,, /, :, ;, =, ?, @, [, and ]. It is highly recommended to run your credentials (username, password, etc.) through a URL encoder before constructing the connection string.

    # Example: Encoding a complex password using Python
    $ python3 -c 'import urllib.parse; print(urllib.parse.quote(input("String to encode: "), ""))'
    String to encode: FAKEpassword!#$%&'()*+,/:;=?@[]
    FAKEpassword%21%23%24%25%26%27%28%29%2A%2B%2C%2F%3A%3B%3D%3F%40%5B%5D
  11. Configure MongoDB migrations

    master

    When using MongoDB with golang-migrate, migrations must be written in JSON format. Each migration file should contain an array of commands that are executed via MongoDB's db.runCommand.

    Key Requirements:

    • Every command is executed as a separate request to the database.
    • All keys in the JSON commands must be enclosed in double quotes (").

    Refer to the examples directory in the repository for specific migration file structures.

    [
      {
        "insert": "collection_name",
        "documents": [
          { "field": "value" }
        ]
      }
    ]