App-Sqitch

 view release on metacpan or  search on metacpan

lib/sqitchtutorial-firebird.pod  view on Meta::CPAN

of our projects:

  > sqitch config --user user.name 'Marge N. O’Vera'
  > sqitch config --user user.email 'marge@example.com'

Have a look at F<~/.sqitch/sqitch.conf> and you'll see something like
this:

  > cat ~/.sqitch/sqitch.conf
  [engine "firebird"]
    client = /opt/local/bin/isql
  [user]
    name = Marge N. O’Vera
    email = marge@example.com

Which means that Sqitch should be able to find C<isql> for any project, and
that it will always properly identify us when planning and committing changes.

Back to the repository. Have a look at the plan file, F<sqitch.plan>:

  > cat sqitch.plan
  %syntax-version=1.0.0
  %project=flipr
  %uri=https://github.com/sqitchers/sqitch-firebird-intro/
  

Note that it has picked up on the name and URI of the app we're building.
Sqitch uses this data to manage cross-project dependencies. The
C<%syntax-version> pragma is always set by Sqitch, so that it always knows how
to parse the plan, even if the format changes in the future.

Let's commit these changes and start creating the database changes.

  > git add .
  > git commit -am 'Initialize Sqitch configuration.'
  [main 2177ce4] Initialize Sqitch configuration.
   2 files changed, 19 insertions(+), 0 deletions(-)
   create mode 100644 sqitch.conf
   create mode 100644 sqitch.plan

Let's create our flipr test database using C<isql>:

  > sudo -u firebird mkdir /tmp/flipr_test
  > echo "CREATE DATABASE 'localhost:/tmp/flipr_test/flipr.fdb'; exit;" \
    | isql-fb -q -u SYSDBA -p masterkey

=head1 Our First Change

Let's create a table. Our app will need users, of course, so we'll create a
table for them. Run this command:

  > sqitch add users -n 'Creates table to track our users.'
  Created deploy/users.sql
  Created revert/users.sql
  Created verify/users.sql
  Added "users" to sqitch.plan

The L<C<add>|sqitch-add> command adds a database change to the plan and writes
deploy, revert, and verify scripts that represent the change. Now we edit
these files. The C<deploy> script's job is to create the table. By default,
the F<deploy/users.sql> file looks like this:

  -- Deploy flipr:users to firebird

  -- XXX Add DDLs here.

  COMMIT;

What we want to do is to replace the C<XXX> comment with the C<CREATE TABLE>
statement, like so:

  -- Deploy flipr:users to firebird

  CREATE TABLE users (
      nickname   VARCHAR(50)  PRIMARY KEY,
      password   VARCHAR(512) NOT NULL,
      fullname   VARCHAR(512) NOT NULL,
      twitter    VARCHAR(512) NOT NULL,
      created_at TIMESTAMP    DEFAULT CURRENT_TIMESTAMP NOT NULL
  );

  COMMIT;

The C<revert> script's job is to precisely revert the change to the deploy
script, so we edit this to F<revert/users.sql> to look like this:

  -- Revert flipr:users from firebird

  DROP TABLE users;

  COMMIT;

Now we can try deploying this change. We tell Sqitch where to send the change
via a L<database URI|https://github.com/libwww-perl/uri-db/>. Here we've
specified a database file, F</tmp/flipr_test/flipr.fdb>:

  > sqitch deploy db:firebird://sysdba:masterkey@localhost//tmp/flipr_test/flipr.fdb
  Adding registry tables to db:firebird://sysdba:@localhost//tmp/flipr_test/sqitch.fdb
  Deploying changes to db:firebird://sysdba:@localhost//tmp/flipr_test/flipr.fdb
    + users .. ok

First Sqitch created the registry database and tables used to track database
changes. The registry is separate from the database to which the C<users>
change was deployed; by default, its name is C<sqitch.$suffix>, where
C<$suffix> is the same as the suffix on the target database, if any. It lives
in the same directory as the target database, which means that one registry
database is used for all the databases with the same suffix in a single
directory. In this case, we should end up with two databases:

=over

=item * F</tmp/flipr_test/sqitch.fdb>

The Sqitch registry database.

=item * F</tmp/flipr_test/flipr.fdb>

The database Sqitch manages.

=back

lib/sqitchtutorial-firebird.pod  view on Meta::CPAN


  > git reset --hard HEAD
  HEAD is now at d5e7e86 Merge branch 'lists'

That throws out our botched merge. Now let's go back to our branch and rebase
it on C<main>:

  > git checkout hashtags
  Switched to branch 'hashtags'
  > git rebase main
  First, rewinding head to replay your work on top of it...
  Applying: Add hashtags table.
  Using index info to reconstruct a base tree...
  M	sqitch.plan
  Falling back to patching base and 3-way merge...
  Auto-merging sqitch.plan
  CONFLICT (content): Merge conflict in sqitch.plan
  Failed to merge in the changes.
  Patch failed at 0001 Add hashtags table.
  The copy of the patch that failed is found in:
     .git/rebase-apply/patch

  When you have resolved this problem, run "git rebase --continue".
  If you prefer to skip this patch, run "git rebase --skip" instead.
  To check out the original branch and stop rebasing, run "git rebase --abort".

Oy, that's kind of a pain. It seems like no matter what we do, we'll need to
resolve conflicts in that file. Except in Git. Fortunately for us, we can tell
Git to resolve conflicts in F<sqitch.plan> differently. Because we only ever
append lines to the file, we can have it use the "union" merge driver, which,
according to L<its
docs|https://git-scm.com/docs/gitattributes#_built-in_merge_drivers>:

=over

Run 3-way file level merge for text files, but take lines from both versions,
instead of leaving conflict markers. This tends to leave the added lines in
the resulting file in random order and the user should verify the result. Do
not use this if you do not understand the implications.

=back

This has the effect of appending lines from all the merging files, which is
exactly what we need. So let's give it a try. First, back out the botched
rebase:

  > git rebase --abort

Now add the union merge driver to F<.gitattributes> for F<sqitch.plan>
and rebase again:

  > echo sqitch.plan merge=union > .gitattributes
  > git rebase main
  First, rewinding head to replay your work on top of it...
  Applying: Add hashtags table.
  Using index info to reconstruct a base tree...
  M sqitch.plan
  Falling back to patching base and 3-way merge...
  Auto-merging sqitch.plan

Ah, that looks a bit better. Let's have a look at the plan:

  > cat sqitch.plan
  %syntax-version=1.0.0
  %project=flipr
  %uri=https://github.com/sqitchers/sqitch-firebird-intro/

  users 2014-01-05T22:01:30Z Marge N. O’Vera <marge@example.com> # Creates table to track our users.
  flips [users] 2014-01-05T22:21:24Z Marge N. O’Vera <marge@example.com> # Adds table for storing flips.
  userflips [users flips] 2014-01-05T22:40:29Z Marge N. O’Vera <marge@example.com> # Creates the userflips view.
  @v1.0.0-dev1 2014-01-05T22:42:36Z Marge N. O’Vera <marge@example.com> # Tag v1.0.0-dev1.

  lists [flips] 2014-01-05T22:44:41Z Marge N. O’Vera <marge@example.com> # Adds table for storing lists.
  hashtags [flips] 2014-01-05T22:54:27Z Marge N. O’Vera <marge@example.com> # Adds table for storing hashtags.

Note that it has appended the changes from the merged "lists" branch, and then
merged the changes from our "hashtags" branch. Test it to make sure it works
as expected:

  > sqitch rebase -y
  Reverting all changes from flipr_test
    - hashtags ................ ok
    - userflips @v1.0.0-dev1 .. ok
    - flips ................... ok
    - users ................... ok
  Deploying changes to flipr_test
    + users ................... ok
    + flips ................... ok
    + userflips @v1.0.0-dev1 .. ok
    + lists ................... ok
    + hashtags ................ ok

Note the use of L<C<rebase>|sqitch-rebase>, which combines a
L<C<revert>|sqitch-revert> and a L<C<deploy>|sqitch-deploy> into a single
command. Handy, right? It correctly reverted our changes, and then deployed
them all again in the proper order. So let's commit F<.gitattributes>; seems
worthwhile to keep that change:

  > git add .
  > git commit -m 'Add `.gitattributes` with union merge for `sqitch.plan`.'
  [hashtags 52ed9a2] Add `.gitattributes` with union merge for `sqitch.plan`.
   1 files changed, 1 insertions(+), 0 deletions(-)
   create mode 100644 .gitattributes

=head2 Merges Mastered

And now, finally, we can merge into C<main>:

  > git checkout main
  Switched to branch 'main'
  > git merge --no-ff hashtags -m "Merge branch 'hashtags'"
  Merge made by recursive.
   .gitattributes      |    1 +
   deploy/hashtags.sql |   10 ++++++++++
   revert/hashtags.sql |    5 +++++
   sqitch.plan         |    1 +
   verify/hashtags.sql |    5 +++++
   5 files changed, 22 insertions(+), 0 deletions(-)
   create mode 100644 .gitattributes
   create mode 100644 deploy/hashtags.sql
   create mode 100644 revert/hashtags.sql



( run in 1.501 second using v1.01-cache-2.11-cpan-39bf76dae61 )