{"id":48652962,"url":"https://github.com/hakadoriya/ddlctl","last_synced_at":"2026-04-10T08:55:13.579Z","repository":{"id":209258030,"uuid":"723538571","full_name":"hakadoriya/ddlctl","owner":"hakadoriya","description":"ddlctl is a tool to control RDBMS DDLs: output all RDBMS DDLs, generate DDLs from tagged Golang source code, view differences between RDBMS and your DDL, and automate migrations.","archived":false,"fork":false,"pushed_at":"2026-02-02T02:07:19.000Z","size":839,"stargazers_count":8,"open_issues_count":2,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-04-10T08:55:07.904Z","etag":null,"topics":["create-table","ddl","diff","go","golang","migration"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hakadoriya.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":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-11-26T01:23:39.000Z","updated_at":"2025-11-21T05:36:13.000Z","dependencies_parsed_at":"2024-01-18T07:47:16.277Z","dependency_job_id":"613cb9e8-db34-4fa6-a53a-eae13d2eb439","html_url":"https://github.com/hakadoriya/ddlctl","commit_stats":null,"previous_names":["kunitsucom/ddlctl","hakadoriya/ddlctl"],"tags_count":23,"template":false,"template_full_name":null,"purl":"pkg:github/hakadoriya/ddlctl","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hakadoriya%2Fddlctl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hakadoriya%2Fddlctl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hakadoriya%2Fddlctl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hakadoriya%2Fddlctl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hakadoriya","download_url":"https://codeload.github.com/hakadoriya/ddlctl/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hakadoriya%2Fddlctl/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31635969,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-10T07:40:12.752Z","status":"ssl_error","status_checked_at":"2026-04-10T07:40:11.664Z","response_time":98,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["create-table","ddl","diff","go","golang","migration"],"created_at":"2026-04-10T08:55:12.378Z","updated_at":"2026-04-10T08:55:13.569Z","avatar_url":"https://github.com/hakadoriya.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# [ddlctl](https://github.com/hakadoriya/ddlctl)\n\n`ddlctl` is a tool to control RDBMS DDLs: output all RDBMS DDLs, generate DDLs from tagged Golang source code, view differences between RDBMS and your DDL, and automate migrations.\n\n\u003e [!WARNING]\n\u003e This project is experimental. It is operational in the author's environment, but it is not known if it can be operated in other environments without trouble.  \n\n[![license](https://img.shields.io/github/license/hakadoriya/ddlctl)](LICENSE)\n[![pkg](https://pkg.go.dev/badge/github.com/hakadoriya/ddlctl)](https://pkg.go.dev/github.com/hakadoriya/ddlctl)\n[![goreportcard](https://goreportcard.com/badge/github.com/hakadoriya/ddlctl)](https://goreportcard.com/report/github.com/hakadoriya/ddlctl)\n[![workflow](https://github.com/hakadoriya/ddlctl/workflows/go-lint/badge.svg)](https://github.com/hakadoriya/ddlctl/tree/main)\n[![workflow](https://github.com/hakadoriya/ddlctl/workflows/go-test/badge.svg)](https://github.com/hakadoriya/ddlctl/tree/main)\n[![workflow](https://github.com/hakadoriya/ddlctl/workflows/go-vuln/badge.svg)](https://github.com/hakadoriya/ddlctl/tree/main)\n[![codecov](https://codecov.io/gh/hakadoriya/ddlctl/graph/badge.svg?token=8Jtk2bpTe2)](https://codecov.io/gh/hakadoriya/ddlctl)\n[![sourcegraph](https://sourcegraph.com/github.com/hakadoriya/ddlctl/-/badge.svg)](https://sourcegraph.com/github.com/hakadoriya/ddlctl)\n\n## Demo\n\n![ddlctl_demo](https://github.com/hakadoriya/ddlctl/assets/29125616/cdb603ad-bb44-4e18-8af0-ac5bce46e319)\n\n## Overview\n\nddlctl can do the following:  \n\n- Output all RDBMS DDLs\n- Generate DDL from tagged Golang source code\n- Output differences between the RDBMS and your DDL\n- Automated Migration\n\n## TODO\n\n- `generate` subcommand\n  - source language\n    - [x] Support `go` (beta)\n  - dialect\n    - [x] Support `mysql` (alpha)\n    - [x] Support `postgres` (alpha)\n    - [x] Support `cockroachdb` (alpha)\n    - [x] Support `spanner` (alpha)\n    - [ ] Support `sqlite3`\n- `show` subcommand\n  - dialect\n    - [x] Support `mysql` (beta)\n    - [x] Support `postgres` (alpha)\n    - [x] Support `cockroachdb` (beta)\n    - [x] Support `spanner` (alpha)\n    - [ ] Support `sqlite3`\n- `diff` subcommand\n  - dialect\n    - [x] Support `mysql` (alpha)\n    - [x] Support `postgres` (alpha)\n    - [x] Support `cockroachdb` (alpha)\n    - [x] Support `spanner` (alpha)\n    - [ ] Support `sqlite3`\n- `apply` subcommand\n  - dialect\n    - [x] Support `mysql` (alpha)\n    - [x] Support `postgres` (alpha)\n    - [x] Support `cockroachdb` (alpha)\n    - [x] Support `spanner` (alpha)\n    - [ ] Support `sqlite3`\n\n## Example: `ddlctl generate`\n\n### 1. Prepare your annotated model source code\n\nFor example, prepare the following Go code:  \n\n```go\npackage sample\n\n// User is a user model struct.\n//\n//pgddl:table      public.users\n//pgddl:constraint UNIQUE (\"username\")\n//pgddl:index      \"index_users_username\" ON public.users (\"username\")\ntype User struct {\n    UserID   string `db:\"user_id\"  pgddl:\"TEXT NOT NULL\" pk:\"true\"`\n    Username string `db:\"username\" pgddl:\"TEXT NOT NULL\"`\n    Age      int    `db:\"age\"      pgddl:\"INT  NOT NULL\"`\n}\n\n// Group is a group model struct.\n//\n//pgddl:table CREATE TABLE IF NOT EXISTS public.groups\n//pgddl:index CREATE UNIQUE INDEX \"index_groups_group_name\" ON public.groups (\"group_name\")\ntype Group struct {\n    GroupID     string `db:\"group_id\"    pgddl:\"TEXT NOT NULL\" pk:\"true\"`\n    GroupName   string `db:\"group_name\"  pgddl:\"TEXT NOT NULL\"`\n    Description string `db:\"description\" pgddl:\"TEXT NOT NULL\"`\n}\n```\n\n### 2. Generate DDL\n\nPlease execute the ddlctl command as follows:  \n\n```console\n$ ddlctl generate --dialect postgres --go-column-tag db --go-ddl-tag pgddl --go-pk-tag pk sample.go sample.sql\nINFO: 2023/11/16 16:10:39 ddlctl.go:44: source: sample.go\nINFO: 2023/11/16 16:10:39 ddlctl.go:73: destination: sample.sql\n```\n\n### 3. Check generated DDL file\n\nPlease check the contents of the outputted DDL:  \n\n```sh\ncat sample.sql\n```\n\ncontent:  \n\n```sql\n-- Code generated by ddlctl. DO NOT EDIT.\n--\n\n-- source: docs/sample.go:5\n-- User is a user model struct.\n--\n-- pgddl:table      public.users\n-- pgddl:constraint UNIQUE (\"username\")\nCREATE TABLE public.users (\n    \"user_id\"  TEXT NOT NULL,\n    \"username\" TEXT NOT NULL,\n    \"age\"      INT  NOT NULL,\n    PRIMARY KEY (\"user_id\"),\n    UNIQUE (\"username\")\n);\n\n-- source: docs/sample.go:7\n-- pgddl:index      \"index_users_username\" ON public.users (\"username\")\nCREATE INDEX \"index_users_username\" ON public.users (\"username\");\n\n-- source: docs/sample.go:16\n-- Group is a group model struct.\n--\n-- pgddl:table CREATE TABLE IF NOT EXISTS public.groups\nCREATE TABLE IF NOT EXISTS public.groups (\n    \"group_id\"    TEXT NOT NULL,\n    \"group_name\"  TEXT NOT NULL,\n    \"description\" TEXT NOT NULL,\n    PRIMARY KEY (\"group_id\")\n);\n\n-- source: docs/sample.go:17\n-- pgddl:index CREATE UNIQUE INDEX \"index_groups_group_name\" ON public.groups (\"group_name\")\nCREATE UNIQUE INDEX \"index_groups_group_name\" ON public.groups (\"group_name\");\n```\n\n## Example: `ddlctl diff` and `ddlctl apply`\n\n### 1. Prepare your DDL\n\n```sh\ncat sample.sql\n```\n\ncontent:  \n\n```sql\n-- Code generated by ddlctl. DO NOT EDIT.\n--\n\n-- source: docs/sample.go:5\n-- User is a user model struct.\n--\n-- pgddl:table      public.users\n-- pgddl:constraint UNIQUE (\"username\")\nCREATE TABLE public.users (\n    \"user_id\"  TEXT NOT NULL,\n    \"username\" TEXT NOT NULL,\n    \"age\"      INT  NOT NULL,\n    PRIMARY KEY (\"user_id\"),\n    UNIQUE (\"username\")\n);\n\n-- source: docs/sample.go:7\n-- pgddl:index      \"index_users_username\" ON public.users (\"username\")\nCREATE INDEX \"index_users_username\" ON public.users (\"username\");\n\n-- source: docs/sample.go:16\n-- Group is a group model struct.\n--\n-- pgddl:table CREATE TABLE IF NOT EXISTS public.groups\nCREATE TABLE IF NOT EXISTS public.groups (\n    \"group_id\"    TEXT NOT NULL,\n    \"group_name\"  TEXT NOT NULL,\n    \"description\" TEXT NOT NULL,\n    PRIMARY KEY (\"group_id\")\n);\n\n-- source: docs/sample.go:17\n-- pgddl:index CREATE UNIQUE INDEX \"index_groups_group_name\" ON public.groups (\"group_name\")\nCREATE UNIQUE INDEX \"index_groups_group_name\" ON public.groups (\"group_name\");\n```\n\n### 2. Check diff from local DDL file to DSN\n\nPlease check the differences between the local DDL file and the destination database:\n\n```console\n$ ddlctl diff --dialect postgres \"postgres://postgres:password@localhost/testdb?sslmode=disable\" sample.sql\nCREATE TABLE public.users (\n    \"user_id\" TEXT NOT NULL,\n    \"username\" TEXT NOT NULL,\n    \"age\" INT NOT NULL,\n    CONSTRAINT users_pkey PRIMARY KEY (\"user_id\"),\n    CONSTRAINT users_unique_username UNIQUE (\"username\")\n);\nCREATE INDEX \"index_users_username\" ON public.users (\"username\");\nCREATE TABLE IF NOT EXISTS public.groups (\n    \"group_id\" TEXT NOT NULL,\n    \"group_name\" TEXT NOT NULL,\n    \"description\" TEXT NOT NULL,\n    CONSTRAINT groups_pkey PRIMARY KEY (\"group_id\")\n);\nCREATE UNIQUE INDEX \"index_groups_group_name\" ON public.groups (\"group_name\");\n```\n\n### 3. Apply DDL\n\n```console\n$ ddlctl apply --dialect postgres \"postgres://postgres:password@localhost/testdb?sslmode=disable\" sample.sql --auto-approve\n\nddlctl will exec the following DDL queries:\n\n-- 8\u003c --\n\nCREATE TABLE public.users (\n    \"user_id\" TEXT NOT NULL,\n    \"username\" TEXT NOT NULL,\n    \"age\" INT NOT NULL,\n    CONSTRAINT users_pkey PRIMARY KEY (\"user_id\"),\n    CONSTRAINT users_unique_username UNIQUE (\"username\")\n);\nCREATE INDEX \"index_users_username\" ON public.users (\"username\");\nCREATE TABLE IF NOT EXISTS public.groups (\n    \"group_id\" TEXT NOT NULL,\n    \"group_name\" TEXT NOT NULL,\n    \"description\" TEXT NOT NULL,\n    CONSTRAINT groups_pkey PRIMARY KEY (\"group_id\")\n);\nCREATE UNIQUE INDEX \"index_groups_group_name\" ON public.groups (\"group_name\");\n\n\n-- \u003e8 --\n\nDo you want to apply these DDL queries?\n  ddlctl will exec the DDL queries described above.\n  Only 'yes' will be accepted to approve.\n\nEnter a value: yes (via --auto-approve option)\n\nexecuting...\ndone\n```\n\n### 4. (Optional) Edit DDL and apply\n\n```diff\n -- pgddl:table public.users\n -- pgddl:constraint UNIQUE (\"username\")\n CREATE TABLE public.users (\n     \"user_id\"     TEXT NOT NULL,\n     \"username\"    TEXT NOT NULL,\n     \"age\"         INT  NOT NULL,\n+    \"description\" TEXT NOT NULL,\n     PRIMARY KEY (\"user_id\"),\n     UNIQUE (\"username\")\n );\n```\n\napply:\n\n```console\n$ ddlctl apply --dialect postgres \"postgres://postgres:password@localhost/testdb?sslmode=disable\" sample.sql --auto-approve\n\nddlctl will exec the following DDL queries:\n\n-- 8\u003c --\n\n-- -\n-- +\"description\" TEXT NOT NULL\nALTER TABLE public.users ADD COLUMN \"description\" TEXT NOT NULL;\n\n\n-- \u003e8 --\n\nDo you want to apply these DDL queries?\n  ddlctl will exec the DDL queries described above.\n  Only 'yes' will be accepted to approve.\n\nEnter a value: yes (via --auto-approve option)\n\nexecuting...\ndone\n```\n\n## Installation\n\n### pre-built binary\n\n```bash\nLATEST_VERSION=$(curl -ISs https://github.com/hakadoriya/ddlctl/releases/latest | tr -d '\\r' | awk -F/ '/location:/{print $NF}')\nOS=$(uname | tr '[:upper:]' '[:lower:]')\nARCH=$(uname -m)\nURL=\"https://github.com/hakadoriya/ddlctl/releases/download/${LATEST_VERSION}/ddlctl_${LATEST_VERSION}_${OS}_${ARCH}.zip\"\n\n# Check URL\necho \"${URL}\"\n\n# Download\ncurl -fLROSs \"${URL}\"\n\n# Unzip\nunzip -j ddlctl_${LATEST_VERSION}_${OS}_${ARCH}.zip '*/ddlctl'\n```\n\n### go install\n\n```bash\ngo install github.com/hakadoriya/ddlctl/cmd/ddlctl@latest\n```\n\n## Usage\n\n### `ddlctl`\n\n```console\n$ ddlctl --help\nUsage:\n    ddlctl [options]\n\nDescription:\n    ddlctl is a tool for control RDBMS DDL.\n\nsub commands:\n    version: show version\n    generate: generate DDL from source (file or directory) to destination (file or directory).\n    show: show DDL from DSN like `SHOW CREATE TABLE`.\n    diff: diff DDL from \u003cbefore DDL source\u003e to \u003cafter DDL source\u003e.\n    apply: apply DDL from \u003cDDL source\u003e to \u003cDSN to apply\u003e.\n\noptions:\n    --trace (env: DDLCTL_TRACE, default: false)\n        trace mode enabled\n    --debug (env: DDLCTL_DEBUG, default: false)\n        debug mode\n    --help (default: false)\n        show usage\n```\n\n### `ddlctl generate`\n\n```console\n$ ddlctl generate --help\nUsage:\n    ddlctl generate [options] --dialect \u003cDDL dialect\u003e \u003csource\u003e \u003cdestination\u003e\n\nDescription:\n    generate DDL from source (file or directory) to destination (file or directory).\n\noptions:\n    --lang (env: DDLCTL_LANGUAGE, default: go)\n        programming language to generate DDL\n    --dialect (env: DDLCTL_DIALECT, default: )\n        SQL dialect to generate DDL\n    --go-column-tag (env: DDLCTL_GO_COLUMN_TAG, default: db)\n        column annotation key for Go struct tag\n    --go-ddl-tag (env: DDLCTL_GO_DDL_TAG, default: ddlctl)\n        DDL annotation key for Go struct tag\n    --go-pk-tag (env: DDLCTL_GO_PK_TAG, default: pk)\n        primary key annotation key for Go struct tag\n    --help (default: false)\n        show usage\n```\n\n### `ddlctl show`\n\n```console\n$ ddlctl show --help\nUsage:\n    ddlctl show --dialect \u003cDDL dialect\u003e \u003cDSN\u003e\n\nDescription:\n    show DDL from DSN like `SHOW CREATE TABLE`.\n\noptions:\n    --dialect (env: DDLCTL_DIALECT, default: )\n        SQL dialect to generate DDL\n    --help (default: false)\n        show usage\n```\n\n### `ddlctl diff`\n\n```console\n$ ddlctl diff --help\nUsage:\n    ddlctl diff [options] --dialect \u003cDDL dialect\u003e \u003cbefore DDL source\u003e \u003cafter DDL source\u003e\n\nDescription:\n    diff DDL from \u003cbefore DDL source\u003e to \u003cafter DDL source\u003e.\n\noptions:\n    --lang (env: DDLCTL_LANGUAGE, default: go)\n        programming language to generate DDL\n    --dialect (env: DDLCTL_DIALECT, default: )\n        SQL dialect to generate DDL\n    --go-column-tag (env: DDLCTL_GO_COLUMN_TAG, default: db)\n        column annotation key for Go struct tag\n    --go-ddl-tag (env: DDLCTL_GO_DDL_TAG, default: ddlctl)\n        DDL annotation key for Go struct tag\n    --go-pk-tag (env: DDLCTL_GO_PK_TAG, default: pk)\n        primary key annotation key for Go struct tag\n    --help (default: false)\n        show usage\n```\n\n### `ddlctl apply`\n\n```console\n$ ddlctl apply --help\nUsage:\n    ddlctl apply [options] --dialect \u003cDDL dialect\u003e \u003cDSN to apply\u003e \u003cDDL source\u003e\n\nDescription:\n    apply DDL from \u003cDDL source\u003e to \u003cDSN to apply\u003e.\n\noptions:\n    --lang (env: DDLCTL_LANGUAGE, default: go)\n        programming language to generate DDL\n    --dialect (env: DDLCTL_DIALECT, default: )\n        SQL dialect to generate DDL\n    --go-column-tag (env: DDLCTL_GO_COLUMN_TAG, default: db)\n        column annotation key for Go struct tag\n    --go-ddl-tag (env: DDLCTL_GO_DDL_TAG, default: ddlctl)\n        DDL annotation key for Go struct tag\n    --go-pk-tag (env: DDLCTL_GO_PK_TAG, default: pk)\n        primary key annotation key for Go struct tag\n    --auto-approve (env: DDLCTL_AUTO_APPROVE, default: false)\n        auto approve\n    --help (default: false)\n        show usage\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhakadoriya%2Fddlctl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhakadoriya%2Fddlctl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhakadoriya%2Fddlctl/lists"}