Git Product home page Git Product logo

sqldef's Introduction

sqldef Build Status

The easiest idempotent MySQL/PostgreSQL/SQLite3 schema management by SQL.

This is inspired by Ridgepole but using SQL, so there's no need to remember Ruby DSL.

demo

Installation

Download the single-binary executable for your favorite database from:

https://github.com/k0kubun/sqldef/releases

Usage

mysqldef

mysqldef should work in the same way as mysql for setting connection information.

$ mysqldef --help
Usage:
  mysqldef [options] db_name

Application Options:
  -u, --user=user_name       MySQL user name (default: root)
  -p, --password=password    MySQL user password, overridden by $MYSQL_PWD
  -h, --host=host_name       Host to connect to the MySQL server (default: 127.0.0.1)
  -P, --port=port_num        Port used for the connection (default: 3306)
  -S, --socket=socket        The socket file to use for connection
      --password-prompt      Force MySQL user password prompt
      --file=sql_file        Read schema SQL from the file, rather than stdin (default: -)
      --dry-run              Don't run DDLs but just show them
      --export               Just dump the current schema to stdout
      --skip-drop            Skip destructive changes such as DROP
      --help                 Show this help

Example

# Make sure that MySQL server can be connected by mysql(1)
$ mysql -uroot test -e "select 1;"
+---+
| 1 |
+---+
| 1 |
+---+

# Dump current schema by adding `def` suffix and --export
$ mysqldef -uroot test --export
CREATE TABLE `user` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(191) DEFAULT 'k0kubun',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

# Save it to edit
$ mysqldef -uroot test --export > schema.sql

Update the schema.sql like (instead of ADD INDEX, you can just add KEY index_name (name) in the CREATE TABLE as well):

 CREATE TABLE user (
   id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
   name VARCHAR(128) DEFAULT 'k0kubun',
+  created_at DATETIME NOT NULL
 ) Engine=InnoDB DEFAULT CHARSET=utf8mb4;
+
+ALTER TABLE user ADD INDEX index_name(name);

And then run:

# Check the auto-generated migration plan without execution
$ mysqldef -uroot test --dry-run < schema.sql
--- dry run ---
Run: 'ALTER TABLE user ADD COLUMN created_at datetime NOT NULL ;'
Run: 'ALTER TABLE user ADD INDEX index_name(name);'

# Run the above DDLs
$ mysqldef -uroot test < schema.sql
Run: 'ALTER TABLE user ADD COLUMN created_at datetime NOT NULL ;'
Run: 'ALTER TABLE user ADD INDEX index_name(name);'

# Operation is idempotent, safe for running it multiple times
$ mysqldef -uroot test < schema.sql
Nothing is modified

# Run without droping existing tables and columns
$ mysqldef -uroot test --skip-drop < schema.sql
Skipped: 'DROP TABLE users;'

psqldef

psqldef should work in the same way as psql for setting connection information.

$ psqldef --help
Usage:
  psqldef [option...] db_name

Application Options:
  -U, --user=username        PostgreSQL user name (default: postgres)
  -W, --password=password    PostgreSQL user password, overridden by $PGPASS
  -h, --host=hostname        Host or socket directory to connect to the PostgreSQL server (default: 127.0.0.1)
  -p, --port=port            Port used for the connection (default: 5432)
      --password-prompt      Force PostgreSQL user password prompt
  -f, --file=filename        Read schema SQL from the file, rather than stdin (default: -)
      --dry-run              Don't run DDLs but just show them
      --export               Just dump the current schema to stdout
      --skip-drop            Skip destructive changes such as DROP
      --help                 Show this help

You can use PGSSLMODE environment variable to specify sslmode.

Example

# Make sure that PostgreSQL server can be connected by psql(1)
$ psql -U postgres test -c "select 1;"
 ?column?
----------
        1
(1 row)

# Dump current schema by adding `def` suffix and --export
$ psqldef -U postgres test --export
CREATE TABLE public.users (
    id bigint NOT NULL,
    name text,
    age integer
);

CREATE TABLE public.bigdata (
    data bigint
);

# Save it to edit
$ psqldef -U postgres test --export > schema.sql

Update the schema.sql like:

 CREATE TABLE users (
     id bigint NOT NULL PRIMARY KEY,
-    name text,
     age int
 );

-CREATE TABLE bigdata (
-    data bigint
-);

And then run:

# Check the auto-generated migration plan without execution
$ psqldef -U postgres test --dry-run < schema.sql
--- dry run ---
Run: 'DROP TABLE bigdata;'
Run: 'ALTER TABLE users DROP COLUMN name;'

# Run the above DDLs
$ psqldef -U postgres test < schema.sql
Run: 'DROP TABLE bigdata;'
Run: 'ALTER TABLE users DROP COLUMN name;'

# Operation is idempotent, safe for running it multiple times
$ psqldef -U postgres test < schema.sql
Nothing is modified

# Run without droping existing tables and columns
$ psqldef -U postgres test --skip-drop < schema.sql
Skipped: 'DROP TABLE users;'

sqlite3def

$ sqlite3def --help
Usage:
  sqlite3def [option...] db_name

Application Options:
  -f, --file=filename    Read schema SQL from the file, rather than stdin (default: -)
      --dry-run          Don't run DDLs but just show them
      --export           Just dump the current schema to stdout
      --skip-drop        Skip destructive changes such as DROP
      --help             Show this help

Supported features

Following DDLs can be generated by updating CREATE TABLE. Some of them can also be used for input schema file.

  • MySQL
    • Table: CREATE TABLE, DROP TABLE
    • Column: ADD COLUMN, CHANGE COLUMN, DROP COLUMN
    • Index: ADD INDEX, ADD UNIQUE INDEX, CREATE INDEX, CREATE UNIQUE INDEX, DROP INDEX
    • Primary key: ADD PRIMARY KEY, DROP PRIMARY KEY
    • Foreign Key: ADD FOREIGN KEY, DROP FOREIGN KEY
  • PostgreSQL
    • Table: CREATE TABLE, DROP TABLE
    • Column: ADD COLUMN, ALTER COLUMN, DROP COLUMN
    • Index: CREATE INDEX, CREATE UNIQUE INDEX, DROP INDEX
    • Foreign / Primary Key: ADD FOREIGN KEY, DROP CONSTRAINT
  • SQLite3
    • Table: CREATE TABLE, DROP TABLE

MySQL examples

CREATE TABLE

+CREATE TABLE users (
+  name VARCHAR(40) DEFAULT NULL
+);

Remove the statement to DROP TABLE.

ADD COLUMN

 CREATE TABLE users (
   name VARCHAR(40) DEFAULT NULL,
+  created_at DATETIME NOT NULL
 );

Remove the line to DROP COLUMN.

CHANGE COLUMN

 CREATE TABLE users (
-  name VARCHAR(40) DEFAULT NULL,
+  name CHAR(40) DEFAULT NULL,
   created_at DATETIME NOT NULL
 );

ADD INDEX

 CREATE TABLE users (
   name CHAR(40) DEFAULT NULL,
   created_at DATETIME NOT NULL,
+  UNIQUE KEY index_name(name)
 );

or

 CREATE TABLE users (
   name CHAR(40) DEFAULT NULL,
   created_at DATETIME NOT NULL
 );
+
+ALTER TABLE users ADD UNIQUE INDEX index_name(name);

Remove the line to DROP INDEX.

ADD PRIMARY KEY

 CREATE TABLE users (
+  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
   name CHAR(40) DEFAULT NULL,
   created_at datetime NOT NULL,
   UNIQUE KEY index_name(name)
 );

Remove the line to DROP PRIMARY KEY.

Composite primary key may not work for now.

ADD FOREIGN KEY

 CREATE TABLE users (
   id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
   name CHAR(40) DEFAULT NULL,
   created_at datetime NOT NULL,
   UNIQUE KEY index_name(name)
 );

 CREATE TABLE posts (
   user_id BIGINT UNSIGNED NOT NULL,
+  CONSTRAINT posts_ibfk_1 FOREIGN KEY (user_id) REFERENCES users (id)
 );

Remove the line to DROP FOREIGN KEY.

Composite foreign key may not work for now.

PostgreSQL examples

CREATE TABLE

+CREATE TABLE users (
+  id BIGINT PRIMARY KEY
+);

Remove the statement to DROP TABLE.

ADD COLUMN

 CREATE TABLE users (
   id BIGINT PRIMARY KEY,
+  name VARCHAR(40)
 );

Remove the line to DROP COLUMN.

CREATE INDEX

 CREATE TABLE users (
   id BIGINT PRIMARY KEY,
   name VARCHAR(40)
 );
+CREATE INDEX index_name on users (name);

Remove the line to DROP INDEX.

ADD FOREIGN KEY

 CREATE TABLE users (
   id BIGINT PRIMARY KEY,
   name VARCHAR(40)
 );
 CREATE INDEX index_name on users (name);

 CREATE TABLE posts (
   user_id BIGINT,
+  CONSTRAINT fk_posts_user_id FOREIGN KEY (user_id) REFERENCES users (id)
 )

Remove the line to DROP CONSTRAINT.

Distributions

Linux

A debian package might be supported in the future, but for now it has not been implemented yet.

# mysqldef
wget -O - https://github.com/k0kubun/sqldef/releases/latest/download/mysqldef_linux_amd64.tar.gz \
  | tar xvz

# psqldef
wget -O - https://github.com/k0kubun/sqldef/releases/latest/download/psqldef_linux_amd64.tar.gz \
  | tar xvz

macOS

Homebrew tap is available.

# mysqldef
brew install sqldef/sqldef/mysqldef

# psqldef
brew install sqldef/sqldef/psqldef

Limitations

Because sqldef distinguishes table/index/column by its name, sqldef does NOT support:

  • RENAME TABLE
  • RENAME INDEX
    • DROP + ADD could be fine for index, though
  • CHANGE COLUMN for rename

To rename them, you would need to rename manually and use --export again.

Development

Following settings could be dangerous. Please develop sqldef under a secure network.

mysqldef

To run integration tests, mysql -uroot needs to succeed. One option is:

$ sudo mysql -uroot
mysql> UNINSTALL PLUGIN validate_password;
mysql> DROP USER 'root'@'localhost';
mysql> CREATE USER 'root'@'%' identified by '';
mysql> GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;
mysql> FLUSH PRIVILEGES;

Then running make test-mysqldef will help your development.

psqldef

To run integration tests, psql -Upostgres needs to succeed by:

  1. Open pg_hba.conf (ex: /etc/postgresql/10/main/pg_hba.conf)
  2. Change local all postgres peer to local all postgres trust
    • You may also need to take care of host all all 127.0.0.1/32 md5
  3. Restart postgresql server (ex: systemctl restart postgresql)

License

Unless otherwise noted, the sqldef source files are distributed under the MIT License found in the LICENSE file.

sqlparser is distributed under the Apache Version 2.0 license found in the sqlparser/LICENSE.md file.

sqldef's People

Contributors

k0kubun avatar touyu avatar yudppp avatar tsuty avatar kei2100 avatar kawakami-o3 avatar timakin avatar sonken625 avatar mattn avatar yuukiaria avatar dependabot[bot] avatar erjanmx avatar kyohei-shimada avatar exussum12 avatar stevep-arm avatar stephenpaulger avatar hottestseason avatar utamori avatar fujiwaram avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.