<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Remo</title>
    <description>The latest articles on DEV Community by Remo (@monacoremo).</description>
    <link>https://dev.to/monacoremo</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F317856%2F53642a22-6147-4f2e-8dd1-d924f70201ec.png</url>
      <title>DEV Community: Remo</title>
      <link>https://dev.to/monacoremo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/monacoremo"/>
    <language>en</language>
    <item>
      <title>How to simply get your dependencies with Nix</title>
      <dc:creator>Remo</dc:creator>
      <pubDate>Sun, 19 Jan 2020 09:33:02 +0000</pubDate>
      <link>https://dev.to/monacoremo/how-to-simply-get-your-dependencies-with-nix-2ce1</link>
      <guid>https://dev.to/monacoremo/how-to-simply-get-your-dependencies-with-nix-2ce1</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;If you haven't hear of Nix yet - that's perfect! If you have looked into it and came off it a bit bewildered... I understand. Nix can seem very unusual at first, but it can also be of tremendous value for your software projects. I hope we can start fresh for this post. 🙂&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Managing dependencies and creating reproducible environments is a Very Hard™ problem
&lt;/h1&gt;

&lt;p&gt;Managing dependencies in software development can be a major pain, and we created a plethora of solutions for it: We have apt, npm, brew, pip, gem, rpm, just to name a few... We also use containers like Docker to manage software packages and create relatively reproducible environments.&lt;/p&gt;

&lt;p&gt;All of those solutions have their limitations. Either they are specific to some language (&lt;code&gt;pip&lt;/code&gt; for Python, &lt;code&gt;gem&lt;/code&gt; for Ruby, &lt;code&gt;stack&lt;/code&gt; for Haskell...), to some OS (&lt;code&gt;apt&lt;/code&gt; for Debian/Ubuntu, &lt;code&gt;rpm&lt;/code&gt; for Fedora &amp;amp; co. ...), to some part of our stack (backend/frontend), or they come with extra complexity (containers). They can be more or less reliable (&lt;code&gt;npm&lt;/code&gt;), their results are more or less reproducible. Few solutions are able to sensibly manage multiple versions of the same package.&lt;/p&gt;

&lt;h1&gt;
  
  
  The solution to all dependency management pains
&lt;/h1&gt;

&lt;p&gt;The solution is &lt;a href="https://xkcd.com/927/"&gt;obvious&lt;/a&gt;: We need another package manager to rule them all!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://nixos.org/"&gt;Nix&lt;/a&gt; is getting remarkably close to being an ideal cross-OS, cross-language, cross-stack package manager, while being extremely reliable and reproducible. Of course, it's not perfect and it has its own set of trade-offs and limitations. There is a lot to explain on Nix, how there is a functional programming language called &lt;code&gt;Nix&lt;/code&gt;, a package repository called &lt;code&gt;Nixpkgs&lt;/code&gt;, a whole operating system called &lt;code&gt;NixOS&lt;/code&gt;... and a lot more. But for this post, I would like to show you a simple, minimal use-case that might already be very valuable to you!&lt;/p&gt;

&lt;h1&gt;
  
  
  Simple example: Managing development dependencies with Nix
&lt;/h1&gt;

&lt;p&gt;Let's say that for hacking on one of our projects we need &lt;a href="https://curl.haxx.se/"&gt;&lt;code&gt;curl&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://stedolan.github.io/jq/"&gt;&lt;code&gt;jq&lt;/code&gt;&lt;/a&gt;, &lt;a href="http://eradman.com/entrproject/"&gt;&lt;code&gt;entr&lt;/code&gt;&lt;/a&gt; and &lt;a href="http://eradman.com/ephemeralpg/"&gt;&lt;code&gt;pg_tmp&lt;/code&gt;&lt;/a&gt;. &lt;code&gt;pg_tmp&lt;/code&gt; in turn depends on the &lt;a href="https://www.postgresql.org/"&gt;Postgres&lt;/a&gt; binaries. This is how to get all that with Nix:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install Nix&lt;/span&gt;
curl https://nixos.org/nix/install | sh

&lt;span class="c"&gt;# Create a `shell.nix` file&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; shell.nix &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
let
  pkgs = import &amp;lt;nixpkgs&amp;gt; {};
in
pkgs.stdenv.mkDerivation {
  name = "my-env";

  buildInputs =
    [
      pkgs.curl
      pkgs.jq
      pkgs.entr
      pkgs.ephemeralpg
    ];
}
&lt;/span&gt;&lt;span class="no"&gt;EOF

&lt;/span&gt;&lt;span class="c"&gt;# Run `nix-shell`&lt;/span&gt;
nix-shell

&lt;span class="c"&gt;# Have all dependencies that we need ready to go on your $PATH! 🎉&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;That's it!&lt;/p&gt;

&lt;p&gt;Installing Nix as above is a relatively invasive change to your system, for example you will find a new '/nix/' directory in your root file system. I would recommend to try this out in a virtual machine or Docker container first.&lt;/p&gt;

&lt;p&gt;I guess it makes sense for me to explain a little bit more on what is happening here and how you can use it. &lt;/p&gt;

&lt;h1&gt;
  
  
  Parts of the Nix ecosystem that we use in this example
&lt;/h1&gt;

&lt;p&gt;We are using three parts of the Nix ecosystem.&lt;/p&gt;

&lt;h2&gt;
  
  
  1/3: The Nix programming language
&lt;/h2&gt;

&lt;p&gt;It's a very small language, the syntax can be described on &lt;a href="https://nixos.wiki/wiki/Nix_Expression_Language"&gt;one page&lt;/a&gt;. If you are familiar with functional programming languages (especially from the ML family, Haskell, Elm), you will be right at home. If you are not, it might seem quite alien and restrictive (no loops?!). &lt;/p&gt;

&lt;p&gt;Everything in the Nix language is an expression, that is everything you write evaluates to a value. The language is mostly pure: Most function calls have no side effects and will always return the same result for the same inputs. The remaining impurities are mostly taken care of with cryptographic hashes. Based on this, the results of any Nix expression are highly reproducible.&lt;/p&gt;

&lt;h2&gt;
  
  
  2/3: The Nix packages repository
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/NixOS/nixpkgs"&gt;Nixpkgs&lt;/a&gt; is one huge, but well organized Nix expression that defines how over 40,000 software packages can be built, including &lt;em&gt;all&lt;/em&gt; their dependencies. It's currently over 17 mb in total.&lt;/p&gt;

&lt;p&gt;The Nix programming language keeps working with this huge expression efficient by being lazy and only evaluating the parts of it that you currently need. &lt;/p&gt;

&lt;p&gt;Nixpkgs is where a lot of the complexity that you might encounter with Nix comes from. Abstractions like &lt;code&gt;mkDerivation&lt;/code&gt;, &lt;code&gt;callPackage&lt;/code&gt; etc. are great for taking out repetition and keeping Nixpkgs maintainable, but their abstractions can be quite difficult to understand. Thinking too much about some of them makes my head hurt.&lt;/p&gt;

&lt;h2&gt;
  
  
  3/3: The &lt;code&gt;nix-shell&lt;/code&gt; utility
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://nixos.org/nixos/nix-pills/developing-with-nix-shell.html"&gt;&lt;code&gt;nix-shell&lt;/code&gt;&lt;/a&gt; binary loads a Nix expression from a file (by default from the files &lt;code&gt;shell.nix&lt;/code&gt; or, if that one doesn't exist, &lt;code&gt;default.nix&lt;/code&gt;), evaluates that expression and then drops us in a shell where all dependencies defined in the expression are (magically) available.&lt;/p&gt;

&lt;h1&gt;
  
  
  More explanations and details
&lt;/h1&gt;

&lt;p&gt;With that said, let's go through the example above in more detail.&lt;/p&gt;

&lt;h2&gt;
  
  
  The &lt;code&gt;shell.nix&lt;/code&gt; file explained
&lt;/h2&gt;

&lt;p&gt;Let's have another look at the &lt;code&gt;shell.nix&lt;/code&gt; file that we created earlier:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt;
  &lt;span class="nv"&gt;pkgs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;nixpkgs&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
&lt;span class="kn"&gt;in&lt;/span&gt;
&lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;stdenv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;mkDerivation&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"my-env"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nv"&gt;buildInputs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;curl&lt;/span&gt;
      &lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;jq&lt;/span&gt;
      &lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;entr&lt;/span&gt;
      &lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;ephemeralpg&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;let [DEFINITIONS] in [EXPRESSION]&lt;/code&gt; expression allows us to define variables in a local scope in the first part after &lt;code&gt;let&lt;/code&gt;, and then evaluates the second part after &lt;code&gt;in&lt;/code&gt; with that scope. Accordingly, the variable &lt;code&gt;pkgs&lt;/code&gt; defined in the first part can be used in the second part.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;import &amp;lt;nixpkgs&amp;gt; {}&lt;/code&gt; on the second line is how we import the Nixpkgs expression that is available in our Nix installation by default. I'll explain in a separate post how to 'pin' the Nixpkgs to one specific, reproducible version.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;pkgs.stdenv.mkDerivation&lt;/code&gt; is a &lt;a href="https://nixos.org/nixos/nix-pills/fundamentals-of-stdenv.html"&gt;complex function&lt;/a&gt; that is used all over Nixpkgs to define how different packages can be built. All we need to know about it for now, is that it takes a set (&lt;code&gt;{...}&lt;/code&gt;) as an argument and returns a derivation (that is 'something that can be built' in Nix parlance). The build inputs will be able on our path if we run this expression in &lt;code&gt;nix-shell&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;name = "my-env";&lt;/code&gt; we set the &lt;code&gt;name&lt;/code&gt; attribute of the set we use as an argument to &lt;code&gt;mkDerivation&lt;/code&gt;. It doesn't really matter what we put here.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;buildInputs&lt;/code&gt; is the most important part: We set it to a list of derivations that we want to have available in our &lt;code&gt;nix-shell&lt;/code&gt;. The items of our list are separated by spaces. We simply use attributes from the &lt;code&gt;pkgs&lt;/code&gt; value. Remember that &lt;code&gt;pkgs&lt;/code&gt; resulted from importing the huge Nixpkgs Nix expression, so it contains all of the over 40,000 packages in its attributes. We just pick out the right ones.&lt;/p&gt;

&lt;p&gt;Finding the right attributes on Nixpkgs is not always simple, but a bit of googling goes a long way. For example, Google told me that &lt;code&gt;pg_tmp&lt;/code&gt; is part of the &lt;code&gt;ephemeralpg&lt;/code&gt; package in Nix.&lt;/p&gt;

&lt;h2&gt;
  
  
  The &lt;code&gt;nix-shell&lt;/code&gt; utility explained
&lt;/h2&gt;

&lt;p&gt;A lot of wonderful magic happens when we run &lt;code&gt;nix-shell&lt;/code&gt;. Let's go through the most significant steps it performs:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;nix-shell&lt;/code&gt; will look for a &lt;code&gt;shell.nix&lt;/code&gt; file in the current directory, and immediately find it in our example.&lt;/li&gt;
&lt;li&gt;It evaluates the Nix expression contained in the file. In most cases, the expression is quite huge as the whole Nixpkgs expression with over 40,000 packages is being imported. Keep in mind that Nix keeps this reasonably efficient by only evaluating the parts that we actually need.&lt;/li&gt;
&lt;li&gt;Now that the Nix expression is evaluated, &lt;code&gt;nix-shell&lt;/code&gt; knows exactly which dependencies are needed. It checks in the local cache located in the &lt;code&gt;/nix/store&lt;/code&gt; directory, if the individual dependencies are already built. If not, it will try to get them from a binary cache at &lt;code&gt;cache.nixos.org&lt;/code&gt;. Only as a last resort will it actually build the required packages itself. &lt;/li&gt;
&lt;li&gt;When all dependencies are successfully cached in &lt;code&gt;/nix/store&lt;/code&gt;, &lt;code&gt;nix-shell&lt;/code&gt; puts together a &lt;code&gt;$PATH&lt;/code&gt; environment variable that ties all the requested dependencies together. It then launches a new shell with that path set.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you only want to run a single command instead of being dropped into a shell, you can use the &lt;code&gt;--run&lt;/code&gt; flag. For example, &lt;code&gt;nix-shell --run "curl http://google.com/"&lt;/code&gt; will query Google using the curl version that was installed by Nix.&lt;/p&gt;

&lt;p&gt;As soon as you leave the Nix shell again with &lt;code&gt;Ctrl-D&lt;/code&gt;, any of the changes that &lt;code&gt;nix-shell&lt;/code&gt; made to our environment will disappear. It will look like the &lt;code&gt;entr&lt;/code&gt; package that we defined as a dependency was never installed, with exception of the cached binary in &lt;code&gt;/nix/store&lt;/code&gt;. The latter can be cleaned up with &lt;code&gt;nix-collect-garbage&lt;/code&gt; or kept for a faster start up of &lt;code&gt;nix-shell&lt;/code&gt; the next time.&lt;/p&gt;

&lt;h1&gt;
  
  
  More to come
&lt;/h1&gt;

&lt;p&gt;Congratulations on surviving your first toe-dipping with Nix! With the example above, you already have a usable first piece that can easily be extended with additional packages. In an upcoming post, I'd like to show you how to pin your version of Nixpkgs in order to make your dependencies reproducible across time and different systems!&lt;/p&gt;

</description>
      <category>nix</category>
      <category>devops</category>
      <category>bash</category>
      <category>functional</category>
    </item>
    <item>
      <title>λ➕ Sum Types in relational databases: Yet another (IMO pretty neat) way to model them in SQL</title>
      <dc:creator>Remo</dc:creator>
      <pubDate>Sat, 18 Jan 2020 09:20:48 +0000</pubDate>
      <link>https://dev.to/monacoremo/sum-types-in-relational-databases-yet-another-imo-pretty-neat-way-to-model-them-in-sql-3o3a</link>
      <guid>https://dev.to/monacoremo/sum-types-in-relational-databases-yet-another-imo-pretty-neat-way-to-model-them-in-sql-3o3a</guid>
      <description>&lt;h1&gt;
  
  
  Sum types
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Tagged_union"&gt;Sum types&lt;/a&gt; are an incredibly useful data-modelling feature that is predominantly used in functional programming languages. For example in &lt;a href="https://elm-lang.org/"&gt;Elm&lt;/a&gt; we can write something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;Animal&lt;/span&gt;
    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Dog&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Integer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;Bird&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;song&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;(It's a silly example, I know...)&lt;/p&gt;

&lt;p&gt;The type we defined here restricts the possible values of an &lt;code&gt;Animal&lt;/code&gt; to exactly &lt;code&gt;Dog&lt;/code&gt; or &lt;code&gt;Bird&lt;/code&gt; with the respective attributes. Those restrictions can make it much easier to reason about code and to check it for correctness. We can extend the type by as many constructors as we need (anyone up for &lt;code&gt;Cat&lt;/code&gt;?).&lt;/p&gt;

&lt;h1&gt;
  
  
  Relational models for sum types
&lt;/h1&gt;

&lt;p&gt;So how do we model this kind of type in SQL? There is no perfect solution, but you can find many good suggestions here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.parsonsmatt.org/2019/03/19/sum_types_in_sql.html"&gt;Sum types in SQL (by Matt Parson)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.typeable.io/posts/2019-11-21-sql-sum-types.html"&gt;Sum types for relational databases (by Dmitry Olshansky and Denis Redozubov)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While modeling a sum type with several normalized tables is arguably cleaner from a relational standpoint (e.g. one central table for &lt;code&gt;Animal&lt;/code&gt; and related ones for &lt;code&gt;Dog&lt;/code&gt; and &lt;code&gt;Bird&lt;/code&gt;), it comes with a lot of complexity.&lt;/p&gt;

&lt;h1&gt;
  
  
  Yet another way to model sum types in SQL
&lt;/h1&gt;

&lt;p&gt;The solution I want to demonstrate here is the 'nullable columns' approach from the blog posts above, with a more compact formulation of the &lt;code&gt;not null&lt;/code&gt; constraints.&lt;/p&gt;

&lt;h2&gt;
  
  
  Data definition
&lt;/h2&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;create&lt;/span&gt; &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;animal_type&lt;/span&gt;
    &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;enum&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'dog'&lt;/span&gt;
        &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'bird'&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;create&lt;/span&gt; &lt;span class="k"&gt;table&lt;/span&gt; &lt;span class="n"&gt;animals&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;animal_id&lt;/span&gt; &lt;span class="nb"&gt;serial&lt;/span&gt; &lt;span class="k"&gt;primary&lt;/span&gt; &lt;span class="k"&gt;key&lt;/span&gt;
    &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;animal_type&lt;/span&gt; &lt;span class="n"&gt;animal_type&lt;/span&gt; &lt;span class="k"&gt;not&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
    &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dog_name&lt;/span&gt; &lt;span class="nb"&gt;text&lt;/span&gt;
        &lt;span class="k"&gt;check&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;animal_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'dog'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dog_name&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="k"&gt;not&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dog_age&lt;/span&gt; &lt;span class="nb"&gt;integer&lt;/span&gt;
        &lt;span class="k"&gt;check&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;animal_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'dog'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dog_age&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="k"&gt;not&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bird_song&lt;/span&gt; &lt;span class="nb"&gt;text&lt;/span&gt;
        &lt;span class="k"&gt;check&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;animal_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'bird'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bird_song&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="k"&gt;not&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;First, we created a new Postgres type in which we exhaustively enumerate all constructors (&lt;code&gt;dog&lt;/code&gt; and &lt;code&gt;bird&lt;/code&gt; in our example).&lt;/p&gt;

&lt;p&gt;Then we define a table where the constructor is tracked in the &lt;code&gt;animal_type&lt;/code&gt; column. The fields of the constructors are all listed in the same table. With the constraint &lt;code&gt;check ((animal_type = 'dog') = (dog_name is not null))&lt;/code&gt;, we make sure that the column is not null when the &lt;code&gt;animal_type&lt;/code&gt; is &lt;code&gt;dog&lt;/code&gt;, and that it is always null otherwise - i.e. only valid combinations.&lt;/p&gt;

&lt;p&gt;Referring to other columns in a check constraint of a column (as we do here with &lt;code&gt;animal_type&lt;/code&gt;) is non-standard SQL and will not be portable. I opted for it in this case, as having the constraints attached to each column makes it quite obvious that they complete and correct.&lt;/p&gt;

&lt;h2&gt;
  
  
  Data modification
&lt;/h2&gt;

&lt;p&gt;Inserting values into this table is straightforward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;insert&lt;/span&gt; &lt;span class="k"&gt;into&lt;/span&gt; &lt;span class="n"&gt;animals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;animal_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bird_song&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;values&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'bird'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'lalala'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;insert&lt;/span&gt; &lt;span class="k"&gt;into&lt;/span&gt; &lt;span class="n"&gt;animals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;animal_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dog_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dog_age&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;values&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'dog'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'rex'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Note that the null columns will not waste any significant amount of space, as Postgres will efficiently pack each record.&lt;/p&gt;

&lt;p&gt;The constraints we set will make sure that only valid values can be inserted or updated:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- This will fail as we also set the `dog_name`attribute, which belongs&lt;/span&gt;
&lt;span class="c1"&gt;-- to another constructor&lt;/span&gt;
&lt;span class="k"&gt;insert&lt;/span&gt; &lt;span class="k"&gt;into&lt;/span&gt; &lt;span class="n"&gt;animals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;animal_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bird_song&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dog_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;values&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'bird'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'lalala'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'rex'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- Fails as the `dog_age` column is missing, but it's required for `dog`&lt;/span&gt;
&lt;span class="k"&gt;insert&lt;/span&gt; &lt;span class="k"&gt;into&lt;/span&gt; &lt;span class="n"&gt;animals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;animal_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dog_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;values&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'dog'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'rex'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Data query
&lt;/h2&gt;

&lt;p&gt;Querying the table is simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;animals&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="n"&gt;animal_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dog_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dog_age&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;animals&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;animal_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'dog'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;On the functional side, decoding the rows back into sum types is relatively simple, we can either use a &lt;code&gt;oneOf&lt;/code&gt; construct or something like &lt;code&gt;Decode.string "animal_type" |&amp;gt; Decode.andThen ...&lt;/code&gt; in Elm.&lt;/p&gt;

&lt;h1&gt;
  
  
  Discussion
&lt;/h1&gt;

&lt;p&gt;There is no perfect way to model sum types in relational databases. Some are very complex to set up and handle, others are more pragmatic and simpler to handle, but less normalized. &lt;/p&gt;

&lt;p&gt;The solution proposed here will not bring any joy to normalization affictionadoes, but it is easy to handle and, due to its simplicity, also performs well. &lt;/p&gt;

&lt;p&gt;What do you think?&lt;/p&gt;

</description>
      <category>sql</category>
      <category>postgres</category>
      <category>database</category>
      <category>functional</category>
    </item>
    <item>
      <title>♻️🐘 Disposable local Postgres databases (without containers!)</title>
      <dc:creator>Remo</dc:creator>
      <pubDate>Fri, 17 Jan 2020 14:35:29 +0000</pubDate>
      <link>https://dev.to/monacoremo/disposable-local-postgres-databases-without-containers-55am</link>
      <guid>https://dev.to/monacoremo/disposable-local-postgres-databases-without-containers-55am</guid>
      <description>&lt;p&gt;In this post, my aim is to show you how to get 'disposable' Postgres databases whenever you need them, e.g. for iterative development and testing. I will also give an example on how to use them to get automatic code reload on your database schema.&lt;/p&gt;

&lt;p&gt;I'll take you through the individual steps of setting up custom local instances of Postgres, as they also helped to understand Postgres a lot better. If you'd like to take a shortcut and skip this learning opportunity, you can also directly use the awesome &lt;a href="http://eradman.com/ephemeralpg/"&gt;&lt;code&gt;pg_tmp&lt;/code&gt;&lt;/a&gt; tool! 🙂&lt;/p&gt;

&lt;p&gt;The approach to running custom local instances of Postgres that I'll demonstrate here is easy, fast and reliable - so much so, that you should be able to reduce the complexity of your development setup in several ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It will eliminate the need for using databases in &lt;strong&gt;containers&lt;/strong&gt; in many cases. Containers are super convenient, but they come with some extra complexity that we should avoid when we can.&lt;/li&gt;
&lt;li&gt;If you currently substitute your production database with something like &lt;strong&gt;SQLite&lt;/strong&gt; for development and testing, this approach will allow you to work in an environment that is much closer to production and enables you to use the full power of Postgres.&lt;/li&gt;
&lt;li&gt;It will completely eliminate the need for fiddling around with the database cluster that comes with your OS (e.g. with the &lt;code&gt;postgresql&lt;/code&gt; package in Debian and derivatives).&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Running a local one-off Postgres database
&lt;/h1&gt;

&lt;p&gt;I invite you to follow along with the steps below in your shell! We will put all of them into a convenient script later, but going through them one by one will give us the best opportunity to experiment and learn.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1 / 4: Create a temporary directory
&lt;/h2&gt;

&lt;p&gt;Let's create a temporary directory in which our one-off database cluster will live:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;tmpdir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;mktemp&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;mktemp -d&lt;/code&gt; creates a new directory and prints the new path to &lt;code&gt;stdout&lt;/code&gt;. We capture that output with &lt;code&gt;$(...)&lt;/code&gt; and assign it to the &lt;code&gt;tmpdir&lt;/code&gt; variable.&lt;/p&gt;

&lt;p&gt;Everything that our Postgres instance does will happen in this directory, it will not save any configuration, data or logs anywhere else. If we want the directory to be automatically deleted when we are done with that database, we can set up the following &lt;code&gt;trap&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;trap&lt;/span&gt; &lt;span class="s2"&gt;"rm -rf &lt;/span&gt;&lt;span class="nv"&gt;$tmpdir&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nb"&gt;exit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Traps are a special feature of our shell. In this case, we tell the shell to make sure that &lt;code&gt;rm -rf $tmpdir&lt;/code&gt; will always be run when it receives the &lt;code&gt;exit&lt;/code&gt; signal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2 / 4: Set up environment
&lt;/h2&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PGDATA&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$tmpdir&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This is the only environment variable that we need for now, &lt;code&gt;initdb&lt;/code&gt;, &lt;code&gt;postgres&lt;/code&gt; and &lt;code&gt;pg_ctl&lt;/code&gt; will all use it to find the directory of our one-off database cluster.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3 / 4: Initialize the database cluster
&lt;/h2&gt;

&lt;p&gt;With the Postgres binaries on our &lt;code&gt;$PATH&lt;/code&gt;, we can set up our new database cluster:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;initdb &lt;span class="nt"&gt;--no-locale&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This will set up the basic directory and file structure that Postgres needs in our temporary directory (which &lt;code&gt;initdb&lt;/code&gt; finds via &lt;code&gt;$PGDATA&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;If you don't have the Postgres binaries on your &lt;code&gt;$PATH&lt;/code&gt; yet, your OS should have them in a package. On Debian, for example, you can get them with &lt;code&gt;sudo apt install postgresql&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You might not need the &lt;code&gt;--no-locale&lt;/code&gt; option, but it makes the initialization more reliable on some systems, in my experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4 / 4: Run the database server
&lt;/h2&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;postgres &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="nv"&gt;listen_addresses&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt; &lt;span class="nt"&gt;-k&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PGDATA&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This tells Postgres to not listen on any TCP port. Instead, we ask it to listen on a Unix domain socket in the directory we specify with &lt;code&gt;-k&lt;/code&gt;. For simplicity, we just reuse the &lt;code&gt;$PGDATA&lt;/code&gt; directory. As we will be in a unique temporary directory on each run, we will never have any port or socket collisions (or any data left over from previous runs!).&lt;/p&gt;

&lt;p&gt;That's it! Our shiny new database cluster is ready to use. 🎉🎉🎉&lt;/p&gt;

&lt;p&gt;As a bonus, on most Linux distributions it will run in memory (and therefore extremely fast!), as the temporary directory we use will usually be on a &lt;a href="https://en.wikipedia.org/wiki/Tmpfs"&gt;&lt;code&gt;tmpfs&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Connecting to our new database
&lt;/h1&gt;

&lt;p&gt;To connect over the Unix domain socket, we need to use a URI that refers to our socket directory (for which we lazily reused &lt;code&gt;$PGDATA&lt;/code&gt;). Let's set it as a environment variable for convenience:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;DB_URI&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"postgresql:///postgres?host=&lt;/span&gt;&lt;span class="nv"&gt;$PGDATA&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let's test if we can connect with psql:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; psql "$DB_URI"
psql (12.1)
Type "help" for help.

postgres=# 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Success! That URI should also work with any other tool or library that takes a Postgres connection URI.&lt;/p&gt;

&lt;h1&gt;
  
  
  Loading our database schema
&lt;/h1&gt;

&lt;p&gt;We could load our database schema now, but it's actually a bit cleaner if we do that before we start the server. That way, we can avoid that other services in our stack get a connection before the database is fully ready. So let's insert an intermediate step:&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3.5 / 4: Load our database schema
&lt;/h2&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PGDATA&lt;/span&gt;&lt;span class="s2"&gt;/setupsocket"&lt;/span&gt;

pg_ctl start &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s2"&gt;"-c listen_addresses=&lt;/span&gt;&lt;span class="se"&gt;\"\"&lt;/span&gt;&lt;span class="s2"&gt; -k &lt;/span&gt;&lt;span class="nv"&gt;$PGDATA&lt;/span&gt;&lt;span class="s2"&gt;/setupsocket"&lt;/span&gt;

psql &lt;span class="s2"&gt;"postgresql:///postgres?host=&lt;/span&gt;&lt;span class="nv"&gt;$PGDATA&lt;/span&gt;&lt;span class="s2"&gt;/setupsocket"&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; app.sql

pg_ctl stop
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Using a separate socket will make sure that none of the other services that we might have will be able to connect before our database is ready. The &lt;code&gt;pg_ctl&lt;/code&gt; utility is useful here, as it will wait for the database startup and shutdown to complete before returning. When starting our database server up with &lt;code&gt;pg_ctl start&lt;/code&gt;, we pass it the same arguments as we do to &lt;code&gt;postgres&lt;/code&gt; as a string with the &lt;code&gt;-o&lt;/code&gt; option.&lt;/p&gt;

&lt;h1&gt;
  
  
  Putting everything together in one script
&lt;/h1&gt;

&lt;p&gt;Here's the full example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;tmpdir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;mktemp&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="nb"&gt;trap&lt;/span&gt; &lt;span class="s1"&gt;'rm -rf "$tmpdir"'&lt;/span&gt; &lt;span class="nb"&gt;exit

export &lt;/span&gt;&lt;span class="nv"&gt;PGDATA&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$tmpdir&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;DB_URI&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"postgresql:///postgres?host=&lt;/span&gt;&lt;span class="nv"&gt;$PGDATA&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

initdb &lt;span class="nt"&gt;--no-locale&lt;/span&gt;

&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PGDATA&lt;/span&gt;&lt;span class="s2"&gt;/setupsocket"&lt;/span&gt;
pg_ctl start &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s2"&gt;"-c listen_addresses=&lt;/span&gt;&lt;span class="se"&gt;\"\"&lt;/span&gt;&lt;span class="s2"&gt; -k &lt;/span&gt;&lt;span class="nv"&gt;$PGDATA&lt;/span&gt;&lt;span class="s2"&gt;/setupsocket"&lt;/span&gt;
psql &lt;span class="s2"&gt;"postgresql:///postgres?host=&lt;/span&gt;&lt;span class="nv"&gt;$PGDATA&lt;/span&gt;&lt;span class="s2"&gt;/setupsocket"&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; app.sql
pg_ctl stop

postgres &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="nv"&gt;listen_addresses&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt; &lt;span class="nt"&gt;-k&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PGDATA&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Starting up a new Postgres instance this way takes less than a second on my machine. That's of course not as fast as SQLite, but it's probably good enough for most use-cases! And we get to use the full power of Postgres, including its extensions and the possibility to have more than one write connection.&lt;/p&gt;

&lt;p&gt;To run tests immediately after the database is ready, e.g. a &lt;code&gt;run-tests.sh&lt;/code&gt; script that connects to the database, we can replace the last line with the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;postgres &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="nv"&gt;listen_addresses&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt; &lt;span class="nt"&gt;-k&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PGDATA&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &amp;amp;

cleanup&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$tmpdir&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="nb"&gt;kill &lt;/span&gt;0
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nb"&gt;trap &lt;/span&gt;cleanup &lt;span class="nb"&gt;exit&lt;/span&gt;

./run-tests.sh &lt;span class="nv"&gt;$DB_URI&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;With this amendment, we first start Postgres in the background with &lt;code&gt;&amp;amp;&lt;/code&gt;. Then, we need to adjust our trap to also kill that background process on exit. We do this by defining a function that both deletes the temporary directory and kills all background processes that are children of our current process. We then reset our earlier exit trap with that function. Finally, we can run our tests and  be sure that we have a fresh, one-off database at the ready.&lt;/p&gt;

&lt;h1&gt;
  
  
  Reloading your database on code changes
&lt;/h1&gt;

&lt;p&gt;Based on the script we created (let's save it as &lt;code&gt;run-db.sh&lt;/code&gt;), we can easily get a database that is reloaded for every change in our code. For example, you can use &lt;a href="http://eradman.com/entrproject/"&gt;&lt;code&gt;entr&lt;/code&gt;&lt;/a&gt; to restart the database and rerun the tests for any change in the current directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;find &lt;span class="nb"&gt;.&lt;/span&gt; | entr &lt;span class="nt"&gt;-r&lt;/span&gt; ./run-db.sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h1&gt;
  
  
  Taking a shortcut with &lt;code&gt;pg_tmp&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;&lt;a href="http://eradman.com/ephemeralpg/"&gt;&lt;code&gt;pg_tmp&lt;/code&gt;&lt;/a&gt; is a neat tool that makes the whole process of setting up temporary Postgres databases even easier:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;db_uri&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;pg_tmp&lt;span class="si"&gt;)&lt;/span&gt;
psql &lt;span class="nv"&gt;$db_uri&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; app.sql
./run-tests.sh &lt;span class="nv"&gt;$db_uri&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This feels like cheating - but it works! In my opinion this is also much simpler than fiddling around with containers. As in our more manual setup we implemented before, you will never experience port collisions or remnants from earlier test runs with &lt;code&gt;pg_tmp&lt;/code&gt;. In the background, &lt;code&gt;pg_tmp&lt;/code&gt; pretty much does what we implemented ourselves, while adding some more optimizations to make the startup-process even faster! The manual approach I guided you through above can, however, be useful if you need more customization and control (like in &lt;a href="https://github.com/monacoremo/postgrest-sessions-example"&gt;this example&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;I hope you will enjoy and make good use of your many new free, recyclable Postgres databases! ♻️🐘&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Many thanks to &lt;a href="http://eradman.com/"&gt;Eric Radman&lt;/a&gt; for writing the awesome &lt;code&gt;entr&lt;/code&gt; and &lt;code&gt;pg_tmp&lt;/code&gt; tools!&lt;/p&gt;

&lt;p&gt;In an upcoming post, I would also like to show how to easily get all dependencies (in this case, the Postgres binaries, pg_tmp etc.) with &lt;a href="https://nixos.org/"&gt;Nix&lt;/a&gt;. It's not &lt;em&gt;that&lt;/em&gt; scary :-)&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>sql</category>
      <category>postgres</category>
      <category>database</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Writing SQL for humans with Literate SQL</title>
      <dc:creator>Remo</dc:creator>
      <pubDate>Thu, 16 Jan 2020 17:00:51 +0000</pubDate>
      <link>https://dev.to/monacoremo/writing-sql-for-humans-with-literate-sql-1ljo</link>
      <guid>https://dev.to/monacoremo/writing-sql-for-humans-with-literate-sql-1ljo</guid>
      <description>&lt;p&gt;In this post, I'll briefly explain Literate Programming and show how you can apply that concept to make your SQL scripts easier to understand (for humans!) and more maintainable.&lt;/p&gt;

&lt;h1&gt;
  
  
  Literate Programming
&lt;/h1&gt;

&lt;p&gt;Literate programming means writing code primarily for humans instead of for machines. &lt;/p&gt;

&lt;p&gt;The first step towards Literate Programming is to &lt;em&gt;switch the comments and code&lt;/em&gt; in our source code. That might sound weird at first... 😛 The easiest way to explain this is with an example. Let's start with the following Python script (please don't mind any details, we'll get to SQL soon!):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# The best kind of jokes are Chuck Norris jokes, so we create a function
# to get them from the ICNDB API.

def random_joke():
     '''Get a random Chuck Norris joke from the ICNDB API.'''
     return requests.get('https://api.icndb.com/jokes/random').json()

# Next, we set up a web server to show the jokes to our users.

...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In a literate program, we would write something like this instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight markdown"&gt;&lt;code&gt;The best kind of jokes are Chuck Norris jokes, so we create a function
to get them from the ICNDB API.
&lt;span class="gt"&gt;
&amp;gt; def random_joke():&lt;/span&gt;
&lt;span class="gt"&gt;&amp;gt;     '''Get a random Chuck Norris joke from the ICNDB API.'''&lt;/span&gt;
&lt;span class="gt"&gt;&amp;gt;     return requests.get('https://api.icndb.com/jokes/random').json()&lt;/span&gt;

Next, we set up a web server to show the jokes to our users.

...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Note that the comments are now regular plain text, and that the code to be executed has been specially marked. As a result, our explanations to humans have taken precedence over the code!&lt;/p&gt;

&lt;p&gt;This literate style will not make sense for all kinds of code and might seem a bit silly in this small example, but it can be very useful for programs where explaining your thoughts and approach is more important than the code itself.&lt;/p&gt;

&lt;p&gt;The concept of Literate Programming was introduced ages ago (in programming time 🙃) by Donald E. Knuth. &lt;a href="http://www.literateprogramming.com/knuthweb.pdf"&gt;Back in 1983 he suggested&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Instead of imagining that our main task is to instruct a computer what to do, let us concentrate rather on explaining to human beings what we want a computer to do.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Since then, a few programming languages got native support for running literate programs. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Haskell: The GHC compiler also works with &lt;a href="https://wiki.haskell.org/Literate_programming"&gt;literate .lhs files&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Python supports a literate style in &lt;a href="https://docs.python.org/3/library/doctest.html"&gt;doctests&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Beyond this, 'Notebooks' have become quite popular and are very close to the concept of literate programming:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://jupyter.org/"&gt;Jupyter Notebooks&lt;/a&gt; support mixing Python and other languages with text and Markdown.&lt;/li&gt;
&lt;li&gt;The &lt;a href="https://docs.microsoft.com/en-us/sql/azure-data-studio/sql-notebooks"&gt;Azure Data Studio&lt;/a&gt; is doing something similar for SQL.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Literate SQL
&lt;/h1&gt;

&lt;p&gt;SQL is a very expressive language where you often put much thought and testing into writing a terse query. Accordingly, applying literate programming to SQL can make a lot of sense!&lt;/p&gt;

&lt;p&gt;I was not able to find any existing tooling that supports Literate Programming in SQL (please let me know if you do!). The Notebook solutions are close and they are fine for querying an existing schema, but they are not a good fit if we want to create a new schema or a whole database application. So let's create our own simple tooling that works for SQL combined with Markdown files.&lt;/p&gt;

&lt;p&gt;Time for an example with SQL! Let's convert the following script into a literate program:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- POSTS TABLE&lt;/span&gt;

&lt;span class="c1"&gt;-- Create a table in which we will track the posts created by our users.&lt;/span&gt;

&lt;span class="k"&gt;create&lt;/span&gt; &lt;span class="k"&gt;table&lt;/span&gt; &lt;span class="n"&gt;posts&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;post_id&lt;/span&gt;  &lt;span class="nb"&gt;serial&lt;/span&gt; &lt;span class="k"&gt;primary&lt;/span&gt; &lt;span class="k"&gt;key&lt;/span&gt;
    &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;    &lt;span class="nb"&gt;text&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;comment&lt;/span&gt; &lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="k"&gt;table&lt;/span&gt; &lt;span class="n"&gt;posts&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt;
    &lt;span class="s1"&gt;'Posts with a title.'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;comment&lt;/span&gt; &lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="k"&gt;column&lt;/span&gt; &lt;span class="n"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt;
    &lt;span class="s1"&gt;'Title of the post'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Note that we used comments for a few different purposes in this script:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating a structure or outline for our script (&lt;code&gt;-- POSTS TABLE&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Explaining what we are doing and why (&lt;code&gt;-- Create a table...&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Attaching comments directly to database objects (&lt;code&gt;comment on .. is ...;&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;comment on ...&lt;/code&gt; statements are very similar to docstrings in Python, which can be accessed &lt;a href="https://jakevdp.github.io/PythonDataScienceHandbook/01.01-help-and-documentation.html"&gt;interactively&lt;/a&gt; or used to &lt;a href="https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html"&gt;generate documentation&lt;/a&gt;. Likewise, the comments in SQL can be very useful for people exploring our schema (e.g. with the family of &lt;a href="https://www.postgresql.org/docs/12/app-psql.html#APP-PSQL-META-COMMANDS"&gt;&lt;code&gt;\d&lt;/code&gt; commands&lt;/a&gt; in psql, in GUI tools like &lt;a href="https://dbeaver.io/"&gt;DBeaver&lt;/a&gt; or via the OpenAPI spec generated by &lt;a href="http://postgrest.org/en/v6.0/api.html#openapi-support"&gt;PostgREST&lt;/a&gt;). &lt;/p&gt;

&lt;p&gt;The Markdown markup language is a good fit for turning this script into a literate SQL file:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We can describe our outline using Markdown headers (&lt;code&gt;#&lt;/code&gt;, &lt;code&gt;##&lt;/code&gt; etc.)&lt;/li&gt;
&lt;li&gt;Our explanations can be written in plain text with Markdown markup where needed (e.g. for links)&lt;/li&gt;
&lt;li&gt;We can put our SQL code into Markdown code blocks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So we can turn our SQL script from above into the following &lt;code&gt;.md&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Posts table&lt;/span&gt;

Create a table in which we will track the posts created by our users.&lt;span class="sb"&gt;

    create table posts
        ( postid serial primary key
        , title text
        );

    comment on table posts is
        'Posts with a title.';

    comment on column posts.title is
        'Title of the post';
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This mechanical conversion is only the starting point, of course, and we would now add further explanations, structure and links as needed.&lt;/p&gt;

&lt;p&gt;We left the &lt;code&gt;comment on ...&lt;/code&gt; statements as they were in the original script, as they are unchangedly useful the users of our schema. Note that we did the same with the docstrings in the Python example that we started with.&lt;/p&gt;

&lt;p&gt;Many text editors will automatically provide the &lt;a href="https://www.markdownguide.org/extended-syntax/#syntax-highlighting"&gt;right syntax highlighting&lt;/a&gt; for the SQL code blocks that we embedded in the Markdown file, for example &lt;a href="https://code.visualstudio.com/"&gt;Visual Studio Code&lt;/a&gt; does it out of the box. It would be even better if we used &lt;a href="https://www.markdownguide.org/extended-syntax/#fenced-code-blocks"&gt;fenced Markdown code blocks&lt;/a&gt;, where we can explicitly set the &lt;code&gt;sql&lt;/code&gt; language for highlighting (see the full example below).&lt;/p&gt;

&lt;p&gt;It's very easy to render the Markdown file into HTML or PDF for documentation and comfortable reading. GitHub and GitLab will, for example, automatically display pretty previews for our literate code.&lt;/p&gt;

&lt;h1&gt;
  
  
  Complete example of a Literate SQL script
&lt;/h1&gt;

&lt;p&gt;The value of Literate Programming in SQL becomes clearer with larger scripts. The following file is a complete example of a literate SQL script: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/monacoremo/postgrest-sessions-example/blob/master/app.sql.md"&gt;&lt;strong&gt;&lt;code&gt;app.sql.md&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This example is much more verbose than setting up a schema would usually warrant, as it's intended to be a tutorial for new PostgREST users at some point. Please keep that in mind and don't be that be that chatty in your literal SQL files! :-)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Even though this script is used to set up a relatively complex application with multiple schemas, indexes, stored procedures and tests, it should be possible for a new reader to understand how the application works relatively quickly. The option to set links to other parts of the code and to external resources also turned out to be very useful.&lt;/p&gt;

&lt;p&gt;But, how can we now run the SQL script that has been 'buried' in that file? We'll solve that small problem in the next section.&lt;/p&gt;

&lt;h1&gt;
  
  
  Tooling for Literate SQL
&lt;/h1&gt;

&lt;p&gt;Literate SQL is not directly supported by the usual SQL tools like the &lt;code&gt;psql&lt;/code&gt; utility from Postgres, but we can easily create our own tooling in order to run literate SQL programs. Short of using a full Markdown parser (e.g. in a Python script), we can use the &lt;code&gt;sed&lt;/code&gt; utility that is available on most Unix machines to pull out the SQL code blocks from our Markdown files.&lt;/p&gt;

&lt;p&gt;For example, if we wanted to convert a literate SQL/Markdown file &lt;code&gt;app.sql.md&lt;/code&gt; into a regular SQL script, we can run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; md2sql.sed &amp;lt;app.sql.md &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;app.sql
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can get &lt;a href="https://github.com/monacoremo/postgrest-sessions-example/blob/master/deploy/md2sql.sed"&gt;&lt;code&gt;md2sql.sed&lt;/code&gt; here&lt;/a&gt;. It's only a two-liner &lt;code&gt;sed&lt;/code&gt;-script to which I added many comments, as this is one of the very expressive but cryptic examples that &lt;code&gt;sed&lt;/code&gt; is notorious for 😜.&lt;/p&gt;

&lt;p&gt;Now that we have turned our literate &lt;code&gt;app.sql.md&lt;/code&gt; file into a regular SQL script &lt;code&gt;app.sql&lt;/code&gt;, we can run it directly in our database, as we would if we had written a plain SQL script in the first place:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;psql &lt;span class="nt"&gt;-f&lt;/span&gt; app.sql
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We are using the &lt;code&gt;psql&lt;/code&gt; utility from Postgres in this example, but it will work similarly for any other relational database. Let's do everything in one command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; md2sql.sed app.sql.md | psql
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This pulls out the SQL code blocks out of our Markdown file and uses &lt;code&gt;psql&lt;/code&gt; to directly run them in our database.&lt;/p&gt;

&lt;p&gt;That's all you need to write and use literate SQL scripts! 🎉&lt;/p&gt;

&lt;h1&gt;
  
  
  Writing SQL for humans
&lt;/h1&gt;

&lt;p&gt;I'm a big fan of tools like &lt;a href="http://postgrest.org/"&gt;PostgREST&lt;/a&gt; and of leveraging the full power of relational databases when developing applications. Using a literate style in Postgres applications (like the &lt;a href="https://github.com/monacoremo/postgrest-sessions-example/"&gt;example for session-based authentication with PostgREST&lt;/a&gt;) goes a long way in making the code easier to understand and to validate.&lt;/p&gt;

&lt;p&gt;The tooling for literate SQL that we created here is very simple and Markdown is a markup language that most developers are familiar with, so I don't think that there are any significant downsides to using Literate SQL as shown in this post. The upside of having clearer, more maintainable code can, however, be huge!&lt;/p&gt;

&lt;h1&gt;
  
  
  Question: Would you use literate SQL in your projects?
&lt;/h1&gt;

&lt;p&gt;Please comment, I'm curious to hear your opinion and looking forward to discussing use-cases with you. Let's figure out how to make this as easy and useful as possible!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In upcoming posts, I plan to write about maintaining SQL applications without annoying migrations and how to easily create disposable Postgres databases for development and testing without containers. Please stay tuned!&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>sql</category>
      <category>database</category>
      <category>postgres</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
