{"id":6869,"library":"schemachange","title":"Schemachange: A Database Change Management tool for Snowflake","description":"Schemachange is an open-source Python-based database change management (DCM) tool designed for Snowflake, inspired by the Flyway database migration tool. It follows an imperative-style approach, allowing users to track and apply SQL and CLI migration scripts in a version-controlled, repeatable, and auditable manner. It integrates seamlessly with CI/CD pipelines to automate database deployments. The current version is 4.3.2, with minor releases typically occurring every 4-6 weeks and patch releases issued as needed for critical bug fixes.","status":"active","version":"4.3.2","language":"en","source_language":"en","source_url":"https://github.com/Snowflake-Labs/schemachange","tags":["Snowflake","database migration","schema management","DevOps","CLI","SQL"],"install":[{"cmd":"pip install schemachange","lang":"bash","label":"Install latest version"}],"dependencies":[{"reason":"Requires Python 3.10 or higher.","package":"python","optional":false},{"reason":"Core dependency for connecting to Snowflake. Minimum version was bumped to 3.0.0 in schemachange v4.3.0.","package":"snowflake-connector-python","optional":false},{"reason":"Added in v4.0.0 for standard log outputs.","package":"structlog","optional":false},{"reason":"Fixed a missing dependency on Windows in v4.2.0.","package":"colorama","optional":false}],"imports":[{"note":"Schemachange is primarily a Command Line Interface (CLI) tool. Direct programmatic imports for deploying migrations are less common for typical quickstart scenarios; users generally interact with it by executing `schemachange` commands via `subprocess` or directly in a shell.","symbol":"schemachange CLI","correct":"import subprocess\nimport os\n\n# Most common usage is via CLI\nsubprocess.run([\"schemachange\", \"deploy\", \"-f\", \"./migrations\"], env=os.environ)"}],"quickstart":{"code":"import os\nimport subprocess\n\n# Create a dummy migrations folder and script for demonstration\nif not os.path.exists('migrations'):\n    os.makedirs('migrations')\n\nwith open('migrations/V1.0.0__initial_setup.sql', 'w') as f:\n    f.write(\"CREATE SCHEMA IF NOT EXISTS MY_APP;\\n\")\n    f.write(\"CREATE TABLE IF NOT EXISTS MY_APP.CUSTOMERS (ID INTEGER, NAME VARCHAR(100));\")\n\n# Set environment variables for Snowflake connection (replace with your actual details)\n# For production, use secure methods like secrets management or connections.toml\n# NOTE: For quickstart, ensure these are actual values or use a dummy Snowflake connection if possible\nenv = os.environ.copy()\nenv['SNOWFLAKE_ACCOUNT'] = os.environ.get('SNOWFLAKE_ACCOUNT', 'your_account_identifier')\nenv['SNOWFLAKE_USER'] = os.environ.get('SNOWFLAKE_USER', 'your_user')\nenv['SNOWFLAKE_PASSWORD'] = os.environ.get('SNOWFLAKE_PASSWORD', 'your_password')\nenv['SNOWFLAKE_ROLE'] = os.environ.get('SNOWFLAKE_ROLE', 'SYSADMIN')\nenv['SNOWFLAKE_WAREHOUSE'] = os.environ.get('SNOWFLAKE_WAREHOUSE', 'COMPUTE_WH')\nenv['SNOWFLAKE_DATABASE'] = os.environ.get('SNOWFLAKE_DATABASE', 'DEMO_DB')\nenv['SCHEMACHANGE_CHANGE_HISTORY_TABLE'] = os.environ.get('SCHEMACHANGE_CHANGE_HISTORY_TABLE', 'DEMO_DB.SCHEMACHANGE.CHANGE_HISTORY')\n\nprint(\"Running schemachange deploy...\")\ntry:\n    result = subprocess.run(\n        [\n            \"schemachange\",\n            \"deploy\",\n            \"-f\", \"./migrations\",\n            \"--create-change-history-table\",\n            \"--verbose\"\n        ],\n        env=env, # Pass environment variables to the subprocess\n        check=True, # Raise an exception for non-zero exit codes\n        capture_output=True, # Capture stdout and stderr\n        text=True # Decode stdout/stderr as text\n    )\n    print(\"Schemachange deployment successful.\")\n    print(\"STDOUT:\", result.stdout)\n    if result.stderr:\n        print(\"STDERR:\", result.stderr)\nexcept subprocess.CalledProcessError as e:\n    print(f\"Schemachange deployment failed with error: {e}\")\n    print(\"STDOUT:\", e.stdout)\n    print(\"STDERR:\", e.stderr)\nexcept FileNotFoundError:\n    print(\"Error: 'schemachange' command not found. Is schemachange installed and in your PATH?\")","lang":"python","description":"This quickstart demonstrates how to set up a basic `schemachange` project and run a deployment using Python's `subprocess` module to execute the `schemachange` CLI. It creates a dummy `migrations` folder and an initial SQL script, then attempts to deploy it to a Snowflake instance using credentials provided via environment variables. The `--create-change-history-table` flag is included to automatically create the change history table if it doesn't exist. Ensure your Snowflake account, user, password, role, warehouse, and database environment variables are correctly set for authentication."},"warnings":[{"fix":"Upgrade directly to v4.3.2. If coming from 4.3.0/4.3.1, expect a one-time 'checksum has drifted' warning for affected V-scripts or potential re-execution for R-scripts.","message":"Checksum drift for scripts ending with a semicolon when upgrading from v4.3.0/v4.3.1 to v4.3.2. A regression in v4.3.0 accidentally removed trailing semicolon stripping, causing checksum mismatches.","severity":"breaking","affected_versions":"4.3.0, 4.3.1"},{"fix":"Ensure `snowflake-connector-python` is updated to a version 3.x or higher before upgrading to schemachange v4.3.0 or later.","message":"Minimum `snowflake-connector-python` version was bumped to `>=3.0.0` in v4.3.0, dropping support for `snowflake-connector-python` 2.x.","severity":"breaking","affected_versions":"<4.3.0"},{"fix":"Either manually create the `METADATA.SCHEMACHANGE.CHANGE_HISTORY` table (or your configured table) in Snowflake, or run `schemachange deploy` with the `--create-change-history-table` flag, or set `create-change-history-table: true` in your `schemachange-config.yml`. Ensure the database for the history table already exists.","message":"Schemachange, by default, will not create the change history table and will fail if it doesn't exist. It also won't create the database for this table.","severity":"gotcha","affected_versions":"All versions"},{"fix":"For sensitive credentials like private key passphrases, use environment variables (e.g., `SNOWFLAKE_PRIVATE_KEY_PASSPHRASE`) or define them in a `connections.toml` file to avoid exposure in process lists or shell history. Generic `SNOWFLAKE_*` environment variables are also passed through.","message":"New CLI authentication parameters (`--snowflake-authenticator`, `--snowflake-private-key-file`, `--snowflake-token-file-path`) were added in v4.1.0, but `--snowflake-private-key-file-pwd` (passphrase) is *intentionally not supported* via CLI for security reasons.","severity":"gotcha","affected_versions":"4.1.0 and later"},{"fix":"Understand the implications of `--out-of-order` (or `SCHEMACHANGE_OUT_OF_ORDER=true` / `out-of-order: true` in config) for your deployment strategy, especially in parallel development workflows. It is recommended to use timestamp-based versioning to minimize collisions.","message":"Out-of-Order Execution, introduced in v4.3.0, changes how versioned scripts are applied. If enabled, scripts can be applied even if their version is older than the maximum applied version.","severity":"gotcha","affected_versions":"4.3.0 and later"},{"fix":"While still functional, consider using alternative logging configurations if precise control over verbosity is needed.","message":"The `--verbose` flag for command-line output was deprecated.","severity":"deprecated","affected_versions":"4.1.0 and later"},{"fix":"Plan to migrate to the newer `--snowflake-private-key-file` and environment variables for passphrases (`SNOWFLAKE_PRIVATE_KEY_PASSPHRASE`) or `connections.toml` configurations.","message":"Parameters `private_key_path` and `private_key_passphrase` are slated for removal in the upcoming v5.0.0 major release.","severity":"deprecated","affected_versions":"All versions (deprecation warning in 4.x, removal in 5.0)"}],"env_vars":null,"last_verified":"2026-04-15T00:00:00.000Z","next_check":"2026-07-14T00:00:00.000Z","problems":[]}