SlideShare a Scribd company logo
1 of 260
Download to read offline
Simple SQL Change
  Management with Sqitch
                                                        David E. Wheeler


                                                          PGCon 2012
                                                         Ottawa, Canada




Text: Attribution-Noncommercial-Share Alike 3.0 United States:
http://creativecommons.org/licenses/by-nc-sa/3.0/us/
Images licensed independently and © Their respective owners.
Whats Wrong with
  Migrations?
Whats Wrong with
    Migrations?
Incomplete mini-language
Whats Wrong with
     Migrations?
Incomplete mini-language

No logical replication integration
Whats Wrong with
     Migrations?
Incomplete mini-language

No logical replication integration

Numbered scripts hard to track
Whats Wrong with
     Migrations?
Incomplete mini-language

No logical replication integration

Numbered scripts hard to track

No VCS awareness
What about SQL
      Migrations?
Incomplete mini-language

No logical replication integration

Numbered scripts hard to track

No VCS awareness
What about SQL
      Migrations?
———————————————
Incomplete mini-language

No logical replication integration

Numbered scripts hard to track

No VCS awareness
What about SQL
      Migrations?
———————————————
Incomplete mini-language

———————————————————
No logical replication integration

Numbered scripts hard to track

No VCS awareness
What about SQL
      Migrations?
———————————————
Incomplete mini-language

———————————————————
No logical replication integration

Numbered scripts hard to track

No VCS awareness

Managing procedures is a PITA
Imagine this Change

>
Imagine this Change

>git diff
diff --git a/sql/deploy/recur.sql b/sql/deploy/recur.sql
index 622d52e..56e419e 100644
--- a/sql/deploy/recur.sql
+++ b/sql/deploy/recur.sql
@@ -22,7 +22,10 @@
             recurrence <> 'none'
           OR (
                recurrence = 'none'
-            AND starts_at BETWEEN range_start AND range_end
+             AND (
+                  starts_at BETWEEN range_start AND range_end
+                 OR ends_at BETWEEN range_start AND range_end
+             )
           )
        )
    LOOP
Imagine this Change

>git diff
diff --git a/sql/deploy/recur.sql b/sql/deploy/recur.sql
index 622d52e..56e419e 100644
--- a/sql/deploy/recur.sql
+++ b/sql/deploy/recur.sql
@@ -22,7 +22,10 @@
             recurrence <> 'none'
           OR (
                recurrence = 'none'
-            AND starts_at BETWEEN range_start AND range_end
+             AND (
+                  starts_at BETWEEN range_start AND range_end
+                 OR ends_at BETWEEN range_start AND range_end
+             )
           )


                  Simple, right?
        )
    LOOP
Not So Much
Not So Much
Paste entire function to new “up” script
Not So Much
Paste entire function to new “up” script

Edit the new file
Not So Much
Paste entire function to new “up” script

Edit the new file

Copy the function to the new “down” script
Not So Much
Paste entire function to new “up” script

Edit the new file

Copy the function to the new “down” script

Three copies of the function!
Not So Much
Paste entire function to new “up” script

Edit the new file

Copy the function to the new “down” script

Three copies of the function!

No real source code management
Not So Much
Paste entire function to new “up” script

Edit the new file

Copy the function to the new “down” script

Three copies of the function!

No real source code management

This sucks
What about Liquibase?




filename
What about Liquibase?
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
 xmlns="http://www.liquibase.org/xml/ns/dbchangelog/1.6"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog/1.6
      http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-1.6.xsd">
 <changeSet id="1" author="me">
  <createTable tableName="first_table">
   <column name="id" type="int">
     <constraints primaryKey="true" nullable="false"/>
   </column>
   <column name="name" type="varchar(50)">
     <constraints nullable="false"/>
   </column>
  </createTable>
  <createTable tableName="new_table">
   <column name="id" type="int">
     <constraints primaryKey="true" nullable="false"/>
   </column>
  </createTable>
 </changeSet>
</databaseChangeLog>
  filename
What about Liquibase?
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
 xmlns="http://www.liquibase.org/xml/ns/dbchangelog/1.6"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog/1.6
      http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-1.6.xsd">
 <changeSet id="1" author="me">
  <createTable tableName="first_table">
   <column name="id" type="int">
     <constraints primaryKey="true" nullable="false"/>
   </column>
   <column name="name" type="varchar(50)">



                                        Whaaaa?
     <constraints nullable="false"/>
   </column>
  </createTable>
  <createTable tableName="new_table">
   <column name="id" type="int">
     <constraints primaryKey="true" nullable="false"/>
   </column>
  </createTable>
 </changeSet>
</databaseChangeLog>
  filename
What about Liquibase?
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
 xmlns="http://www.liquibase.org/xml/ns/dbchangelog/1.6"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog/1.6
      http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-1.6.xsd">
 <changeSet id="1" author="me">
  <createTable tableName="first_table">
   <column name="id" type="int">
     <constraints primaryKey="true" nullable="false"/>
   </column>
   <column name="name" type="varchar(50)">



                                        Whaaaa?
     <constraints nullable="false"/>
   </column>
  </createTable>
  <createTable tableName="new_table">
   <column name="id" type="int">
     <constraints primaryKey="true" nullable="false"/>



                                          GTFO!
   </column>
  </createTable>
 </changeSet>
</databaseChangeLog>
  filename
depesz’s Versioning?
depesz’s Versioning?
https:/
      /github.com/depesz/versioning
depesz’s Versioning?
https:/
      /github.com/depesz/versioning

Nice dependency specification
depesz’s Versioning?
https:/
      /github.com/depesz/versioning

Nice dependency specification

Tight PostgreSQL integration
depesz’s Versioning?
https:/
      /github.com/depesz/versioning

Nice dependency specification

Tight PostgreSQL integration

No VCS integration
depesz’s Versioning?
https:/
      /github.com/depesz/versioning

Nice dependency specification

Tight PostgreSQL integration

No VCS integration

No tools
depesz’s Versioning?
https:/
      /github.com/depesz/versioning

Nice dependency specification

Tight PostgreSQL integration

No VCS integration

No tools

Managing procedures still a PITA
Introducing
   Sqitch
Sq—what?


SQL ch anges
Sq—what?


SQ ch
Sq—what?


SQitch
Sq—what?


SQitch


 There is no “u”
Sqitch Philosophy
Sqitch Philosophy
No opinions
Sqitch Philosophy
No opinions

Native scripting
Sqitch Philosophy
No opinions

Native scripting

VCS integration
Sqitch Philosophy
No opinions

Native scripting

VCS integration

Dependency resolution
Sqitch Philosophy
No opinions

Native scripting

VCS integration

Dependency resolution

No numbering
Sqitch Philosophy
No opinions

Native scripting

VCS integration

Dependency resolution

No numbering

Distribution bundling
Sqitch Philosophy
Sqitch Philosophy
Reduced duplication
Sqitch Philosophy
Reduced duplication

Built-in configuration
Sqitch Philosophy
Reduced duplication

Built-in configuration

Deployment planning
Sqitch Philosophy
Reduced duplication

Built-in configuration

Deployment planning

Git-style interface
Sqitch Philosophy
Reduced duplication

Built-in configuration

Deployment planning

Git-style interface

Deployment tagging
Sqitch Terminology
Sqitch Terminology
step
Sqitch Terminology
step

tag
Sqitch Terminology
step

tag

plan
Sqitch Terminology
step

tag

plan

deploy
Sqitch Terminology
step

tag

plan

deploy

revert
Caveats
Caveats
Caveats
Under heavy development
Caveats
Under heavy development

v0.30 Testing release today
Caveats
Under heavy development

v0.30 Testing release today

Functionality rapidly evolving
Caveats
Under heavy development

v0.30 Testing release today

Functionality rapidly evolving

Some gaps still to be filled in
Caveats
Under heavy development

v0.30 Testing release today

Functionality rapidly evolving

Some gaps still to be filled in

VCS integration in flux
How it Works
>
How it Works
>mkdir flipr
> cd flipr
> git init .
Initialized empty Git repository in /flipr/.git/
> touch README.md
> git add .
> git commit -am 'Fist post!'

>
How it Works
>mkdir flipr
> cd flipr
> git init .
Initialized empty Git repository in /flipr/.git/
> touch README.md
> git add .
> git commit -am 'Fist post!'

>sqitch --engine pg init
Created sql/deploy
Created sql/revert
Created sql/test
Created sqitch.conf
>
How it Works
>mkdir flipr
> cd flipr
> git init .
Initialized empty Git repository in /flipr/.git/
> touch README.md
> git add .
> git commit -am 'Fist post!'

>sqitch --engine pg init
Created sql/deploy
Created sql/revert
Created sql/test
Created sqitch.conf
>emacs sqitch.conf
sqitch.conf
[core]

   engine = pg

   # plan_file = sqitch.plan

   # sql_dir = sql

   # deploy_dir = sql/deploy

   # revert_dir = sql/revert

   # test_dir = sql/test

   # extension = sql
# [core "pg"]

   # db_name =

   # client = psql

   # sqitch_schema = sqitch

   # password =

   # port =

   # host =

   # username =
  sqitch.conf
sqitch.conf
[core]


    engine = pg
                       --engine pg
    # plan_file = sqitch.plan

   # sql_dir = sql

   # deploy_dir = sql/deploy

   # revert_dir = sql/revert

   # test_dir = sql/test

   # extension = sql
# [core "pg"]

   # db_name =

   # client = psql

   # sqitch_schema = sqitch

   # password =

   # port =

   # host =

   # username =
  sqitch.conf
Add User Config
>
Add User Config
>sqitch config --user core.pg.client /var/lib/pgsql/bin/
psql
>
Add User Config
>sqitch config --user core.pg.client /var/lib/pgsql/bin/
psql
>
Add User Config
>sqitch config --user core.pg.client /var/lib/pgsql/bin/
psql
>emacs ~/.sqitch/sqitch.conf
~/
          .sqitch/sqitch.conf
[core "pg"]

   client = /var/lib/pgsql/bin/psql




  ~/.sqitch/sqitc
~/
          .sqitch/sqitch.conf
[core "pg"]

   client = /var/lib/pgsql/bin/psql




                    Good for
                    all projects
  ~/.sqitch/sqitc
Make It So
>
Make It So
>git add .
> git commit -am 'Initialize Sqitch configuration.'
[master (root-commit) a22000d] Initialize Sqitch
configuration.
 1 file changed, 16 insertions(+)
 create mode 100644 sqitch.conf
>
First Deployment
>
First Deployment
> sqitch add-step appuser
Created sql/deploy/appuser.sql
Created sql/revert/appuser.sql
Created sql/test/appuser.sql
>
First Deployment
> sqitch add-step appuser
Created sql/deploy/appuser.sql
Created sql/revert/appuser.sql
Created sql/test/appuser.sql
>
First Deployment
> sqitch add-step appuser
Created sql/deploy/appuser.sql
Created sql/revert/appuser.sql
Created sql/test/appuser.sql
>emacs sql/deploy/appuser.sql
sql/deploy/appuser.sql
-- Deploy appuser

BEGIN;

-- XXX Add DDLs here.

COMMIT;




  sql/deploy/appu
sql/deploy/appuser.sql
-- Deploy appuser

BEGIN;

CREATE ROLE flipr WITH LOGIN;

COMMIT;




  sql/deploy/appu
First Deployment
> sqitch add-step appuser
Created sql/deploy/appuser.sql
Created sql/revert/appuser.sql
Created sql/test/appuser.sql
> emacs sql/deploy/appuser.sql
>
First Deployment
> sqitch add-step appuser
Created sql/deploy/appuser.sql
Created sql/revert/appuser.sql
Created sql/test/appuser.sql
> emacs sql/deploy/appuser.sql
>emacs sql/revert/appuser.sql
sql/revert/appuser.sql
-- Revert appuser

BEGIN;

-- XXX Add DDLs here.

COMMIT;




  sql/deploy/appu
sql/revert/appuser.sql
-- Revert appuser

BEGIN;

DROP ROLE flipr;

COMMIT;




  sql/deploy/appu
Make it So!
>
Make it So!
>createdb flipr_test
> sqitch --db-name flipr_test deploy --untracked
Adding metadata tables to flipr_test
Deploying HEAD+ to flipr_test
 + appuser
>
Make it So!
>createdb flipr_test
> sqitch --db-name flipr_test deploy --untracked
Adding metadata tables to flipr_test
Deploying HEAD+ to flipr_test
 + appuser
>
Make it So!
>createdb flipr_test
> sqitch --db-name flipr_test deploy --untracked
Adding metadata tables to flipr_test
Deploying HEAD+ to flipr_test
 + appuser
>
Make it So!
>createdb flipr_test
> sqitch --db-name flipr_test deploy --untracked
Adding metadata tables to flipr_test
Deploying HEAD+ to flipr_test
 + appuser
>
Make it So!
>createdb flipr_test
> sqitch --db-name flipr_test deploy --untracked
Adding metadata tables to flipr_test
Deploying HEAD+ to flipr_test
  + appuser
>psql -d flipr_test -c 'du flipr'
       List of roles
 Role name | Attributes | Member of
-----------+------------+-----------
 flipr   |         | {}
>
How’s it Look?
>
How’s it Look?
> sqitch -d flipr_test status
# On database flipr_test
# Tag: HEAD+
# Step: appuser
# Date: 2012-05-18 17:15:23
#
Nothing to deploy (up-to-date)
>
How’s it Look?
> sqitch -d flipr_test status
# On database flipr_test
# Tag: HEAD+
# Step: appuser
# Date: 2012-05-18 17:15:23
#
Nothing to deploy (up-to-date)
>
How’s it Look?
> sqitch -d flipr_test status
# On database flipr_test
# Tag: HEAD+
# Step: appuser
# Date: 2012-05-18 17:15:23
#
Nothing to deploy (up-to-date)
>
How’s it Look?
> sqitch -d flipr_test status
# On database flipr_test
# Tag: HEAD+
# Step: appuser
# Date: 2012-05-18 17:15:23
#
Nothing to deploy (up-to-date)
>


                                 Proposed
Go Back
>
Go Back
>sqitch --db-name flipr_test revert
Reverting all changes from flipr_test
 - appuser
>
Go Back
>sqitch --db-name flipr_test revert
Reverting all changes from flipr_test
 - appuser
>
Go Back
>sqitch --db-name flipr_test revert
Reverting all changes from flipr_test
 - appuser
>
Go Back
>sqitch --db-name flipr_test revert
Reverting all changes from flipr_test
  - appuser
>psql -d flipr_test -c 'du flipr'
        List of roles
 Role name | Attributes | Member of
-----------+------------+-----------

>
What’s The Status?
>
What’s The Status?
>sqitch -d flipr_test status --untracked
# On database flipr_test
# Nothing deployed.
#
# Changes not deployed:
# * HEAD+
# appuser
#
Use "sqitch deploy --untracked" to deploy these
changes
>
What’s The Status?
>sqitch -d flipr_test status --untracked
# On database flipr_test
# Nothing deployed.
#
# Changes not deployed:
# * HEAD+
# appuser
#
Use "sqitch deploy --untracked" to deploy these
changes
>
History
>
History
>sqitch -d flipr_test log
step appuser reverted
By: david
Date: 2012-05-18 17:15:23
Tag: HEAD+

step appuser deployed
By: david
Date: 2012-05-18 17:18:12
Tag: HEAD+
>
History
>sqitch -d flipr_test log
step appuser reverted
By: david
Date: 2012-05-18 17:15:23
Tag: HEAD+

step appuser deployed
By: david
Date: 2012-05-18 17:18:12
Tag: HEAD+
>
History
>sqitch -d flipr_test log
step appuser reverted
By: david
Date: 2012-05-18 17:15:23
Tag: HEAD+

step appuser deployed
By: david
Date: 2012-05-18 17:18:12
Tag: HEAD+
>
Commit It!
>
Commit It!
>git add .
> git commit -m 'Add app user.'
[master 36acafd] Add app user.
 2 files changed, 2 insertions(+)
 create mode 100644 sql/deploy/appuser.sql
 create mode 100644 sql/revert/appuser.sql
 create mode 100644 sql/test/appuser.sql
>
Commit It!
>git add .
> git commit -m 'Add app user.'
[master 36acafd] Add app user.
 2 files changed, 2 insertions(+)
 create mode 100644 sql/deploy/appuser.sql
 create mode 100644 sql/revert/appuser.sql
 create mode 100644 sql/test/appuser.sql
>sqitch --db-name flipr_test deploy
Deploying 36acafd to flipr_test
  + appuser
>
Commit It!
>git add .
> git commit -m 'Add app user.'
[master 36acafd] Add app user.
 2 files changed, 2 insertions(+)
 create mode 100644 sql/deploy/appuser.sql
 create mode 100644 sql/revert/appuser.sql
 create mode 100644 sql/test/appuser.sql
>sqitch --db-name flipr_test deploy
Deploying 36acafd to flipr_test
  + appuser
>
Commit It!
>git add .
> git commit -m 'Add app user.'
[master 36acafd] Add app user.
 2 files changed, 2 insertions(+)
 create mode 100644 sql/deploy/appuser.sql
 create mode 100644 sql/revert/appuser.sql
 create mode 100644 sql/test/appuser.sql
>sqitch --db-name flipr_test deploy
Deploying 36acafd to flipr_test
  + appuser
>psql -d flipr_test -c 'du flipr'
        List of roles
 Role name | Attributes | Member of
-----------+------------+-----------
 flipr    |         | {}
Status Update
>
Status Update
> sqitch -d flipr_test status
# On database flipr_test
# Tag: 36acafd
# Step: appuser
# Date: 2012-05-18 17:21:54
#
Nothing to deploy (up-to-date)
>
Save My Fingers
>
Save My Fingers
>sqitch config core.pg.db_name flipr_test
>
Save My Fingers
>sqitch config core.pg.db_name flipr_test
>sqitch status
# On database flipr_test
# Tag: 36acafd                   No --db-name
# Step: appuser
# Date: 2012-05-18 17:21:54
#
Nothing to deploy (up-to-date)
>
Dependencies!
>
Dependencies!
> sqitch add-step users --requires appuser
Created sql/deploy/users.sql
      -- requires: appuser
Created sql/revert/users.sql
Created sql/test/users.sql
>
Dependencies!
> sqitch add-step users --requires appuser
Created sql/deploy/users.sql
      -- requires: appuser
Created sql/revert/users.sql
Created sql/test/users.sql
>
Dependencies!
> sqitch add-step users --requires appuser
Created sql/deploy/users.sql
      -- requires: appuser
Created sql/revert/users.sql
Created sql/test/users.sql
>emacs sql/deploy/users.sql
sql/deploy/users.sql
-- Deploy users
-- :requires: appuser

BEGIN;

-- XXX Add DDLs here.

COMMIT;




  sql/deploy/user
sql/deploy/users.sql
-- Deploy users
-- :requires: appuser

BEGIN;

-- XXX Add DDLs here.

COMMIT;




  sql/deploy/user
sql/deploy/users.sql
-- Deploy users
-- :requires: appuser

BEGIN;

CREATE TABLE users (
   nickname TEXT     PRIMARY KEY,
   password TEXT     NOT NULL,
   timestamp TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

GRANT SELECT ON users TO flipr;
COMMIT;



  sql/deploy/user
Dependencies!
> sqitch add-step users --requires appuser
Created sql/deploy/users.sql
      -- requires: appuser
Created sql/revert/users.sql
Created sql/test/users.sql
> emacs sql/deploy/users.sql
>
Dependencies!
> sqitch add-step users --requires appuser
Created sql/deploy/users.sql
      -- requires: appuser
Created sql/revert/users.sql
Created sql/test/users.sql
> emacs sql/deploy/users.sql
>emacs sql/revert/users.sql
sql/revert/users
-- Revert users

BEGIN;

-- XXX Add DDLs here.

COMMIT;




  sql/deploy/user
sql/revert/users
-- Revert users

BEGIN;

DROP TABLE users;

COMMIT;




  sql/deploy/user
Make Users
>
Make Users
>sqitch deploy --untracked
Deploying HEAD+ to flipr_test
 + users
>
Make Users
>sqitch deploy --untracked
Deploying HEAD+ to flipr_test
 + users
>
Make Users
>sqitch deploy --untracked
Deploying HEAD+ to flipr_test
  + users
> psql -d flipr_test -c 'd users'
             Table "public.users"
  Column |     Type |       Modifiers
-----------+-------------+------------------------
 nickname | text      | not null
 password | text      | not null
 timestamp | timestamptz | not null default now()
Indexes:
   "users_pkey" PRIMARY KEY, btree (nickname)
>
Status Update

>
Status Update

> sqitch status
# On database flipr_test
# Tag: HEAD+
# Step: users
# Date: 2012-05-18 17:25:39
#
Nothing to deploy (up-to-date)
>
Status Update

> sqitch status
# On database flipr_test
# Tag: HEAD+
# Step: users
# Date: 2012-05-18 17:25:39
#
Nothing to deploy (up-to-date)
>sqitch revert --to HEAD
Reverting HEAD+ from flipr_test
  - users
>
Status Update

> sqitch status
# On database flipr_test
# Tag: HEAD+
# Step: users
# Date: 2012-05-18 17:25:39
#
Nothing to deploy (up-to-date)
>sqitch revert --to HEAD
Reverting HEAD+ from flipr_test
  - users
>
Check in and Deploy
>
Check in and Deploy
>git add .
> git commit -am 'Add users table.'
[master fa650af] Add users table.
 2 files changed, 16 insertions(+)
 create mode 100644 sql/deploy/users.sql
 create mode 100644 sql/revert/users.sql
 create mode 100644 sql/test/users.sql
>
Check in and Deploy
>git add .
> git commit -am 'Add users table.'
[master fa650af] Add users table.
 2 files changed, 16 insertions(+)
 create mode 100644 sql/deploy/users.sql
 create mode 100644 sql/revert/users.sql
 create mode 100644 sql/test/users.sql
>sqitch deploy
Deploying fa650af to flipr_test
  + users
>
Up to Date
>
Up to Date
> sqitch status --show tags
# On database flipr_test
# Tag: fa650af
# Step: users
# Date: 2012-05-18 17:31:23
#
# Tags:
# fa650af - 2012-05-18 17:31:23 - david
# 36acafd - 2012-05-18 17:25:39 - david
#
Nothing to deploy (up-to-date)
>
Up to Date
> sqitch status --show tags
# On database flipr_test
# Tag: fa650af
# Step: users
# Date: 2012-05-18 17:31:23
#
# Tags:
# fa650af - 2012-05-18 17:31:23 - david
# 36acafd - 2012-05-18 17:25:39 - david
#
Nothing to deploy (up-to-date)
>
Up to Date
> sqitch status --show tags
# On database flipr_test
# Tag: fa650af
# Step: users
# Date: 2012-05-18 17:31:23
#
# Tags:
# fa650af - 2012-05-18 17:31:23 - david
# 36acafd - 2012-05-18 17:25:39 - david
#
Nothing to deploy (up-to-date)
>
A Twofer
>
A Twofer
>sqitch add-step insert_user -r users -r appuser
Adding sql/deploy/insert_user.sql
    -- requires: users, appuser
Adding sql/revert/insert_user.sql
Adding sql/test/insert_user.sql

>
A Twofer
>sqitch add-step insert_user -r users -r appuser
Adding sql/deploy/insert_user.sql
    -- requires: users, appuser
Adding sql/revert/insert_user.sql
Adding sql/test/insert_user.sql

>
A Twofer
>sqitch add-step insert_user -r users -r appuser
Adding sql/deploy/insert_user.sql
    -- requires: users, appuser
Adding sql/revert/insert_user.sql
Adding sql/test/insert_user.sql

> sqitch add-step change_pass -r users -r appuser
Adding sql/deploy/change_pass.sql
    -- requires: users, appuser
Adding sql/revert/change_pass.sql
Adding sql/test/change_pass.sql

>
A Twofer
>sqitch add-step insert_user -r users -r appuser
Adding sql/deploy/insert_user.sql
    -- requires: users, appuser
Adding sql/revert/insert_user.sql
Adding sql/test/insert_user.sql

> sqitch add-step change_pass -r users -r appuser
Adding sql/deploy/change_pass.sql
    -- requires: users, appuser
Adding sql/revert/change_pass.sql
Adding sql/test/change_pass.sql

>
A Twofer
>sqitch add-step insert_user -r users -r appuser
Adding sql/deploy/insert_user.sql
    -- requires: users, appuser
Adding sql/revert/insert_user.sql
Adding sql/test/insert_user.sql

> sqitch add-step change_pass -r users -r appuser
Adding sql/deploy/change_pass.sql
    -- requires: users, appuser
Adding sql/revert/change_pass.sql
Adding sql/test/change_pass.sql

>emacs sql/deploy/insert_user.sql
sql/deploy/
                    insert_user.sql
-- Deploy insert_user
-- :requires: appuser
-- :requires: users

BEGIN;

-- XXX Add DDLs here.

COMMIT;




  sql/deploy/inse
sql/deploy/
                    insert_user.sql
-- Deploy insert_user
-- :requires: appuser
-- :requires: users

BEGIN;

-- XXX Add DDLs here.

COMMIT;




  sql/deploy/inse
sql/deploy/
                    insert_user.sql
-- Deploy insert_user
-- :requires: appuser
-- :requires: users

BEGIN;

CREATE OR REPLACE FUNCTION insert_user(
   nickname TEXT,
   password TEXT
) RETURNS VOID LANGUAGE SQL SECURITY DEFINER AS $$
   INSERT INTO users VALUES($1, md5($2));
$$;

GRANT EXECUTE ON FUNCTION insert_user(TEXT, TEXT) TO flipr;

COMMIT;
  sql/deploy/inse
A Twofer
>sqitch add-step insert_user -r users -r appuser
Adding sql/deploy/insert_user.sql
    -- requires: users, appuser
Adding sql/revert/insert_user.sql
Adding sql/test/insert_user.sql

> sqitch add-step change_pass -r users -r appuser
Adding sql/deploy/change_pass.sql
    -- requires: users, appuser
Adding sql/revert/change_pass.sql
Adding sql/test/change_pass.sql

>emacs sql/deploy/insert_user.sql
>
A Twofer
>sqitch add-step insert_user -r users -r appuser
Adding sql/deploy/insert_user.sql
    -- requires: users, appuser
Adding sql/revert/insert_user.sql
Adding sql/test/insert_user.sql

> sqitch add-step change_pass -r users -r appuser
Adding sql/deploy/change_pass.sql
    -- requires: users, appuser
Adding sql/revert/change_pass.sql
Adding sql/test/change_pass.sql

>emacs sql/deploy/insert_user.sql
>emacs sql/deploy/change_pass.sql
sql/deploy/
                   change_pass.sql
-- Deploy change_pass
-- :requires: appuser
-- :requires: users
BEGIN;

-- XXX Add DDLs here.

COMMIT;




 sql/deploy/chan
sql/deploy/
                   change_pass.sql
-- Deploy change_pass
-- :requires: appuser
-- :requires: users
BEGIN;
CREATE OR REPLACE FUNCTION change_pass(
    nick TEXT, oldpass TEXT, newpass TEXT
) RETURNS BOOLEAN LANGUAGE plpgsql SECURITY DEFINER AS $$
BEGIN
   UPDATE users SET password = md5($3)
    WHERE nickname = $1 AND password = md5($2);
   RETURN FOUND;
END;
$$;
GRANT EXECUTE ON FUNCTION change_pass(TEXT, TEXT, TEXT)
TO flipr;
COMMIT;
 sql/deploy/chan
Deploy Functions
>
Deploy Functions
>sqitch deploy --untracked
Deploying HEAD+ to flipr_test
 + change_pass
 + insert_user
>
Deploy Functions
>sqitch deploy --untracked
Deploying HEAD+ to flipr_test
  + change_pass
  + insert_user
>psql -d flipr_test -c 'df'
                          List of function
 Schema | Name         | Result data type |
--------+-------------+------------------+----------
 public | change_pass | boolean           | nick text
 public | insert_user | void          | nickname
>
Commit It
Commit It
sqitch revert --to HEAD
Commit It
sqitch revert --to HEAD

git add && git commit
Commit It
sqitch revert --to HEAD

git add && git commit

sqitch deploy
Commit It
sqitch revert --to HEAD

git add && git commit

sqitch deploy

And now…
Stage It
>
Stage It
>git tag v1.0.0-dev1 -am 'Tag v1.0.0-dev1'
>
Stage It
>git tag v1.0.0-dev1 -am 'Tag v1.0.0-dev1'
>createdb flipr_dev
> sqitch --db-name flipr_dev deploy
Deploying 36acafd to flipr_dev
 + appuser
Deploying fa650af to flipr_dev
 + users
Deploying 803e6b8, v1.0.0-dev1 to flipr_dev
 + insert_user
 + change_pass
>
Stage It
>git tag v1.0.0-dev1 -am 'Tag v1.0.0-dev1'
>createdb flipr_dev
> sqitch --db-name flipr_dev deploy
Deploying 36acafd to flipr_dev
 + appuser
Deploying fa650af to flipr_dev
 + users
Deploying 803e6b8, v1.0.0-dev1 to flipr_dev
 + insert_user
 + change_pass
>
Stage It
>git tag v1.0.0-dev1 -am 'Tag v1.0.0-dev1'
>createdb flipr_dev
> sqitch --db-name flipr_dev deploy
Deploying 36acafd to flipr_dev
 + appuser
Deploying fa650af to flipr_dev
 + users
Deploying 803e6b8, v1.0.0-dev1 to flipr_dev
 + insert_user
 + change_pass
>
Stage Status?
>
Stage Status?
>sqitch --db-name flipr_dev status --show tags
# On database flipr_dev
# Tags: 803e6b8, v1.0.0-dev1
# Step: change_pass
# Date: 2012-05-18 17:38:28
#
# Tags:
# 803e6b8, v1.0.0-dev1 - 2012-05-18 17:38:28 - david
# fa650af           - 2012-05-18 17:38:21 - david
# 36acafd           - 2012-05-18 17:38:15 - david
#
Nothing to deploy (up-to-date)
>
Distribution Bundling
Distribution Bundling
Bundle plan + scripts for deployment
Distribution Bundling
Bundle plan + scripts for deployment

Plan generated from VCS history
Distribution Bundling
Bundle plan + scripts for deployment

Plan generated from VCS history

Package up as
Distribution Bundling
Bundle plan + scripts for deployment

Plan generated from VCS history

Package up as

  RPM
Distribution Bundling
Bundle plan + scripts for deployment

Plan generated from VCS history

Package up as

  RPM

  Debian Package
Distribution Bundling
Bundle plan + scripts for deployment

Plan generated from VCS history

Package up as

  RPM

  Debian Package

  Gem
Ship It!
>
Ship It!
>sqitch bundle --tags-only
Bundling in bundle/
Config written to bundle/sqitch.conf
Bundling v1.0.0-dev1
 - appuser
 - users
 - change_pass
 - insert_user
Plan written to bundle/sqitch.plan
>
Ship It!
>sqitch bundle --tags-only
Bundling in bundle/
Config written to bundle/sqitch.conf
Bundling v1.0.0-dev1
 - appuser
 - users
 - change_pass
 - insert_user
Plan written to bundle/sqitch.plan
>
Ship It!
>sqitch bundle --tags-only
Bundling in bundle/
Config written to bundle/sqitch.conf
Bundling v1.0.0-dev1
 - appuser
 - users
 - change_pass
 - insert_user
Plan written to bundle/sqitch.plan
>
Ship It!
>sqitch bundle --tags-only
Bundling in bundle/
Config written to bundle/sqitch.conf
Bundling v1.0.0-dev1
 - appuser
 - users
 - change_pass
 - insert_user
Plan written to bundle/sqitch.plan
>
Ship It!
>sqitch bundle --tags-only
Bundling in bundle/
Config written to bundle/sqitch.conf
Bundling v1.0.0-dev1
 - appuser
 - users
 - change_pass
 - insert_user
Plan written to bundle/sqitch.plan
>emacs bundle/sqitch.plan
The Plan, Man
[v1.0.0-dev1]
appuser
users
change_pass
insert_user




  bundle/sqitch.p
Kick the Tires
>
Kick the Tires
>cd bundle
> createdb flipr_staging
> sqitch --db-name flipr_staging deploy
Deploying v1.0.0-dev1 to flipr_prod
 + appuser
 + users
 + insert_user
 + change_pass
>
Kick the Tires
>cd bundle
> createdb flipr_staging
> sqitch --db-name flipr_staging deploy
Deploying v1.0.0-dev1 to flipr_prod
 + appuser
 + users
 + insert_user
 + change_pass
>
Ch-Check it Out
>
Ch-Check it Out
>sqitch --db-name flipr_prod status --show tags
# On database flipr_prod
# Tag: v1.0.0-dev1
# Step: change_pass
# Date: 2012-04-09 22:17:38
#
# Tags:
# v1.0.0-dev1 - 2012-05-18 17:40:00 - david
#
Nothing to deploy (up-to-date)
>
Ch-Check it Out
>sqitch --db-name flipr_prod status --show tags
# On database flipr_prod
# Tag: v1.0.0-dev1
# Step: change_pass              No SHA1s
# Date: 2012-04-09 22:17:38
#
# Tags:
# v1.0.0-dev1 - 2012-05-18 17:40:00 - david
#
Nothing to deploy (up-to-date)
>
Ruh-Roh
>
Ruh-Roh
>psql -d flipr_test -c "
   SELECT insert_user('foo', 'secr3t'),
       insert_user('bar', 'secr3t');
   SELECT nickname, password FROM users;
"
 nickname |          password
----------+----------------------------------
 foo    | 9695da4dd567a19f9b92065f240c6725
 bar    | 9695da4dd567a19f9b92065f240c6725
Ruh-Roh
>psql -d flipr_test -c "
   SELECT insert_user('foo', 'secr3t'),
       insert_user('bar', 'secr3t');
   SELECT nickname, password FROM users;
"
 nickname |          password
----------+----------------------------------
 foo    | 9695da4dd567a19f9b92065f240c6725
 bar    | 9695da4dd567a19f9b92065f240c6725




                       Not good.
Add pgcrypto
>
Add pgcrypto
>sqitch add-step pgcrypto
Adding sql/deploy/pgcrypto.sql
Adding sql/revert/pgcrypto.sql
Adding sql/test/pgcrypto.sql
>
Add pgcrypto
>sqitch add-step pgcrypto
Adding sql/deploy/pgcrypto.sql
Adding sql/revert/pgcrypto.sql
Adding sql/test/pgcrypto.sql
>emacs sql/deploy/pgcrpyto.sql
ssql/deploy/pgcrypto.sql
-- Deploy pgcrypto

BEGIN;

-- XXX Add DDLs here.

COMMIT;




  sql/deploy/pgcr
ssql/deploy/pgcrypto.sql
-- Deploy pgcrypto

BEGIN;

CREATE EXTENSION pgcrypto;

COMMIT;




  sql/deploy/pgcr
How to Modify?
How to Modify?
Copy insert_user.sql to new deploy file
How to Modify?
Copy insert_user.sql to new deploy file

Change that new file
How to Modify?
Copy insert_user.sql to new deploy file

Change that new file

Copy insert_user.sql to new revert file
How to Modify?
Copy insert_user.sql to new deploy file

Change that new file

Copy insert_user.sql to new revert file

Test it
How to Modify?
Copy insert_user.sql to new deploy file

Change that new file

Copy insert_user.sql to new revert file

Test it

Do the same for change_pass.sql
How to Modify?
Copy insert_user.sql to new deploy file

Change that new file

Copy insert_user.sql to new revert file

Test it

Do the same for change_pass.sql

The problem with that…
>
> git diff HEAD^
diff --git a/sql/deploy/insert_user_crypt.sql b/sql/deploy/insert_user_cr
new file mode 100644
index 0000000..fa8d0c6
--- /dev/null
+++ b/sql/deploy/insert_user_crypt.sql
@@ -0,0 +1,8 @@
+-- requires: users, appuser, pgcrypto
+
+CREATE OR REPLACE FUNCTION insert_user(
+ nickname TEXT,
+ password TEXT
+) RETURNS VOID LANGUAGE SQL AS $$
+ INSERT INTO users values($1, crypt($2, gen_salt('md5')));
+$$;
diff --git a/sql/revert/insert_user_crypt.sql b/sql/revert/insert_user_cr
new file mode 100644
index 0000000..a7f4e31
--- /dev/null
+++ b/sql/revert/insert_user_crypt.sql
@@ -0,0 +1,8 @@
+-- requires: users, appuser
+
+CREATE OR REPLACE FUNCTION insert_user(
+ nickname TEXT,
+ password TEXT
+) RETURNS VOID LANGUAGE SQL AS $$
+ INSERT INTO users values($1, md5($2));
+$$;
> git diff HEAD^
diff --git a/sql/deploy/insert_user_crypt.sql b/sql/deploy/insert_user_cr
new file mode 100644
index 0000000..fa8d0c6
--- /dev/null
+++ b/sql/deploy/insert_user_crypt.sql
@@ -0,0 +1,8 @@
+-- requires: users, appuser, pgcrypto
+
+CREATE OR REPLACE FUNCTION insert_user(
+ nickname TEXT,
+ password TEXT
+) RETURNS VOID LANGUAGE SQL AS $$
+ INSERT INTO users values($1, crypt($2, gen_salt('md5')));
+$$;
diff --git a/sql/revert/insert_user_crypt.sql b/sql/revert/insert_user_cr
new file mode 100644
index 0000000..a7f4e31
--- /dev/null
+++ b/sql/revert/insert_user_crypt.sql
@@ -0,0 +1,8 @@
+-- requires: users, appuser
+
+CREATE OR REPLACE FUNCTION insert_user(
+ nickname TEXT,
+ password TEXT
+) RETURNS VOID LANGUAGE SQL AS $$
+ INSERT INTO users values($1, md5($2));
+$$;                                                              Oy.
Use the VCS, Luke
Use the VCS, Luke
Just modify deploy scripts directly
Use the VCS, Luke
Just modify deploy scripts directly

Requirement:
Use the VCS, Luke
Just modify deploy scripts directly

Requirement:

  Change must be idempotent
Use the VCS, Luke
Just modify deploy scripts directly

Requirement:

  Change must be idempotent

  Same result no matter how often applied
Use the VCS, Luke
Just modify deploy scripts directly

Requirement:

  Change must be idempotent

  Same result no matter how often applied

CREATE OR REPLACE FUNCTION is idempotent
Use the VCS, Luke
Just modify deploy scripts directly

Requirement:

  Change must be idempotent

  Same result no matter how often applied

CREATE OR REPLACE FUNCTION is idempotent

So change procedures in place!
What’s the Diff?
>
What’s the Diff?
>diff -u sql/deploy/insert_user.sql
@@ -1,8 +1,8 @@
--- requires: users, appuser
+-- requires: users, appuser, pgcrypto

 CREATE OR REPLACE FUNCTION insert_user(
    nickname TEXT,
    password TEXT
 ) RETURNS VOID LANGUAGE SQL AS $$
- INSERT INTO users values($1, md5($2));
+ INSERT INTO users values($1, crypt($2, gen_salt('md5')));
 $$;
What’s the Diff?
>
What’s the Diff?
>diff -u sql/deploy/change_pass.sql
@@ -1,4 +1,4 @@
--- requires: users, appuser
+-- requires: users, appuser, pgcrypto

 CREATE OR REPLACE FUNCTION change_pass(
    nick TEXT,
@@ -7,9 +7,9 @@ CREATE OR REPLACE FUNCTION change_pass(
 ) RETURNS BOOLEAN LANGUAGE plpgsql AS $$
 BEGIN
    UPDATE users
-      SET password = md5($3)
+      SET password = crypt($3, gen_salt('md5'))
     WHERE nickname = $1
-      AND password = md5($2);
+      AND password = crypt($2, password);
    RETURN FOUND;
 END;
Send it Up!
>
Send it Up!
>sqitch deploy --untracked
Deploying HEAD+ to flipr_test
 + insert_user
 + change_pass
>
Send it Up!
>sqitch deploy --untracked
Deploying HEAD+ to flipr_test
  + insert_user
  + change_pass
>psql -d flipr_test -c "
   DELETE FROM users;
   SELECT insert_user('foo', 'secr3t'),
        insert_user('bar', 'secr3t');
   SELECT nickname, password FROM users;
"
 nickname |           password
----------+------------------------------------
 foo     | $1$l6OEKyF3$kv5ae7505ROub75d9QKTh/
 bar     | $1$J4NJDgaJ$578i9Lt6b8ohJwi6WhNNO1
>
Send it Up!
>sqitch deploy --untracked
Deploying HEAD+ to flipr_test
  + insert_user
  + change_pass
>psql -d flipr_test -c "
                                   o/
   DELETE FROM users;
   SELECT insert_user('foo', 'secr3t'),
        insert_user('bar', 'secr3t');
   SELECT nickname, password FROM users;
"
 nickname |           password
----------+------------------------------------
 foo     | $1$l6OEKyF3$kv5ae7505ROub75d9QKTh/
 bar     | $1$J4NJDgaJ$578i9Lt6b8ohJwi6WhNNO1
>
Can We Go Back?
>
Can We Go Back?
>sqitch revert --to HEAD
Reverting HEAD+ from flipr_test
 - change_pass
 - insert_user
>
Can We Go Back?
>sqitch revert --to HEAD
Reverting HEAD+ from flipr_test
  - change_pass
  - insert_user
>psql -d flipr_test -c "
   DELETE FROM users;
   SELECT insert_user('foo', 'secr3t'),
        insert_user('bar', 'secr3t');
   SELECT nickname, password FROM users;
"
 nickname |           password
----------+----------------------------------
 foo     | 9695da4dd567a19f9b92065f240c6725
 bar     | 9695da4dd567a19f9b92065f240c6725
>
What About Bundling?
>
What About Bundling?
> git tag v1.0.0-b1 -am 'Tag v1.0.0-b1'
> sqitch bundle --tags-only
Bundling in bundle/
Config written to bundle/sqitch.conf
Bundling v1.0.0-dev1
 - appuser
 - users
 - change_pass
 - insert_user
Bundling v1.0.0-b1
 - change_pass_v2
 - insert_user_v2
Plan written to bundle/sqitch.plan
>
What About Bundling?
> git tag v1.0.0-b1 -am 'Tag v1.0.0-b1'
> sqitch bundle --tags-only
Bundling in bundle/
Config written to bundle/sqitch.conf
Bundling v1.0.0-dev1
 - appuser
 - users
 - change_pass
 - insert_user
Bundling v1.0.0-b1
 - change_pass_v2
 - insert_user_v2
Plan written to bundle/sqitch.plan
>
What About Bundling?
> git tag v1.0.0-b1 -am 'Tag v1.0.0-b1'
> sqitch bundle --tags-only
Bundling in bundle/
Config written to bundle/sqitch.conf
Bundling v1.0.0-dev1
 - appuser
 - users
 - change_pass
 - insert_user
Bundling v1.0.0-b1
 - change_pass_v2
 - insert_user_v2
Plan written to bundle/sqitch.plan
>
What About Bundling?
> git tag v1.0.0-b1 -am 'Tag v1.0.0-b1'
> sqitch bundle --tags-only
Bundling in bundle/
Config written to bundle/sqitch.conf
Bundling v1.0.0-dev1
 - appuser
 - users
 - change_pass
 - insert_user
Bundling v1.0.0-b1
 - change_pass_v2
 - insert_user_v2
Plan written to bundle/sqitch.plan
>emacs bundle/sqitch.plan
What’s the Plan?
[v1.0.0-dev1]
  appuser
  users
  change_pass
  insert_user

[v1.0.0-b1]
  change_pass_v2
  insert_user_v2




  filename
Make it So
>
Make it So
>cd bundle
> sqitch -d flipr_staging deploy
Deploying v1.0.0-b1 to flipr_staging
 + change_pass_v2
 + insert_user_v2
>
Make it So
>cd bundle
> sqitch -d flipr_staging deploy
Deploying v1.0.0-b1 to flipr_staging
  + change_pass_v2
  + insert_user_v2
> sqitch -d flipr_staging status
# On database flipr_staging
# Tag: v1.0.0-b1
# Step: insert_user_v2
# Date: 2012-05-18 17:51:35
#
Nothing to deploy (up-to-date)
>
Ship It!
Other Commands
Other Commands
log - Like git log
Other Commands
log - Like git log

check - Validate plan & database
Other Commands
log - Like git log

check - Validate plan & database

test - Test deployment success
Other Commands
log - Like git log

check - Validate plan & database

test - Test deployment success

help - Get it
Current Status
Current Status
Working on it full time
Current Status
Working on it full time

Rethinking VCS integration
Current Status
Working on it full time

Rethinking VCS integration

  Rely more on plan file
Current Status
Working on it full time

Rethinking VCS integration

  Rely more on plan file

  Complement with VCS history
Current Status
Working on it full time

Rethinking VCS integration

  Rely more on plan file

  Complement with VCS history

Tools for plan file management
Fork It
Fork It
http:/
     /sqitch.org/
Fork It
http:/
     /sqitch.org/

https:/
      /github.com/theory/sqitch/
Fork It
http:/
     /sqitch.org/

https:/
      /github.com/theory/sqitch/

Opinions wanted
Fork It
http:/
     /sqitch.org/

https:/
      /github.com/theory/sqitch/

Opinions wanted

Coders wanted
Fork It
http:/
     /sqitch.org/

https:/
      /github.com/theory/sqitch/

Opinions wanted

Coders wanted

Doc writers and web designers wanted!
Fork It
http:/
     /sqitch.org/

https:/
      /github.com/theory/sqitch/

Opinions wanted

Coders wanted

Doc writers and web designers wanted!

Make it great!
Thank you.
Simple SQL Change
  Management with Sqitch
                                                       David E. Wheeler
                                                      http:/
                                                           /sqitch.org/


                                                          PGCon 2012
                                                         Ottawa, Canada




Text: Attribution-Noncommercial-Share Alike 3.0 United States:
http://creativecommons.org/licenses/by-nc-sa/3.0/us/
Images licensed independently and © Their respective owners.

More Related Content

What's hot

KYSUC - Keep Your Schema Under Control
KYSUC - Keep Your Schema Under ControlKYSUC - Keep Your Schema Under Control
KYSUC - Keep Your Schema Under ControlCoimbra JUG
 
The Bash Dashboard (Or: How to Use Bash for Data Analysis)
The Bash Dashboard (Or: How to Use Bash for Data Analysis)The Bash Dashboard (Or: How to Use Bash for Data Analysis)
The Bash Dashboard (Or: How to Use Bash for Data Analysis)Bram Adams
 
Max Voloshin - "Organization of frontend development for products with micros...
Max Voloshin - "Organization of frontend development for products with micros...Max Voloshin - "Organization of frontend development for products with micros...
Max Voloshin - "Organization of frontend development for products with micros...IT Event
 
Gearman work queue in php
Gearman work queue in phpGearman work queue in php
Gearman work queue in phpBo-Yi Wu
 
What’s New in Rails 5.0?
What’s New in Rails 5.0?What’s New in Rails 5.0?
What’s New in Rails 5.0?Unboxed
 
Nina Zakharenko - Introduction to Git - Start SLC 2015
Nina Zakharenko - Introduction to Git - Start SLC 2015Nina Zakharenko - Introduction to Git - Start SLC 2015
Nina Zakharenko - Introduction to Git - Start SLC 2015Nina Zakharenko
 
Hosting Your Own OTA Update Service
Hosting Your Own OTA Update ServiceHosting Your Own OTA Update Service
Hosting Your Own OTA Update ServiceQuinlan Jung
 
Wicket Presentation @ AlphaCSP Java Web Frameworks Playoff 2008
Wicket Presentation @ AlphaCSP Java Web Frameworks Playoff 2008Wicket Presentation @ AlphaCSP Java Web Frameworks Playoff 2008
Wicket Presentation @ AlphaCSP Java Web Frameworks Playoff 2008Baruch Sadogursky
 
One commit, one release. Continuously delivering a Symfony project.
One commit, one release. Continuously delivering a Symfony project.One commit, one release. Continuously delivering a Symfony project.
One commit, one release. Continuously delivering a Symfony project.Javier López
 
Continous Delivering a PHP application
Continous Delivering a PHP applicationContinous Delivering a PHP application
Continous Delivering a PHP applicationJavier López
 
Мониторинг облачной CI-системы на примере Jenkins / Александр Акбашев (HERE T...
Мониторинг облачной CI-системы на примере Jenkins / Александр Акбашев (HERE T...Мониторинг облачной CI-системы на примере Jenkins / Александр Акбашев (HERE T...
Мониторинг облачной CI-системы на примере Jenkins / Александр Акбашев (HERE T...Ontico
 
VCS for Teamwork - GIT Workshop
VCS for Teamwork - GIT WorkshopVCS for Teamwork - GIT Workshop
VCS for Teamwork - GIT WorkshopAnis Ahmad
 
Javascript - The Stack and Beyond
Javascript - The Stack and BeyondJavascript - The Stack and Beyond
Javascript - The Stack and BeyondAll Things Open
 
Deep dark-side of git: How git works internally
Deep dark-side of git: How git works internallyDeep dark-side of git: How git works internally
Deep dark-side of git: How git works internallySeongJae Park
 
That's (g)it! par Sébastien Dawans CETIC
That's (g)it! par Sébastien Dawans CETICThat's (g)it! par Sébastien Dawans CETIC
That's (g)it! par Sébastien Dawans CETICLa FeWeb
 
ITB2019 ColdBox APIs + VueJS - powering Mobile, Desktop and Web Apps with 1 V...
ITB2019 ColdBox APIs + VueJS - powering Mobile, Desktop and Web Apps with 1 V...ITB2019 ColdBox APIs + VueJS - powering Mobile, Desktop and Web Apps with 1 V...
ITB2019 ColdBox APIs + VueJS - powering Mobile, Desktop and Web Apps with 1 V...Ortus Solutions, Corp
 
ITB2019 CommandBox vs Node.js - Nolan Erck
ITB2019  CommandBox vs Node.js - Nolan ErckITB2019  CommandBox vs Node.js - Nolan Erck
ITB2019 CommandBox vs Node.js - Nolan ErckOrtus Solutions, Corp
 
Tracing Software Build Processes to Uncover License Compliance Inconsistencies
Tracing Software Build Processes to Uncover License Compliance InconsistenciesTracing Software Build Processes to Uncover License Compliance Inconsistencies
Tracing Software Build Processes to Uncover License Compliance InconsistenciesShane McIntosh
 
Don't screw it up: how to build durable web apis
Don't screw it up: how to build durable web apisDon't screw it up: how to build durable web apis
Don't screw it up: how to build durable web apisAlessandro Cinelli (cirpo)
 

What's hot (20)

KYSUC - Keep Your Schema Under Control
KYSUC - Keep Your Schema Under ControlKYSUC - Keep Your Schema Under Control
KYSUC - Keep Your Schema Under Control
 
The Bash Dashboard (Or: How to Use Bash for Data Analysis)
The Bash Dashboard (Or: How to Use Bash for Data Analysis)The Bash Dashboard (Or: How to Use Bash for Data Analysis)
The Bash Dashboard (Or: How to Use Bash for Data Analysis)
 
Max Voloshin - "Organization of frontend development for products with micros...
Max Voloshin - "Organization of frontend development for products with micros...Max Voloshin - "Organization of frontend development for products with micros...
Max Voloshin - "Organization of frontend development for products with micros...
 
Gearman work queue in php
Gearman work queue in phpGearman work queue in php
Gearman work queue in php
 
What’s New in Rails 5.0?
What’s New in Rails 5.0?What’s New in Rails 5.0?
What’s New in Rails 5.0?
 
Nina Zakharenko - Introduction to Git - Start SLC 2015
Nina Zakharenko - Introduction to Git - Start SLC 2015Nina Zakharenko - Introduction to Git - Start SLC 2015
Nina Zakharenko - Introduction to Git - Start SLC 2015
 
Hosting Your Own OTA Update Service
Hosting Your Own OTA Update ServiceHosting Your Own OTA Update Service
Hosting Your Own OTA Update Service
 
Wicket Presentation @ AlphaCSP Java Web Frameworks Playoff 2008
Wicket Presentation @ AlphaCSP Java Web Frameworks Playoff 2008Wicket Presentation @ AlphaCSP Java Web Frameworks Playoff 2008
Wicket Presentation @ AlphaCSP Java Web Frameworks Playoff 2008
 
One commit, one release. Continuously delivering a Symfony project.
One commit, one release. Continuously delivering a Symfony project.One commit, one release. Continuously delivering a Symfony project.
One commit, one release. Continuously delivering a Symfony project.
 
Continous Delivering a PHP application
Continous Delivering a PHP applicationContinous Delivering a PHP application
Continous Delivering a PHP application
 
Мониторинг облачной CI-системы на примере Jenkins / Александр Акбашев (HERE T...
Мониторинг облачной CI-системы на примере Jenkins / Александр Акбашев (HERE T...Мониторинг облачной CI-системы на примере Jenkins / Александр Акбашев (HERE T...
Мониторинг облачной CI-системы на примере Jenkins / Александр Акбашев (HERE T...
 
Namshi in 2014: let's rock!
Namshi in 2014: let's rock!Namshi in 2014: let's rock!
Namshi in 2014: let's rock!
 
VCS for Teamwork - GIT Workshop
VCS for Teamwork - GIT WorkshopVCS for Teamwork - GIT Workshop
VCS for Teamwork - GIT Workshop
 
Javascript - The Stack and Beyond
Javascript - The Stack and BeyondJavascript - The Stack and Beyond
Javascript - The Stack and Beyond
 
Deep dark-side of git: How git works internally
Deep dark-side of git: How git works internallyDeep dark-side of git: How git works internally
Deep dark-side of git: How git works internally
 
That's (g)it! par Sébastien Dawans CETIC
That's (g)it! par Sébastien Dawans CETICThat's (g)it! par Sébastien Dawans CETIC
That's (g)it! par Sébastien Dawans CETIC
 
ITB2019 ColdBox APIs + VueJS - powering Mobile, Desktop and Web Apps with 1 V...
ITB2019 ColdBox APIs + VueJS - powering Mobile, Desktop and Web Apps with 1 V...ITB2019 ColdBox APIs + VueJS - powering Mobile, Desktop and Web Apps with 1 V...
ITB2019 ColdBox APIs + VueJS - powering Mobile, Desktop and Web Apps with 1 V...
 
ITB2019 CommandBox vs Node.js - Nolan Erck
ITB2019  CommandBox vs Node.js - Nolan ErckITB2019  CommandBox vs Node.js - Nolan Erck
ITB2019 CommandBox vs Node.js - Nolan Erck
 
Tracing Software Build Processes to Uncover License Compliance Inconsistencies
Tracing Software Build Processes to Uncover License Compliance InconsistenciesTracing Software Build Processes to Uncover License Compliance Inconsistencies
Tracing Software Build Processes to Uncover License Compliance Inconsistencies
 
Don't screw it up: how to build durable web apis
Don't screw it up: how to build durable web apisDon't screw it up: how to build durable web apis
Don't screw it up: how to build durable web apis
 

Similar to Simple SQL Change Management with Sqitch

Sane SQL Change Management with Sqitch
Sane SQL Change Management with SqitchSane SQL Change Management with Sqitch
Sane SQL Change Management with SqitchDavid Wheeler
 
Free The Enterprise With Ruby & Master Your Own Domain
Free The Enterprise With Ruby & Master Your Own DomainFree The Enterprise With Ruby & Master Your Own Domain
Free The Enterprise With Ruby & Master Your Own DomainKen Collins
 
SQL Server 2008 Integration Services
SQL Server 2008 Integration ServicesSQL Server 2008 Integration Services
SQL Server 2008 Integration ServicesEduardo Castro
 
Database automated build and test - SQL In The City Cambridge
Database automated build and test - SQL In The City CambridgeDatabase automated build and test - SQL In The City Cambridge
Database automated build and test - SQL In The City CambridgeRed Gate Software
 
Web Development Foundation & Team Collaboration
Web Development Foundation & Team CollaborationWeb Development Foundation & Team Collaboration
Web Development Foundation & Team CollaborationSupanat Potiwarakorn
 
Version Control ThinkVitamin
Version Control ThinkVitaminVersion Control ThinkVitamin
Version Control ThinkVitaminAlex Hillman
 
Handling Database Deployments
Handling Database DeploymentsHandling Database Deployments
Handling Database DeploymentsMike Willbanks
 
Deploying TYPO3 Neos websites using Surf
Deploying TYPO3 Neos websites using SurfDeploying TYPO3 Neos websites using Surf
Deploying TYPO3 Neos websites using SurfKarsten Dambekalns
 
PgConf US 2015 - ALTER DATABASE ADD more SANITY
PgConf US 2015  - ALTER DATABASE ADD more SANITYPgConf US 2015  - ALTER DATABASE ADD more SANITY
PgConf US 2015 - ALTER DATABASE ADD more SANITYOleksii Kliukin
 
Embracing Distributed Version Control
Embracing Distributed Version ControlEmbracing Distributed Version Control
Embracing Distributed Version ControlNowell Strite
 
How to Contribute Code to MySQL?
How to Contribute Code to MySQL?How to Contribute Code to MySQL?
How to Contribute Code to MySQL?Thava Alagu
 
Real world Python+django
Real world Python+djangoReal world Python+django
Real world Python+djangoJoel Corrêa
 
NoSQL - No Security? - The BSides Edition
NoSQL - No Security? - The BSides EditionNoSQL - No Security? - The BSides Edition
NoSQL - No Security? - The BSides EditionGavin Holt
 
Evolutionary Database Design
Evolutionary Database DesignEvolutionary Database Design
Evolutionary Database DesignAndrei Solntsev
 
Troubleshooting tips from docker support engineers
Troubleshooting tips from docker support engineersTroubleshooting tips from docker support engineers
Troubleshooting tips from docker support engineersDocker, Inc.
 
Five Ways Automation Has Increased Application Deployment and Changed Culture
Five Ways Automation Has Increased Application Deployment and Changed CultureFive Ways Automation Has Increased Application Deployment and Changed Culture
Five Ways Automation Has Increased Application Deployment and Changed CultureXebiaLabs
 
Continuous Deployment: The Dirty Details
Continuous Deployment: The Dirty DetailsContinuous Deployment: The Dirty Details
Continuous Deployment: The Dirty DetailsMike Brittain
 

Similar to Simple SQL Change Management with Sqitch (20)

Sane SQL Change Management with Sqitch
Sane SQL Change Management with SqitchSane SQL Change Management with Sqitch
Sane SQL Change Management with Sqitch
 
Free The Enterprise With Ruby & Master Your Own Domain
Free The Enterprise With Ruby & Master Your Own DomainFree The Enterprise With Ruby & Master Your Own Domain
Free The Enterprise With Ruby & Master Your Own Domain
 
Javaone 2014
Javaone 2014Javaone 2014
Javaone 2014
 
SQL Server 2008 Integration Services
SQL Server 2008 Integration ServicesSQL Server 2008 Integration Services
SQL Server 2008 Integration Services
 
Database automated build and test - SQL In The City Cambridge
Database automated build and test - SQL In The City CambridgeDatabase automated build and test - SQL In The City Cambridge
Database automated build and test - SQL In The City Cambridge
 
Web Development Foundation & Team Collaboration
Web Development Foundation & Team CollaborationWeb Development Foundation & Team Collaboration
Web Development Foundation & Team Collaboration
 
Version Control ThinkVitamin
Version Control ThinkVitaminVersion Control ThinkVitamin
Version Control ThinkVitamin
 
Handling Database Deployments
Handling Database DeploymentsHandling Database Deployments
Handling Database Deployments
 
Deploying TYPO3 Neos websites using Surf
Deploying TYPO3 Neos websites using SurfDeploying TYPO3 Neos websites using Surf
Deploying TYPO3 Neos websites using Surf
 
PgConf US 2015 - ALTER DATABASE ADD more SANITY
PgConf US 2015  - ALTER DATABASE ADD more SANITYPgConf US 2015  - ALTER DATABASE ADD more SANITY
PgConf US 2015 - ALTER DATABASE ADD more SANITY
 
Embracing Distributed Version Control
Embracing Distributed Version ControlEmbracing Distributed Version Control
Embracing Distributed Version Control
 
Revoke-Obfuscation
Revoke-ObfuscationRevoke-Obfuscation
Revoke-Obfuscation
 
How to Contribute Code to MySQL?
How to Contribute Code to MySQL?How to Contribute Code to MySQL?
How to Contribute Code to MySQL?
 
Real world Python+django
Real world Python+djangoReal world Python+django
Real world Python+django
 
NoSQL - No Security? - The BSides Edition
NoSQL - No Security? - The BSides EditionNoSQL - No Security? - The BSides Edition
NoSQL - No Security? - The BSides Edition
 
Evolutionary Database Design
Evolutionary Database DesignEvolutionary Database Design
Evolutionary Database Design
 
Troubleshooting tips from docker support engineers
Troubleshooting tips from docker support engineersTroubleshooting tips from docker support engineers
Troubleshooting tips from docker support engineers
 
Five Ways Automation Has Increased Application Deployment and Changed Culture
Five Ways Automation Has Increased Application Deployment and Changed CultureFive Ways Automation Has Increased Application Deployment and Changed Culture
Five Ways Automation Has Increased Application Deployment and Changed Culture
 
Liquibase
LiquibaseLiquibase
Liquibase
 
Continuous Deployment: The Dirty Details
Continuous Deployment: The Dirty DetailsContinuous Deployment: The Dirty Details
Continuous Deployment: The Dirty Details
 

More from David Wheeler

Building and Distributing PostgreSQL Extensions Without Learning C
Building and Distributing PostgreSQL Extensions Without Learning CBuilding and Distributing PostgreSQL Extensions Without Learning C
Building and Distributing PostgreSQL Extensions Without Learning CDavid Wheeler
 
Releasing PostgreSQL Extension on PGXN
Releasing PostgreSQL Extension on PGXNReleasing PostgreSQL Extension on PGXN
Releasing PostgreSQL Extension on PGXNDavid Wheeler
 
Building and Distributing PostgreSQL Extensions Without Learning C
Building and Distributing PostgreSQL Extensions Without Learning CBuilding and Distributing PostgreSQL Extensions Without Learning C
Building and Distributing PostgreSQL Extensions Without Learning CDavid Wheeler
 
Test Driven Database Development
Test Driven Database DevelopmentTest Driven Database Development
Test Driven Database DevelopmentDavid Wheeler
 
PgTAP Best Practices
PgTAP Best PracticesPgTAP Best Practices
PgTAP Best PracticesDavid Wheeler
 
Unit Test Your Database
Unit Test Your DatabaseUnit Test Your Database
Unit Test Your DatabaseDavid Wheeler
 

More from David Wheeler (6)

Building and Distributing PostgreSQL Extensions Without Learning C
Building and Distributing PostgreSQL Extensions Without Learning CBuilding and Distributing PostgreSQL Extensions Without Learning C
Building and Distributing PostgreSQL Extensions Without Learning C
 
Releasing PostgreSQL Extension on PGXN
Releasing PostgreSQL Extension on PGXNReleasing PostgreSQL Extension on PGXN
Releasing PostgreSQL Extension on PGXN
 
Building and Distributing PostgreSQL Extensions Without Learning C
Building and Distributing PostgreSQL Extensions Without Learning CBuilding and Distributing PostgreSQL Extensions Without Learning C
Building and Distributing PostgreSQL Extensions Without Learning C
 
Test Driven Database Development
Test Driven Database DevelopmentTest Driven Database Development
Test Driven Database Development
 
PgTAP Best Practices
PgTAP Best PracticesPgTAP Best Practices
PgTAP Best Practices
 
Unit Test Your Database
Unit Test Your DatabaseUnit Test Your Database
Unit Test Your Database
 

Recently uploaded

Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfIngrid Airi González
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Farhan Tariq
 
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentPim van der Noll
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfpanagenda
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality AssuranceInflectra
 
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security ObservabilityGlenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security Observabilityitnewsafrica
 
Connecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfConnecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfNeo4j
 
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...BookNet Canada
 
Digital Tools & AI in Career Development
Digital Tools & AI in Career DevelopmentDigital Tools & AI in Career Development
Digital Tools & AI in Career DevelopmentMahmoud Rabie
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPathCommunity
 
A Glance At The Java Performance Toolbox
A Glance At The Java Performance ToolboxA Glance At The Java Performance Toolbox
A Glance At The Java Performance ToolboxAna-Maria Mihalceanu
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesThousandEyes
 
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...itnewsafrica
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI AgeCprime
 
2024 April Patch Tuesday
2024 April Patch Tuesday2024 April Patch Tuesday
2024 April Patch TuesdayIvanti
 
Landscape Catalogue 2024 Australia-1.pdf
Landscape Catalogue 2024 Australia-1.pdfLandscape Catalogue 2024 Australia-1.pdf
Landscape Catalogue 2024 Australia-1.pdfAarwolf Industries LLC
 
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...Jeffrey Haguewood
 
JET Technology Labs White Paper for Virtualized Security and Encryption Techn...
JET Technology Labs White Paper for Virtualized Security and Encryption Techn...JET Technology Labs White Paper for Virtualized Security and Encryption Techn...
JET Technology Labs White Paper for Virtualized Security and Encryption Techn...amber724300
 
All These Sophisticated Attacks, Can We Really Detect Them - PDF
All These Sophisticated Attacks, Can We Really Detect Them - PDFAll These Sophisticated Attacks, Can We Really Detect Them - PDF
All These Sophisticated Attacks, Can We Really Detect Them - PDFMichael Gough
 
QMMS Lesson 2 - Using MS Excel Formula.pdf
QMMS Lesson 2 - Using MS Excel Formula.pdfQMMS Lesson 2 - Using MS Excel Formula.pdf
QMMS Lesson 2 - Using MS Excel Formula.pdfROWELL MARQUINA
 

Recently uploaded (20)

Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdf
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...
 
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
 
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security ObservabilityGlenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
 
Connecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfConnecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdf
 
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...
 
Digital Tools & AI in Career Development
Digital Tools & AI in Career DevelopmentDigital Tools & AI in Career Development
Digital Tools & AI in Career Development
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to Hero
 
A Glance At The Java Performance Toolbox
A Glance At The Java Performance ToolboxA Glance At The Java Performance Toolbox
A Glance At The Java Performance Toolbox
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
 
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI Age
 
2024 April Patch Tuesday
2024 April Patch Tuesday2024 April Patch Tuesday
2024 April Patch Tuesday
 
Landscape Catalogue 2024 Australia-1.pdf
Landscape Catalogue 2024 Australia-1.pdfLandscape Catalogue 2024 Australia-1.pdf
Landscape Catalogue 2024 Australia-1.pdf
 
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...
 
JET Technology Labs White Paper for Virtualized Security and Encryption Techn...
JET Technology Labs White Paper for Virtualized Security and Encryption Techn...JET Technology Labs White Paper for Virtualized Security and Encryption Techn...
JET Technology Labs White Paper for Virtualized Security and Encryption Techn...
 
All These Sophisticated Attacks, Can We Really Detect Them - PDF
All These Sophisticated Attacks, Can We Really Detect Them - PDFAll These Sophisticated Attacks, Can We Really Detect Them - PDF
All These Sophisticated Attacks, Can We Really Detect Them - PDF
 
QMMS Lesson 2 - Using MS Excel Formula.pdf
QMMS Lesson 2 - Using MS Excel Formula.pdfQMMS Lesson 2 - Using MS Excel Formula.pdf
QMMS Lesson 2 - Using MS Excel Formula.pdf
 

Simple SQL Change Management with Sqitch

  • 1. Simple SQL Change Management with Sqitch David E. Wheeler PGCon 2012 Ottawa, Canada Text: Attribution-Noncommercial-Share Alike 3.0 United States: http://creativecommons.org/licenses/by-nc-sa/3.0/us/ Images licensed independently and © Their respective owners.
  • 2. Whats Wrong with Migrations?
  • 3. Whats Wrong with Migrations? Incomplete mini-language
  • 4. Whats Wrong with Migrations? Incomplete mini-language No logical replication integration
  • 5. Whats Wrong with Migrations? Incomplete mini-language No logical replication integration Numbered scripts hard to track
  • 6. Whats Wrong with Migrations? Incomplete mini-language No logical replication integration Numbered scripts hard to track No VCS awareness
  • 7. What about SQL Migrations? Incomplete mini-language No logical replication integration Numbered scripts hard to track No VCS awareness
  • 8. What about SQL Migrations? ——————————————— Incomplete mini-language No logical replication integration Numbered scripts hard to track No VCS awareness
  • 9. What about SQL Migrations? ——————————————— Incomplete mini-language ——————————————————— No logical replication integration Numbered scripts hard to track No VCS awareness
  • 10. What about SQL Migrations? ——————————————— Incomplete mini-language ——————————————————— No logical replication integration Numbered scripts hard to track No VCS awareness Managing procedures is a PITA
  • 12. Imagine this Change >git diff diff --git a/sql/deploy/recur.sql b/sql/deploy/recur.sql index 622d52e..56e419e 100644 --- a/sql/deploy/recur.sql +++ b/sql/deploy/recur.sql @@ -22,7 +22,10 @@ recurrence <> 'none' OR ( recurrence = 'none' - AND starts_at BETWEEN range_start AND range_end + AND ( + starts_at BETWEEN range_start AND range_end + OR ends_at BETWEEN range_start AND range_end + ) ) ) LOOP
  • 13. Imagine this Change >git diff diff --git a/sql/deploy/recur.sql b/sql/deploy/recur.sql index 622d52e..56e419e 100644 --- a/sql/deploy/recur.sql +++ b/sql/deploy/recur.sql @@ -22,7 +22,10 @@ recurrence <> 'none' OR ( recurrence = 'none' - AND starts_at BETWEEN range_start AND range_end + AND ( + starts_at BETWEEN range_start AND range_end + OR ends_at BETWEEN range_start AND range_end + ) ) Simple, right? ) LOOP
  • 15. Not So Much Paste entire function to new “up” script
  • 16. Not So Much Paste entire function to new “up” script Edit the new file
  • 17. Not So Much Paste entire function to new “up” script Edit the new file Copy the function to the new “down” script
  • 18. Not So Much Paste entire function to new “up” script Edit the new file Copy the function to the new “down” script Three copies of the function!
  • 19. Not So Much Paste entire function to new “up” script Edit the new file Copy the function to the new “down” script Three copies of the function! No real source code management
  • 20. Not So Much Paste entire function to new “up” script Edit the new file Copy the function to the new “down” script Three copies of the function! No real source code management This sucks
  • 22. What about Liquibase? <?xml version="1.0" encoding="UTF-8"?> <databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog/1.6" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog/1.6 http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-1.6.xsd"> <changeSet id="1" author="me"> <createTable tableName="first_table"> <column name="id" type="int"> <constraints primaryKey="true" nullable="false"/> </column> <column name="name" type="varchar(50)"> <constraints nullable="false"/> </column> </createTable> <createTable tableName="new_table"> <column name="id" type="int"> <constraints primaryKey="true" nullable="false"/> </column> </createTable> </changeSet> </databaseChangeLog> filename
  • 23. What about Liquibase? <?xml version="1.0" encoding="UTF-8"?> <databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog/1.6" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog/1.6 http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-1.6.xsd"> <changeSet id="1" author="me"> <createTable tableName="first_table"> <column name="id" type="int"> <constraints primaryKey="true" nullable="false"/> </column> <column name="name" type="varchar(50)"> Whaaaa? <constraints nullable="false"/> </column> </createTable> <createTable tableName="new_table"> <column name="id" type="int"> <constraints primaryKey="true" nullable="false"/> </column> </createTable> </changeSet> </databaseChangeLog> filename
  • 24. What about Liquibase? <?xml version="1.0" encoding="UTF-8"?> <databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog/1.6" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog/1.6 http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-1.6.xsd"> <changeSet id="1" author="me"> <createTable tableName="first_table"> <column name="id" type="int"> <constraints primaryKey="true" nullable="false"/> </column> <column name="name" type="varchar(50)"> Whaaaa? <constraints nullable="false"/> </column> </createTable> <createTable tableName="new_table"> <column name="id" type="int"> <constraints primaryKey="true" nullable="false"/> GTFO! </column> </createTable> </changeSet> </databaseChangeLog> filename
  • 26. depesz’s Versioning? https:/ /github.com/depesz/versioning
  • 27. depesz’s Versioning? https:/ /github.com/depesz/versioning Nice dependency specification
  • 28. depesz’s Versioning? https:/ /github.com/depesz/versioning Nice dependency specification Tight PostgreSQL integration
  • 29. depesz’s Versioning? https:/ /github.com/depesz/versioning Nice dependency specification Tight PostgreSQL integration No VCS integration
  • 30. depesz’s Versioning? https:/ /github.com/depesz/versioning Nice dependency specification Tight PostgreSQL integration No VCS integration No tools
  • 31. depesz’s Versioning? https:/ /github.com/depesz/versioning Nice dependency specification Tight PostgreSQL integration No VCS integration No tools Managing procedures still a PITA
  • 32.
  • 33. Introducing Sqitch
  • 41. Sqitch Philosophy No opinions Native scripting VCS integration
  • 42. Sqitch Philosophy No opinions Native scripting VCS integration Dependency resolution
  • 43. Sqitch Philosophy No opinions Native scripting VCS integration Dependency resolution No numbering
  • 44. Sqitch Philosophy No opinions Native scripting VCS integration Dependency resolution No numbering Distribution bundling
  • 48. Sqitch Philosophy Reduced duplication Built-in configuration Deployment planning
  • 49. Sqitch Philosophy Reduced duplication Built-in configuration Deployment planning Git-style interface
  • 50. Sqitch Philosophy Reduced duplication Built-in configuration Deployment planning Git-style interface Deployment tagging
  • 60. Caveats Under heavy development v0.30 Testing release today
  • 61. Caveats Under heavy development v0.30 Testing release today Functionality rapidly evolving
  • 62. Caveats Under heavy development v0.30 Testing release today Functionality rapidly evolving Some gaps still to be filled in
  • 63. Caveats Under heavy development v0.30 Testing release today Functionality rapidly evolving Some gaps still to be filled in VCS integration in flux
  • 65. How it Works >mkdir flipr > cd flipr > git init . Initialized empty Git repository in /flipr/.git/ > touch README.md > git add . > git commit -am 'Fist post!' >
  • 66. How it Works >mkdir flipr > cd flipr > git init . Initialized empty Git repository in /flipr/.git/ > touch README.md > git add . > git commit -am 'Fist post!' >sqitch --engine pg init Created sql/deploy Created sql/revert Created sql/test Created sqitch.conf >
  • 67. How it Works >mkdir flipr > cd flipr > git init . Initialized empty Git repository in /flipr/.git/ > touch README.md > git add . > git commit -am 'Fist post!' >sqitch --engine pg init Created sql/deploy Created sql/revert Created sql/test Created sqitch.conf >emacs sqitch.conf
  • 68. sqitch.conf [core] engine = pg # plan_file = sqitch.plan # sql_dir = sql # deploy_dir = sql/deploy # revert_dir = sql/revert # test_dir = sql/test # extension = sql # [core "pg"] # db_name = # client = psql # sqitch_schema = sqitch # password = # port = # host = # username = sqitch.conf
  • 69. sqitch.conf [core] engine = pg --engine pg # plan_file = sqitch.plan # sql_dir = sql # deploy_dir = sql/deploy # revert_dir = sql/revert # test_dir = sql/test # extension = sql # [core "pg"] # db_name = # client = psql # sqitch_schema = sqitch # password = # port = # host = # username = sqitch.conf
  • 71. Add User Config >sqitch config --user core.pg.client /var/lib/pgsql/bin/ psql >
  • 72. Add User Config >sqitch config --user core.pg.client /var/lib/pgsql/bin/ psql >
  • 73. Add User Config >sqitch config --user core.pg.client /var/lib/pgsql/bin/ psql >emacs ~/.sqitch/sqitch.conf
  • 74. ~/ .sqitch/sqitch.conf [core "pg"] client = /var/lib/pgsql/bin/psql ~/.sqitch/sqitc
  • 75. ~/ .sqitch/sqitch.conf [core "pg"] client = /var/lib/pgsql/bin/psql Good for all projects ~/.sqitch/sqitc
  • 77. Make It So >git add . > git commit -am 'Initialize Sqitch configuration.' [master (root-commit) a22000d] Initialize Sqitch configuration. 1 file changed, 16 insertions(+) create mode 100644 sqitch.conf >
  • 79. First Deployment > sqitch add-step appuser Created sql/deploy/appuser.sql Created sql/revert/appuser.sql Created sql/test/appuser.sql >
  • 80. First Deployment > sqitch add-step appuser Created sql/deploy/appuser.sql Created sql/revert/appuser.sql Created sql/test/appuser.sql >
  • 81. First Deployment > sqitch add-step appuser Created sql/deploy/appuser.sql Created sql/revert/appuser.sql Created sql/test/appuser.sql >emacs sql/deploy/appuser.sql
  • 82. sql/deploy/appuser.sql -- Deploy appuser BEGIN; -- XXX Add DDLs here. COMMIT; sql/deploy/appu
  • 83. sql/deploy/appuser.sql -- Deploy appuser BEGIN; CREATE ROLE flipr WITH LOGIN; COMMIT; sql/deploy/appu
  • 84. First Deployment > sqitch add-step appuser Created sql/deploy/appuser.sql Created sql/revert/appuser.sql Created sql/test/appuser.sql > emacs sql/deploy/appuser.sql >
  • 85. First Deployment > sqitch add-step appuser Created sql/deploy/appuser.sql Created sql/revert/appuser.sql Created sql/test/appuser.sql > emacs sql/deploy/appuser.sql >emacs sql/revert/appuser.sql
  • 86. sql/revert/appuser.sql -- Revert appuser BEGIN; -- XXX Add DDLs here. COMMIT; sql/deploy/appu
  • 87. sql/revert/appuser.sql -- Revert appuser BEGIN; DROP ROLE flipr; COMMIT; sql/deploy/appu
  • 89. Make it So! >createdb flipr_test > sqitch --db-name flipr_test deploy --untracked Adding metadata tables to flipr_test Deploying HEAD+ to flipr_test + appuser >
  • 90. Make it So! >createdb flipr_test > sqitch --db-name flipr_test deploy --untracked Adding metadata tables to flipr_test Deploying HEAD+ to flipr_test + appuser >
  • 91. Make it So! >createdb flipr_test > sqitch --db-name flipr_test deploy --untracked Adding metadata tables to flipr_test Deploying HEAD+ to flipr_test + appuser >
  • 92. Make it So! >createdb flipr_test > sqitch --db-name flipr_test deploy --untracked Adding metadata tables to flipr_test Deploying HEAD+ to flipr_test + appuser >
  • 93. Make it So! >createdb flipr_test > sqitch --db-name flipr_test deploy --untracked Adding metadata tables to flipr_test Deploying HEAD+ to flipr_test + appuser >psql -d flipr_test -c 'du flipr' List of roles Role name | Attributes | Member of -----------+------------+----------- flipr | | {} >
  • 95. How’s it Look? > sqitch -d flipr_test status # On database flipr_test # Tag: HEAD+ # Step: appuser # Date: 2012-05-18 17:15:23 # Nothing to deploy (up-to-date) >
  • 96. How’s it Look? > sqitch -d flipr_test status # On database flipr_test # Tag: HEAD+ # Step: appuser # Date: 2012-05-18 17:15:23 # Nothing to deploy (up-to-date) >
  • 97. How’s it Look? > sqitch -d flipr_test status # On database flipr_test # Tag: HEAD+ # Step: appuser # Date: 2012-05-18 17:15:23 # Nothing to deploy (up-to-date) >
  • 98. How’s it Look? > sqitch -d flipr_test status # On database flipr_test # Tag: HEAD+ # Step: appuser # Date: 2012-05-18 17:15:23 # Nothing to deploy (up-to-date) > Proposed
  • 100. Go Back >sqitch --db-name flipr_test revert Reverting all changes from flipr_test - appuser >
  • 101. Go Back >sqitch --db-name flipr_test revert Reverting all changes from flipr_test - appuser >
  • 102. Go Back >sqitch --db-name flipr_test revert Reverting all changes from flipr_test - appuser >
  • 103. Go Back >sqitch --db-name flipr_test revert Reverting all changes from flipr_test - appuser >psql -d flipr_test -c 'du flipr' List of roles Role name | Attributes | Member of -----------+------------+----------- >
  • 105. What’s The Status? >sqitch -d flipr_test status --untracked # On database flipr_test # Nothing deployed. # # Changes not deployed: # * HEAD+ # appuser # Use "sqitch deploy --untracked" to deploy these changes >
  • 106. What’s The Status? >sqitch -d flipr_test status --untracked # On database flipr_test # Nothing deployed. # # Changes not deployed: # * HEAD+ # appuser # Use "sqitch deploy --untracked" to deploy these changes >
  • 108. History >sqitch -d flipr_test log step appuser reverted By: david Date: 2012-05-18 17:15:23 Tag: HEAD+ step appuser deployed By: david Date: 2012-05-18 17:18:12 Tag: HEAD+ >
  • 109. History >sqitch -d flipr_test log step appuser reverted By: david Date: 2012-05-18 17:15:23 Tag: HEAD+ step appuser deployed By: david Date: 2012-05-18 17:18:12 Tag: HEAD+ >
  • 110. History >sqitch -d flipr_test log step appuser reverted By: david Date: 2012-05-18 17:15:23 Tag: HEAD+ step appuser deployed By: david Date: 2012-05-18 17:18:12 Tag: HEAD+ >
  • 112. Commit It! >git add . > git commit -m 'Add app user.' [master 36acafd] Add app user. 2 files changed, 2 insertions(+) create mode 100644 sql/deploy/appuser.sql create mode 100644 sql/revert/appuser.sql create mode 100644 sql/test/appuser.sql >
  • 113. Commit It! >git add . > git commit -m 'Add app user.' [master 36acafd] Add app user. 2 files changed, 2 insertions(+) create mode 100644 sql/deploy/appuser.sql create mode 100644 sql/revert/appuser.sql create mode 100644 sql/test/appuser.sql >sqitch --db-name flipr_test deploy Deploying 36acafd to flipr_test + appuser >
  • 114. Commit It! >git add . > git commit -m 'Add app user.' [master 36acafd] Add app user. 2 files changed, 2 insertions(+) create mode 100644 sql/deploy/appuser.sql create mode 100644 sql/revert/appuser.sql create mode 100644 sql/test/appuser.sql >sqitch --db-name flipr_test deploy Deploying 36acafd to flipr_test + appuser >
  • 115. Commit It! >git add . > git commit -m 'Add app user.' [master 36acafd] Add app user. 2 files changed, 2 insertions(+) create mode 100644 sql/deploy/appuser.sql create mode 100644 sql/revert/appuser.sql create mode 100644 sql/test/appuser.sql >sqitch --db-name flipr_test deploy Deploying 36acafd to flipr_test + appuser >psql -d flipr_test -c 'du flipr' List of roles Role name | Attributes | Member of -----------+------------+----------- flipr | | {}
  • 117. Status Update > sqitch -d flipr_test status # On database flipr_test # Tag: 36acafd # Step: appuser # Date: 2012-05-18 17:21:54 # Nothing to deploy (up-to-date) >
  • 119. Save My Fingers >sqitch config core.pg.db_name flipr_test >
  • 120. Save My Fingers >sqitch config core.pg.db_name flipr_test >sqitch status # On database flipr_test # Tag: 36acafd No --db-name # Step: appuser # Date: 2012-05-18 17:21:54 # Nothing to deploy (up-to-date) >
  • 122. Dependencies! > sqitch add-step users --requires appuser Created sql/deploy/users.sql -- requires: appuser Created sql/revert/users.sql Created sql/test/users.sql >
  • 123. Dependencies! > sqitch add-step users --requires appuser Created sql/deploy/users.sql -- requires: appuser Created sql/revert/users.sql Created sql/test/users.sql >
  • 124. Dependencies! > sqitch add-step users --requires appuser Created sql/deploy/users.sql -- requires: appuser Created sql/revert/users.sql Created sql/test/users.sql >emacs sql/deploy/users.sql
  • 125. sql/deploy/users.sql -- Deploy users -- :requires: appuser BEGIN; -- XXX Add DDLs here. COMMIT; sql/deploy/user
  • 126. sql/deploy/users.sql -- Deploy users -- :requires: appuser BEGIN; -- XXX Add DDLs here. COMMIT; sql/deploy/user
  • 127. sql/deploy/users.sql -- Deploy users -- :requires: appuser BEGIN; CREATE TABLE users ( nickname TEXT PRIMARY KEY, password TEXT NOT NULL, timestamp TIMESTAMPTZ NOT NULL DEFAULT NOW() ); GRANT SELECT ON users TO flipr; COMMIT; sql/deploy/user
  • 128. Dependencies! > sqitch add-step users --requires appuser Created sql/deploy/users.sql -- requires: appuser Created sql/revert/users.sql Created sql/test/users.sql > emacs sql/deploy/users.sql >
  • 129. Dependencies! > sqitch add-step users --requires appuser Created sql/deploy/users.sql -- requires: appuser Created sql/revert/users.sql Created sql/test/users.sql > emacs sql/deploy/users.sql >emacs sql/revert/users.sql
  • 130. sql/revert/users -- Revert users BEGIN; -- XXX Add DDLs here. COMMIT; sql/deploy/user
  • 131. sql/revert/users -- Revert users BEGIN; DROP TABLE users; COMMIT; sql/deploy/user
  • 133. Make Users >sqitch deploy --untracked Deploying HEAD+ to flipr_test + users >
  • 134. Make Users >sqitch deploy --untracked Deploying HEAD+ to flipr_test + users >
  • 135. Make Users >sqitch deploy --untracked Deploying HEAD+ to flipr_test + users > psql -d flipr_test -c 'd users' Table "public.users" Column | Type | Modifiers -----------+-------------+------------------------ nickname | text | not null password | text | not null timestamp | timestamptz | not null default now() Indexes: "users_pkey" PRIMARY KEY, btree (nickname) >
  • 137. Status Update > sqitch status # On database flipr_test # Tag: HEAD+ # Step: users # Date: 2012-05-18 17:25:39 # Nothing to deploy (up-to-date) >
  • 138. Status Update > sqitch status # On database flipr_test # Tag: HEAD+ # Step: users # Date: 2012-05-18 17:25:39 # Nothing to deploy (up-to-date) >sqitch revert --to HEAD Reverting HEAD+ from flipr_test - users >
  • 139. Status Update > sqitch status # On database flipr_test # Tag: HEAD+ # Step: users # Date: 2012-05-18 17:25:39 # Nothing to deploy (up-to-date) >sqitch revert --to HEAD Reverting HEAD+ from flipr_test - users >
  • 140. Check in and Deploy >
  • 141. Check in and Deploy >git add . > git commit -am 'Add users table.' [master fa650af] Add users table. 2 files changed, 16 insertions(+) create mode 100644 sql/deploy/users.sql create mode 100644 sql/revert/users.sql create mode 100644 sql/test/users.sql >
  • 142. Check in and Deploy >git add . > git commit -am 'Add users table.' [master fa650af] Add users table. 2 files changed, 16 insertions(+) create mode 100644 sql/deploy/users.sql create mode 100644 sql/revert/users.sql create mode 100644 sql/test/users.sql >sqitch deploy Deploying fa650af to flipr_test + users >
  • 144. Up to Date > sqitch status --show tags # On database flipr_test # Tag: fa650af # Step: users # Date: 2012-05-18 17:31:23 # # Tags: # fa650af - 2012-05-18 17:31:23 - david # 36acafd - 2012-05-18 17:25:39 - david # Nothing to deploy (up-to-date) >
  • 145. Up to Date > sqitch status --show tags # On database flipr_test # Tag: fa650af # Step: users # Date: 2012-05-18 17:31:23 # # Tags: # fa650af - 2012-05-18 17:31:23 - david # 36acafd - 2012-05-18 17:25:39 - david # Nothing to deploy (up-to-date) >
  • 146. Up to Date > sqitch status --show tags # On database flipr_test # Tag: fa650af # Step: users # Date: 2012-05-18 17:31:23 # # Tags: # fa650af - 2012-05-18 17:31:23 - david # 36acafd - 2012-05-18 17:25:39 - david # Nothing to deploy (up-to-date) >
  • 148. A Twofer >sqitch add-step insert_user -r users -r appuser Adding sql/deploy/insert_user.sql -- requires: users, appuser Adding sql/revert/insert_user.sql Adding sql/test/insert_user.sql >
  • 149. A Twofer >sqitch add-step insert_user -r users -r appuser Adding sql/deploy/insert_user.sql -- requires: users, appuser Adding sql/revert/insert_user.sql Adding sql/test/insert_user.sql >
  • 150. A Twofer >sqitch add-step insert_user -r users -r appuser Adding sql/deploy/insert_user.sql -- requires: users, appuser Adding sql/revert/insert_user.sql Adding sql/test/insert_user.sql > sqitch add-step change_pass -r users -r appuser Adding sql/deploy/change_pass.sql -- requires: users, appuser Adding sql/revert/change_pass.sql Adding sql/test/change_pass.sql >
  • 151. A Twofer >sqitch add-step insert_user -r users -r appuser Adding sql/deploy/insert_user.sql -- requires: users, appuser Adding sql/revert/insert_user.sql Adding sql/test/insert_user.sql > sqitch add-step change_pass -r users -r appuser Adding sql/deploy/change_pass.sql -- requires: users, appuser Adding sql/revert/change_pass.sql Adding sql/test/change_pass.sql >
  • 152. A Twofer >sqitch add-step insert_user -r users -r appuser Adding sql/deploy/insert_user.sql -- requires: users, appuser Adding sql/revert/insert_user.sql Adding sql/test/insert_user.sql > sqitch add-step change_pass -r users -r appuser Adding sql/deploy/change_pass.sql -- requires: users, appuser Adding sql/revert/change_pass.sql Adding sql/test/change_pass.sql >emacs sql/deploy/insert_user.sql
  • 153. sql/deploy/ insert_user.sql -- Deploy insert_user -- :requires: appuser -- :requires: users BEGIN; -- XXX Add DDLs here. COMMIT; sql/deploy/inse
  • 154. sql/deploy/ insert_user.sql -- Deploy insert_user -- :requires: appuser -- :requires: users BEGIN; -- XXX Add DDLs here. COMMIT; sql/deploy/inse
  • 155. sql/deploy/ insert_user.sql -- Deploy insert_user -- :requires: appuser -- :requires: users BEGIN; CREATE OR REPLACE FUNCTION insert_user( nickname TEXT, password TEXT ) RETURNS VOID LANGUAGE SQL SECURITY DEFINER AS $$ INSERT INTO users VALUES($1, md5($2)); $$; GRANT EXECUTE ON FUNCTION insert_user(TEXT, TEXT) TO flipr; COMMIT; sql/deploy/inse
  • 156. A Twofer >sqitch add-step insert_user -r users -r appuser Adding sql/deploy/insert_user.sql -- requires: users, appuser Adding sql/revert/insert_user.sql Adding sql/test/insert_user.sql > sqitch add-step change_pass -r users -r appuser Adding sql/deploy/change_pass.sql -- requires: users, appuser Adding sql/revert/change_pass.sql Adding sql/test/change_pass.sql >emacs sql/deploy/insert_user.sql >
  • 157. A Twofer >sqitch add-step insert_user -r users -r appuser Adding sql/deploy/insert_user.sql -- requires: users, appuser Adding sql/revert/insert_user.sql Adding sql/test/insert_user.sql > sqitch add-step change_pass -r users -r appuser Adding sql/deploy/change_pass.sql -- requires: users, appuser Adding sql/revert/change_pass.sql Adding sql/test/change_pass.sql >emacs sql/deploy/insert_user.sql >emacs sql/deploy/change_pass.sql
  • 158. sql/deploy/ change_pass.sql -- Deploy change_pass -- :requires: appuser -- :requires: users BEGIN; -- XXX Add DDLs here. COMMIT; sql/deploy/chan
  • 159. sql/deploy/ change_pass.sql -- Deploy change_pass -- :requires: appuser -- :requires: users BEGIN; CREATE OR REPLACE FUNCTION change_pass( nick TEXT, oldpass TEXT, newpass TEXT ) RETURNS BOOLEAN LANGUAGE plpgsql SECURITY DEFINER AS $$ BEGIN UPDATE users SET password = md5($3) WHERE nickname = $1 AND password = md5($2); RETURN FOUND; END; $$; GRANT EXECUTE ON FUNCTION change_pass(TEXT, TEXT, TEXT) TO flipr; COMMIT; sql/deploy/chan
  • 161. Deploy Functions >sqitch deploy --untracked Deploying HEAD+ to flipr_test + change_pass + insert_user >
  • 162. Deploy Functions >sqitch deploy --untracked Deploying HEAD+ to flipr_test + change_pass + insert_user >psql -d flipr_test -c 'df' List of function Schema | Name | Result data type | --------+-------------+------------------+---------- public | change_pass | boolean | nick text public | insert_user | void | nickname >
  • 165. Commit It sqitch revert --to HEAD git add && git commit
  • 166. Commit It sqitch revert --to HEAD git add && git commit sqitch deploy
  • 167. Commit It sqitch revert --to HEAD git add && git commit sqitch deploy And now…
  • 169. Stage It >git tag v1.0.0-dev1 -am 'Tag v1.0.0-dev1' >
  • 170. Stage It >git tag v1.0.0-dev1 -am 'Tag v1.0.0-dev1' >createdb flipr_dev > sqitch --db-name flipr_dev deploy Deploying 36acafd to flipr_dev + appuser Deploying fa650af to flipr_dev + users Deploying 803e6b8, v1.0.0-dev1 to flipr_dev + insert_user + change_pass >
  • 171. Stage It >git tag v1.0.0-dev1 -am 'Tag v1.0.0-dev1' >createdb flipr_dev > sqitch --db-name flipr_dev deploy Deploying 36acafd to flipr_dev + appuser Deploying fa650af to flipr_dev + users Deploying 803e6b8, v1.0.0-dev1 to flipr_dev + insert_user + change_pass >
  • 172. Stage It >git tag v1.0.0-dev1 -am 'Tag v1.0.0-dev1' >createdb flipr_dev > sqitch --db-name flipr_dev deploy Deploying 36acafd to flipr_dev + appuser Deploying fa650af to flipr_dev + users Deploying 803e6b8, v1.0.0-dev1 to flipr_dev + insert_user + change_pass >
  • 174. Stage Status? >sqitch --db-name flipr_dev status --show tags # On database flipr_dev # Tags: 803e6b8, v1.0.0-dev1 # Step: change_pass # Date: 2012-05-18 17:38:28 # # Tags: # 803e6b8, v1.0.0-dev1 - 2012-05-18 17:38:28 - david # fa650af - 2012-05-18 17:38:21 - david # 36acafd - 2012-05-18 17:38:15 - david # Nothing to deploy (up-to-date) >
  • 176. Distribution Bundling Bundle plan + scripts for deployment
  • 177. Distribution Bundling Bundle plan + scripts for deployment Plan generated from VCS history
  • 178. Distribution Bundling Bundle plan + scripts for deployment Plan generated from VCS history Package up as
  • 179. Distribution Bundling Bundle plan + scripts for deployment Plan generated from VCS history Package up as RPM
  • 180. Distribution Bundling Bundle plan + scripts for deployment Plan generated from VCS history Package up as RPM Debian Package
  • 181. Distribution Bundling Bundle plan + scripts for deployment Plan generated from VCS history Package up as RPM Debian Package Gem
  • 183. Ship It! >sqitch bundle --tags-only Bundling in bundle/ Config written to bundle/sqitch.conf Bundling v1.0.0-dev1 - appuser - users - change_pass - insert_user Plan written to bundle/sqitch.plan >
  • 184. Ship It! >sqitch bundle --tags-only Bundling in bundle/ Config written to bundle/sqitch.conf Bundling v1.0.0-dev1 - appuser - users - change_pass - insert_user Plan written to bundle/sqitch.plan >
  • 185. Ship It! >sqitch bundle --tags-only Bundling in bundle/ Config written to bundle/sqitch.conf Bundling v1.0.0-dev1 - appuser - users - change_pass - insert_user Plan written to bundle/sqitch.plan >
  • 186. Ship It! >sqitch bundle --tags-only Bundling in bundle/ Config written to bundle/sqitch.conf Bundling v1.0.0-dev1 - appuser - users - change_pass - insert_user Plan written to bundle/sqitch.plan >
  • 187. Ship It! >sqitch bundle --tags-only Bundling in bundle/ Config written to bundle/sqitch.conf Bundling v1.0.0-dev1 - appuser - users - change_pass - insert_user Plan written to bundle/sqitch.plan >emacs bundle/sqitch.plan
  • 190. Kick the Tires >cd bundle > createdb flipr_staging > sqitch --db-name flipr_staging deploy Deploying v1.0.0-dev1 to flipr_prod + appuser + users + insert_user + change_pass >
  • 191. Kick the Tires >cd bundle > createdb flipr_staging > sqitch --db-name flipr_staging deploy Deploying v1.0.0-dev1 to flipr_prod + appuser + users + insert_user + change_pass >
  • 193. Ch-Check it Out >sqitch --db-name flipr_prod status --show tags # On database flipr_prod # Tag: v1.0.0-dev1 # Step: change_pass # Date: 2012-04-09 22:17:38 # # Tags: # v1.0.0-dev1 - 2012-05-18 17:40:00 - david # Nothing to deploy (up-to-date) >
  • 194. Ch-Check it Out >sqitch --db-name flipr_prod status --show tags # On database flipr_prod # Tag: v1.0.0-dev1 # Step: change_pass No SHA1s # Date: 2012-04-09 22:17:38 # # Tags: # v1.0.0-dev1 - 2012-05-18 17:40:00 - david # Nothing to deploy (up-to-date) >
  • 196. Ruh-Roh >psql -d flipr_test -c " SELECT insert_user('foo', 'secr3t'), insert_user('bar', 'secr3t'); SELECT nickname, password FROM users; " nickname | password ----------+---------------------------------- foo | 9695da4dd567a19f9b92065f240c6725 bar | 9695da4dd567a19f9b92065f240c6725
  • 197. Ruh-Roh >psql -d flipr_test -c " SELECT insert_user('foo', 'secr3t'), insert_user('bar', 'secr3t'); SELECT nickname, password FROM users; " nickname | password ----------+---------------------------------- foo | 9695da4dd567a19f9b92065f240c6725 bar | 9695da4dd567a19f9b92065f240c6725 Not good.
  • 199. Add pgcrypto >sqitch add-step pgcrypto Adding sql/deploy/pgcrypto.sql Adding sql/revert/pgcrypto.sql Adding sql/test/pgcrypto.sql >
  • 200. Add pgcrypto >sqitch add-step pgcrypto Adding sql/deploy/pgcrypto.sql Adding sql/revert/pgcrypto.sql Adding sql/test/pgcrypto.sql >emacs sql/deploy/pgcrpyto.sql
  • 201. ssql/deploy/pgcrypto.sql -- Deploy pgcrypto BEGIN; -- XXX Add DDLs here. COMMIT; sql/deploy/pgcr
  • 202. ssql/deploy/pgcrypto.sql -- Deploy pgcrypto BEGIN; CREATE EXTENSION pgcrypto; COMMIT; sql/deploy/pgcr
  • 204. How to Modify? Copy insert_user.sql to new deploy file
  • 205. How to Modify? Copy insert_user.sql to new deploy file Change that new file
  • 206. How to Modify? Copy insert_user.sql to new deploy file Change that new file Copy insert_user.sql to new revert file
  • 207. How to Modify? Copy insert_user.sql to new deploy file Change that new file Copy insert_user.sql to new revert file Test it
  • 208. How to Modify? Copy insert_user.sql to new deploy file Change that new file Copy insert_user.sql to new revert file Test it Do the same for change_pass.sql
  • 209. How to Modify? Copy insert_user.sql to new deploy file Change that new file Copy insert_user.sql to new revert file Test it Do the same for change_pass.sql The problem with that…
  • 210. >
  • 211. > git diff HEAD^ diff --git a/sql/deploy/insert_user_crypt.sql b/sql/deploy/insert_user_cr new file mode 100644 index 0000000..fa8d0c6 --- /dev/null +++ b/sql/deploy/insert_user_crypt.sql @@ -0,0 +1,8 @@ +-- requires: users, appuser, pgcrypto + +CREATE OR REPLACE FUNCTION insert_user( + nickname TEXT, + password TEXT +) RETURNS VOID LANGUAGE SQL AS $$ + INSERT INTO users values($1, crypt($2, gen_salt('md5'))); +$$; diff --git a/sql/revert/insert_user_crypt.sql b/sql/revert/insert_user_cr new file mode 100644 index 0000000..a7f4e31 --- /dev/null +++ b/sql/revert/insert_user_crypt.sql @@ -0,0 +1,8 @@ +-- requires: users, appuser + +CREATE OR REPLACE FUNCTION insert_user( + nickname TEXT, + password TEXT +) RETURNS VOID LANGUAGE SQL AS $$ + INSERT INTO users values($1, md5($2)); +$$;
  • 212. > git diff HEAD^ diff --git a/sql/deploy/insert_user_crypt.sql b/sql/deploy/insert_user_cr new file mode 100644 index 0000000..fa8d0c6 --- /dev/null +++ b/sql/deploy/insert_user_crypt.sql @@ -0,0 +1,8 @@ +-- requires: users, appuser, pgcrypto + +CREATE OR REPLACE FUNCTION insert_user( + nickname TEXT, + password TEXT +) RETURNS VOID LANGUAGE SQL AS $$ + INSERT INTO users values($1, crypt($2, gen_salt('md5'))); +$$; diff --git a/sql/revert/insert_user_crypt.sql b/sql/revert/insert_user_cr new file mode 100644 index 0000000..a7f4e31 --- /dev/null +++ b/sql/revert/insert_user_crypt.sql @@ -0,0 +1,8 @@ +-- requires: users, appuser + +CREATE OR REPLACE FUNCTION insert_user( + nickname TEXT, + password TEXT +) RETURNS VOID LANGUAGE SQL AS $$ + INSERT INTO users values($1, md5($2)); +$$; Oy.
  • 213. Use the VCS, Luke
  • 214. Use the VCS, Luke Just modify deploy scripts directly
  • 215. Use the VCS, Luke Just modify deploy scripts directly Requirement:
  • 216. Use the VCS, Luke Just modify deploy scripts directly Requirement: Change must be idempotent
  • 217. Use the VCS, Luke Just modify deploy scripts directly Requirement: Change must be idempotent Same result no matter how often applied
  • 218. Use the VCS, Luke Just modify deploy scripts directly Requirement: Change must be idempotent Same result no matter how often applied CREATE OR REPLACE FUNCTION is idempotent
  • 219. Use the VCS, Luke Just modify deploy scripts directly Requirement: Change must be idempotent Same result no matter how often applied CREATE OR REPLACE FUNCTION is idempotent So change procedures in place!
  • 221. What’s the Diff? >diff -u sql/deploy/insert_user.sql @@ -1,8 +1,8 @@ --- requires: users, appuser +-- requires: users, appuser, pgcrypto CREATE OR REPLACE FUNCTION insert_user( nickname TEXT, password TEXT ) RETURNS VOID LANGUAGE SQL AS $$ - INSERT INTO users values($1, md5($2)); + INSERT INTO users values($1, crypt($2, gen_salt('md5'))); $$;
  • 223. What’s the Diff? >diff -u sql/deploy/change_pass.sql @@ -1,4 +1,4 @@ --- requires: users, appuser +-- requires: users, appuser, pgcrypto CREATE OR REPLACE FUNCTION change_pass( nick TEXT, @@ -7,9 +7,9 @@ CREATE OR REPLACE FUNCTION change_pass( ) RETURNS BOOLEAN LANGUAGE plpgsql AS $$ BEGIN UPDATE users - SET password = md5($3) + SET password = crypt($3, gen_salt('md5')) WHERE nickname = $1 - AND password = md5($2); + AND password = crypt($2, password); RETURN FOUND; END;
  • 225. Send it Up! >sqitch deploy --untracked Deploying HEAD+ to flipr_test + insert_user + change_pass >
  • 226. Send it Up! >sqitch deploy --untracked Deploying HEAD+ to flipr_test + insert_user + change_pass >psql -d flipr_test -c " DELETE FROM users; SELECT insert_user('foo', 'secr3t'), insert_user('bar', 'secr3t'); SELECT nickname, password FROM users; " nickname | password ----------+------------------------------------ foo | $1$l6OEKyF3$kv5ae7505ROub75d9QKTh/ bar | $1$J4NJDgaJ$578i9Lt6b8ohJwi6WhNNO1 >
  • 227. Send it Up! >sqitch deploy --untracked Deploying HEAD+ to flipr_test + insert_user + change_pass >psql -d flipr_test -c " o/ DELETE FROM users; SELECT insert_user('foo', 'secr3t'), insert_user('bar', 'secr3t'); SELECT nickname, password FROM users; " nickname | password ----------+------------------------------------ foo | $1$l6OEKyF3$kv5ae7505ROub75d9QKTh/ bar | $1$J4NJDgaJ$578i9Lt6b8ohJwi6WhNNO1 >
  • 228. Can We Go Back? >
  • 229. Can We Go Back? >sqitch revert --to HEAD Reverting HEAD+ from flipr_test - change_pass - insert_user >
  • 230. Can We Go Back? >sqitch revert --to HEAD Reverting HEAD+ from flipr_test - change_pass - insert_user >psql -d flipr_test -c " DELETE FROM users; SELECT insert_user('foo', 'secr3t'), insert_user('bar', 'secr3t'); SELECT nickname, password FROM users; " nickname | password ----------+---------------------------------- foo | 9695da4dd567a19f9b92065f240c6725 bar | 9695da4dd567a19f9b92065f240c6725 >
  • 232. What About Bundling? > git tag v1.0.0-b1 -am 'Tag v1.0.0-b1' > sqitch bundle --tags-only Bundling in bundle/ Config written to bundle/sqitch.conf Bundling v1.0.0-dev1 - appuser - users - change_pass - insert_user Bundling v1.0.0-b1 - change_pass_v2 - insert_user_v2 Plan written to bundle/sqitch.plan >
  • 233. What About Bundling? > git tag v1.0.0-b1 -am 'Tag v1.0.0-b1' > sqitch bundle --tags-only Bundling in bundle/ Config written to bundle/sqitch.conf Bundling v1.0.0-dev1 - appuser - users - change_pass - insert_user Bundling v1.0.0-b1 - change_pass_v2 - insert_user_v2 Plan written to bundle/sqitch.plan >
  • 234. What About Bundling? > git tag v1.0.0-b1 -am 'Tag v1.0.0-b1' > sqitch bundle --tags-only Bundling in bundle/ Config written to bundle/sqitch.conf Bundling v1.0.0-dev1 - appuser - users - change_pass - insert_user Bundling v1.0.0-b1 - change_pass_v2 - insert_user_v2 Plan written to bundle/sqitch.plan >
  • 235. What About Bundling? > git tag v1.0.0-b1 -am 'Tag v1.0.0-b1' > sqitch bundle --tags-only Bundling in bundle/ Config written to bundle/sqitch.conf Bundling v1.0.0-dev1 - appuser - users - change_pass - insert_user Bundling v1.0.0-b1 - change_pass_v2 - insert_user_v2 Plan written to bundle/sqitch.plan >emacs bundle/sqitch.plan
  • 236. What’s the Plan? [v1.0.0-dev1] appuser users change_pass insert_user [v1.0.0-b1] change_pass_v2 insert_user_v2 filename
  • 238. Make it So >cd bundle > sqitch -d flipr_staging deploy Deploying v1.0.0-b1 to flipr_staging + change_pass_v2 + insert_user_v2 >
  • 239. Make it So >cd bundle > sqitch -d flipr_staging deploy Deploying v1.0.0-b1 to flipr_staging + change_pass_v2 + insert_user_v2 > sqitch -d flipr_staging status # On database flipr_staging # Tag: v1.0.0-b1 # Step: insert_user_v2 # Date: 2012-05-18 17:51:35 # Nothing to deploy (up-to-date) >
  • 242. Other Commands log - Like git log
  • 243. Other Commands log - Like git log check - Validate plan & database
  • 244. Other Commands log - Like git log check - Validate plan & database test - Test deployment success
  • 245. Other Commands log - Like git log check - Validate plan & database test - Test deployment success help - Get it
  • 247. Current Status Working on it full time
  • 248. Current Status Working on it full time Rethinking VCS integration
  • 249. Current Status Working on it full time Rethinking VCS integration Rely more on plan file
  • 250. Current Status Working on it full time Rethinking VCS integration Rely more on plan file Complement with VCS history
  • 251. Current Status Working on it full time Rethinking VCS integration Rely more on plan file Complement with VCS history Tools for plan file management
  • 253. Fork It http:/ /sqitch.org/
  • 254. Fork It http:/ /sqitch.org/ https:/ /github.com/theory/sqitch/
  • 255. Fork It http:/ /sqitch.org/ https:/ /github.com/theory/sqitch/ Opinions wanted
  • 256. Fork It http:/ /sqitch.org/ https:/ /github.com/theory/sqitch/ Opinions wanted Coders wanted
  • 257. Fork It http:/ /sqitch.org/ https:/ /github.com/theory/sqitch/ Opinions wanted Coders wanted Doc writers and web designers wanted!
  • 258. Fork It http:/ /sqitch.org/ https:/ /github.com/theory/sqitch/ Opinions wanted Coders wanted Doc writers and web designers wanted! Make it great!
  • 260. Simple SQL Change Management with Sqitch David E. Wheeler http:/ /sqitch.org/ PGCon 2012 Ottawa, Canada Text: Attribution-Noncommercial-Share Alike 3.0 United States: http://creativecommons.org/licenses/by-nc-sa/3.0/us/ Images licensed independently and © Their respective owners.

Editor's Notes

  1. TODO:\n&amp;#x2022; Add more privilege stuff?\n&amp;#x2022; Add example of renaming `flips.timestamp`?\n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n
  43. \n
  44. \n
  45. \n
  46. \n
  47. \n
  48. \n
  49. \n
  50. \n
  51. \n
  52. \n
  53. \n
  54. \n
  55. \n
  56. \n
  57. \n
  58. \n
  59. \n
  60. \n
  61. \n
  62. \n
  63. \n
  64. \n
  65. \n
  66. \n
  67. \n
  68. \n
  69. \n
  70. \n
  71. \n
  72. \n
  73. \n
  74. \n
  75. \n
  76. \n
  77. \n
  78. \n
  79. \n
  80. \n
  81. \n
  82. \n
  83. \n
  84. \n
  85. \n
  86. \n
  87. \n
  88. \n
  89. \n
  90. \n
  91. \n
  92. \n
  93. \n
  94. \n
  95. \n
  96. \n
  97. \n
  98. \n
  99. \n
  100. \n
  101. \n
  102. \n
  103. \n
  104. \n
  105. \n
  106. \n
  107. \n
  108. \n
  109. \n
  110. \n
  111. \n
  112. \n
  113. \n
  114. \n
  115. \n
  116. \n
  117. \n
  118. \n
  119. \n
  120. \n
  121. \n
  122. \n
  123. \n
  124. \n
  125. \n
  126. \n
  127. \n
  128. \n
  129. \n
  130. \n
  131. \n
  132. \n
  133. \n
  134. \n
  135. \n
  136. \n
  137. \n
  138. \n
  139. \n
  140. \n
  141. \n
  142. \n
  143. \n
  144. \n
  145. \n
  146. \n
  147. \n
  148. \n
  149. \n
  150. \n
  151. \n
  152. \n
  153. \n
  154. \n
  155. \n
  156. \n
  157. \n
  158. \n
  159. \n
  160. \n
  161. \n
  162. \n
  163. \n
  164. \n
  165. \n
  166. \n
  167. \n
  168. \n
  169. \n
  170. \n
  171. \n
  172. \n
  173. \n
  174. \n
  175. \n
  176. \n
  177. \n
  178. \n
  179. \n
  180. \n
  181. \n
  182. \n
  183. \n
  184. \n
  185. \n
  186. \n
  187. \n
  188. \n
  189. \n
  190. \n
  191. \n
  192. \n
  193. \n
  194. \n
  195. \n
  196. \n
  197. \n
  198. \n
  199. \n
  200. \n
  201. \n
  202. \n
  203. \n
  204. \n
  205. \n
  206. \n
  207. \n
  208. \n
  209. \n
  210. \n
  211. \n
  212. \n
  213. \n
  214. \n
  215. \n
  216. \n
  217. \n
  218. \n
  219. \n
  220. \n
  221. \n
  222. \n
  223. \n
  224. \n
  225. \n
  226. \n
  227. \n
  228. \n
  229. \n
  230. \n
  231. \n
  232. \n
  233. \n
  234. \n
  235. \n
  236. \n
  237. \n
  238. \n
  239. \n
  240. \n
  241. \n
  242. \n
  243. \n
  244. \n
  245. \n
  246. \n
  247. \n
  248. \n
  249. \n
  250. \n
  251. \n
  252. \n
  253. \n
  254. \n
  255. \n
  256. \n
  257. \n
  258. \n
  259. \n
  260. \n
  261. \n
  262. \n
  263. \n
  264. \n
  265. \n
  266. \n
  267. \n
  268. \n
  269. \n
  270. \n
  271. \n
  272. \n
  273. \n
  274. \n
  275. \n
  276. \n
  277. \n
  278. \n
  279. \n
  280. \n
  281. \n
  282. \n
  283. \n
  284. \n
  285. TODO:\n&amp;#x2022; Add more privilege stuff?\n&amp;#x2022; Add example of renaming `flips.timestamp`?\n