Recipe: Verifying PostgreSQL schema migrations with plain SQL

Sqitch verify made simple

Sergii Tkachenko
JWP Product & Engineering
3 min readJan 24, 2019

--

Recipes are the new series of short-form posts to JW Player engineering blog. Their objective is promoting healthy coding hygiene and sharing hard-won practical knowledge.

You can treat them just as cooking recipes, a step-by-step set of instructions. In recipes, we’ll capture day in and day out of our engineers: best security practices, ready-made solutions for specific problems, tips, tricks, and opinions. Recipes may not get deep into the weeds or provide comprehensive details, but they will always be practical and useful.

Problem

In JW Player we use Sqitch to run database migrations. We love Sqitch for its pure plain SQL approach which makes it suitable for use with any language or framework. Database schema changes (called deploy step) and their counterpart rollbacks (called revert step) are easily written in plain SQL, as they’re meant to be.

Having said that, there’s one more step called verify and writing it in plain SQL isn’t as straightforward. This step is used to ensure instructions in deploy step did precisely what you expect them to do.

Sqitch PostgreSQL tutorial provides a couple of examples of verify step.

In one example, they ensure schema flipr exists. The offered approach is rather implicit: it uses division by zero error to check whether the query finds matching rows.

No matched records results inCOUNT(*) = 0, which makes PostgreSQL run1/0 and fail with ERROR: division by zero.

Another example is dangerously misleading:

At first glance, this step ensures the current user has usage privilege on schema flipr. SELECT true should pass the verification and SELECT false should fail, right? Well, that’s not what’s happening.

This verify step will not fail on pg_catalog.has_schema_privilege() returning false! It will pass even when the user has no usage rights.

What this step actually does is the same as the first example: verifying that schema flipr exists. If it’s not, has_schema_privilege() throws an error. It has nothing to do with schema privileges.

Solution

PostgreSQL has built-in procedural language PL/pgSQL (yep, mouthful). Postgres v9.5+ brings anonymous functions and ASSERT / RAISE statements into PL/pgSQL. This makes it perfect for test assertions.

You can verify that the matching record is found:

This works perfectly with any built-in function returning a boolean:

This time it does exactly what you’d expect: ensure the current user has usage rights on flipr schema.

You can even use variables to perform more complex checks.

This example ensures the record with id=1 in pipelines table has name field equal Example.

Remarks

  • The integrity of your PostgreSQL schema migrations can easily be verified using built-in PL/pgSQL procedural language. You can learn about its features in PostgreSQL Documentation.
  • Open source is ingrained in JW Player’s DNA. Open source contributions are highly encouraged. We’ve submitted our PL/pgSQL examples to Sqitch PostgreSQL tutorial: https://github.com/sqitchers/sqitch/pull/425

--

--

JWP Product & Engineering
JWP Product & Engineering

Published in JWP Product & Engineering

A technical blog about delivering online video at scale.

Sergii Tkachenko
Sergii Tkachenko

Written by Sergii Tkachenko

Senior Software Engineer at @jwplayer. Proprietary by day, MIT by night.

Responses (2)