<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>databases — jd:/dev/blog</title><description>Posts tagged &quot;databases&quot; on jd:/dev/blog.</description><link>https://julien.danjou.info/</link><item><title>The Art of PostgreSQL is out!</title><link>https://julien.danjou.info/blog/the-art-of-postgresql-is-out/</link><guid isPermaLink="true">https://julien.danjou.info/blog/the-art-of-postgresql-is-out/</guid><description>If you remember well, a couple of years ago, I wrote about Mastering PostgreSQL, a fantastic book written by my friend Dimitri Fontaine.  Dimitri is a long-time PostgreSQL core developer — for example</description><pubDate>Wed, 28 Aug 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;If you remember well, a couple of years ago, I wrote about &lt;em&gt;Mastering PostgreSQL&lt;/em&gt;, a fantastic book written by my friend Dimitri Fontaine.&lt;/p&gt;
&lt;p&gt;Dimitri is a long-time PostgreSQL core developer — for example, he wrote the extension support in PostgreSQL — no less. He is featured in my book &lt;a href=&quot;https://serious-python.com&quot;&gt;Serious Python&lt;/a&gt;, where he advises on using databases and ORM in Python.&lt;/p&gt;
&lt;p&gt;Today, Dimitri comes back with the new version of this book, named &lt;em&gt;&lt;a href=&quot;https://jdanjou--theartofpostgresql.thrivecart.com/full-edition/?ref=blog&quot;&gt;The Art of PostgreSQL&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/08/IMG_20141121_164610.jpg&quot; alt=&quot;As a bonus, here&apos;s a picture of me and Dimitri having fun in a PostgreSQL meetup!&quot; /&gt;&lt;/p&gt;
&lt;p&gt;I love the motto of this book: &lt;em&gt;Turn Thousands of Lines of Code into Simple Queries&lt;/em&gt;. I have spent all my career working with code that talks to databases, and I can&apos;t count the number of times where I&apos;ve seen people write lengthy, slow code in their pet language rather than a single well-thought SQL query which would do a better job.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/08/image-5.png&quot; alt=&quot;Cover of The Art of PostgreSQL&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;This is exactly what &lt;a href=&quot;https://jdanjou--theartofpostgresql.thrivecart.com/full-edition/?ref=blog&quot;&gt;this book&lt;/a&gt; is about.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;That&apos;s why it&apos;s my favorite SQL book. I learned so many things from it. In many cases, I&apos;ve been able to divide by 10 the size of the code I had to write in Python to implement a feature. All I had to do is to browse the book to discover the right PostgreSQL feature and write a single SQL query. The &lt;em&gt;right&lt;/em&gt; query that does the job for me_._&lt;/p&gt;
&lt;p&gt;Less code, fewer bugs, more happiness!&lt;/p&gt;
&lt;p&gt;The book also features interviews with great PostgreSQL users and developers — hey, no wonder where Dimitri got this idea, right? ;-)&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/08/Screenshot-2019-08-28-at-15.09.21.png&quot; alt=&quot;Screenshot of interview excerpts featured in The Art of PostgreSQL&quot; /&gt;&lt;/p&gt;
&lt;p&gt;I loved those interviews. What&apos;s better than reading Kris Jenkins explaining how Clojure and PostgreSQL play nice together, or Markus Winand (from the famous &lt;a href=&quot;https://use-the-index-luke.com/&quot;&gt;use-the-index-luke.com&lt;/a&gt;) talking about the relationship developers have with their database. :-)&lt;/p&gt;
&lt;p&gt;No need to say that you should get your hands on this &lt;strong&gt;right now.&lt;/strong&gt; Dimitri just made a launch offer where &lt;a href=&quot;https://jdanjou--theartofpostgresql.thrivecart.com/full-edition/?ref=blog&quot;&gt;he offers a &lt;strong&gt;15% discount&lt;/strong&gt; on the book&lt;/a&gt; until the end of this month! You can also &lt;a href=&quot;https://jdanjou--theartofpostgresql.thrivecart.com/full-edition/?ref=blog&quot;&gt;read the free chapter&lt;/a&gt; to get an idea of what you&apos;ll get.&lt;/p&gt;
&lt;p&gt;Last thing: it&apos;s DRM-free and money-back guaranteed. You can &lt;a href=&quot;https://jdanjou--theartofpostgresql.thrivecart.com/full-edition/?ref=blog&quot;&gt;get this book&lt;/a&gt; with your eyes closed.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/08/Screenshot-2019-08-28-at-15.25.14.png&quot; alt=&quot;Screenshot of The Art of PostgreSQL book packages and pricing&quot; /&gt;&lt;/p&gt;
</content:encoded><category>databases</category><category>books</category></item><item><title>Why You Should Care That Your SQL DDL is Transactional</title><link>https://julien.danjou.info/blog/why-you-should-care-that-your-sql-ddl-is-transactional/</link><guid isPermaLink="true">https://julien.danjou.info/blog/why-you-should-care-that-your-sql-ddl-is-transactional/</guid><description>I don&apos;t write a lot about database management. How come? I&apos;m a software engineer, and like many of my peers, I leverage databases to store data. I should talk more about this! What made me write this</description><pubDate>Mon, 07 Jan 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I don&apos;t write a lot about database management. How come? I&apos;m a software engineer, and like many of my peers, I leverage databases to store data. I should talk more about this! What made me write this today is that I&apos;ve discovered that many of my peers wouldn&apos;t be able to understand the title of this post.&lt;/p&gt;
&lt;p&gt;However, I can tell you that once you&apos;ve finished reading this, you&apos;ll thank me!&lt;/p&gt;
&lt;h2&gt;DDL?&lt;/h2&gt;
&lt;p&gt;To understand what this post is about, let&apos;s start with DDL. DDL is the abbreviation of &lt;em&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Data_definition_language&quot;&gt;Data Definition Language&lt;/a&gt;&lt;/em&gt;. In summary, a DDL is a language that allows defining your data structure. A famous one is the SQL DDL — and that&apos;s the one I talk about here.&lt;/p&gt;
&lt;p&gt;I&apos;m sure you already used it if you created a relational database with &lt;code&gt;CREATE TABLE foo (id INTEGER)&lt;/code&gt;. That is a DDL statement.&lt;/p&gt;
&lt;p&gt;In SQL, there&apos;s a lot of DDL operations you can do, such as creating a table, renaming a table, creating or removing a column, converting a column to a new type, etc.&lt;/p&gt;
&lt;p&gt;Those DDL statements are commonly used in two cases:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;When creating your database&apos; tables for the first time. You issue a bunch of &lt;code&gt;CREATE TABLE&lt;/code&gt; statements, and your database is ready to be used.&lt;/li&gt;
&lt;li&gt;When updating your database by adding, removing or modifying tables or columns. This is typically done when upgrading your application to a new version.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The fact that our DDL is transactional or not in option 1. has often little impact in practice. It&apos;s can still be useful, where for example you could get an error because the disk is full — having the ability to roll back in this case can be a life saviour.&lt;/p&gt;
&lt;p&gt;In our case here, we&apos;ll talk about why you need a transactional DDL when upgrading your database.&lt;/p&gt;
&lt;h3&gt;Transactional You Said?&lt;/h3&gt;
&lt;p&gt;What transactional means here? It means that we can issue those DDL statements inside a transaction.&lt;/p&gt;
&lt;p&gt;Wait, what&apos;s a transaction? To make it simple, in a database, a transaction is a group of operations that are treated as a single coherent operation, independently of other transactions. The final operation has to be &lt;strong&gt;a&lt;/strong&gt;tomic, &lt;strong&gt;c&lt;/strong&gt;onsistent, &lt;strong&gt;i&lt;/strong&gt;solated and &lt;strong&gt;d&lt;/strong&gt;urable — therefore that &lt;strong&gt;ACID&lt;/strong&gt; property you keep reading about while always wondering what it meant. The operations composing the transaction are either entirely executed, or not at all.&lt;/p&gt;
&lt;p&gt;In our case, having the DDL being transactional means one simple thing: the ability to execute several operations (e.g., several &lt;code&gt;ALTER TABLE&lt;/code&gt;) in a single operation, that can be either committed or rolled back.&lt;/p&gt;
&lt;p&gt;Let&apos;s use an example. Here&apos;s a table &lt;code&gt;ingredients&lt;/code&gt; with a &lt;code&gt;name&lt;/code&gt; column created with:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;CREATE TABLE ingredients (
  name text NOT NULL
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this table, there is a list of ingredients in the form of &lt;code&gt;water 20 mL&lt;/code&gt;, &lt;code&gt;flour 300 g&lt;/code&gt;, etc.&lt;/p&gt;
&lt;p&gt;Now, we&apos;re upgrading our application, and we want to handle the quantity of ingredients in their columns to make it easier to query the data. Let&apos;s say we&apos;re going to handle quantity and quantity units for our ingredients. We need to add two new columns to our table schema, &lt;code&gt;quantity&lt;/code&gt; and &lt;code&gt;unit&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ALTER TABLE ingredients ADD COLUMN quantity integer NOT NULL;
ALTER TABLE ingredients ADD COLUMN unit text NOT NULL;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We also need to convert the &lt;code&gt;name&lt;/code&gt; by splitting it into &lt;code&gt;&amp;lt;name&amp;gt; &amp;lt;quantity&amp;gt; &amp;lt;unit&amp;gt;&lt;/code&gt; and insert this into the new columns. We can do this like that:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;UPDATE ingredients SET name=split_part(name, &apos; &apos;, 1), quantity=split_part(name, &apos; &apos;, 2)::int, unit=split_part(name, &apos; &apos;, 3);
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;In this example, I&apos;m using &lt;a href=&quot;https://www.postgresql.org/docs/11/static/functions-string.html&quot;&gt;the &lt;code&gt;split_part&lt;/code&gt; operator from PostgreSQL&lt;/a&gt; to split the string.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;With the &lt;code&gt;UPDATE&lt;/code&gt; statement, the &lt;code&gt;name&lt;/code&gt; column containing &lt;code&gt;flour 300 grams&lt;/code&gt; now contains &lt;code&gt;flour&lt;/code&gt;, and the columns &lt;code&gt;quantity&lt;/code&gt; and &lt;code&gt;unit&lt;/code&gt; respectively stores &lt;code&gt;300&lt;/code&gt; and &lt;code&gt;grams&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;When we run our upgrade procedure consisting of those two &lt;code&gt;ALTER TABLE&lt;/code&gt; and one &lt;code&gt;UPDATE&lt;/code&gt;, we got our final table like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;## SELECT * FROM ingredients;
 name  │ quantity │ unit
───────┼──────────┼──────
 flour │      300 │ g
(1 row)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Exactly what we want.&lt;/p&gt;
&lt;h2&gt;Ok, So What?&lt;/h2&gt;
&lt;p&gt;In the previous example, everything worked fine. Our 300 grams of flour string is split, converted and stored into the three different columns. However, let&apos;s think about what happens if the conversion fails because our ingredient &lt;code&gt;name&lt;/code&gt; is &lt;code&gt;foobar&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;## ALTER TABLE ingredients ADD COLUMN quantity integer;
ALTER TABLE
## ALTER TABLE ingredients ADD COLUMN unit text;
ALTER TABLE
## UPDATE ingredients SET name=split_part(name, &apos; &apos;, 1), quantity=split_part(name, &apos; &apos;, 2)::int, unit=split_part(name, &apos; &apos;, 3);
ERROR:  invalid input syntax for integer: &quot;&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Right, so in this case our update failed because it&apos;s impossible to convert an empty string to an integer.&lt;/p&gt;
&lt;p&gt;We&apos;re going to fix this piece of data in our database (manually or automatically, whatever) to make it work, changing &lt;code&gt;foobar&lt;/code&gt; to something like &lt;code&gt;foobar 1 kg&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Then, when we rerun the upgrade script, this is what happens:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;## ALTER TABLE ingredients ADD COLUMN quantity integer NOT NULL;
ERROR:  column &quot;quantity&quot; of relation &quot;ingredients&quot; already exists
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The upgrade script failed earlier — not in the &lt;code&gt;UPDATE&lt;/code&gt; statement. It has a good reason to fail: the column &lt;code&gt;quantity&lt;/code&gt; already exists.&lt;/p&gt;
&lt;p&gt;Why is that? Well, when we run the upgrade procedure the first time, we did not run it inside a transaction. Every DDL statement was committed right after its execution. Therefore, the current state of our database is &lt;em&gt;half-migrated&lt;/em&gt;: we have the new schema installed, but not the data migrated.&lt;/p&gt;
&lt;p&gt;This sucks. This should not happen. Ever.&lt;/p&gt;
&lt;h2&gt;Why?&lt;/h2&gt;
&lt;p&gt;Some database systems (e.g., MySQL) do not support DDL running in a transaction, so you have no choice than running the three operations (&lt;code&gt;ALTER&lt;/code&gt;, &lt;code&gt;ALTER&lt;/code&gt; and then &lt;code&gt;UPDATE&lt;/code&gt;) as three distinct operations: if any of those fails, there&apos;s no way to recover and get back to the initial state.&lt;/p&gt;
&lt;p&gt;If you&apos;re using a database that supports running DDL statements inside a transaction (e.g., PostgreSQL), we can run your upgrade script like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;postgres=# BEGIN;
postgres=# ALTER TABLE ingredients ADD COLUMN quantity integer;
ALTER TABLE
postgres=# ALTER TABLE ingredients ADD COLUMN unit text;
ALTER TABLE
postgres=# UPDATE ingredients SET name=split_part(name, &apos; &apos;, 1), quantity=split_part(name, &apos; &apos;, 2)::int, unit=split_part(name, &apos; &apos;, 3);
ERROR:  invalid input syntax for integer: &quot;&quot;
postgres=# ROLLBACK;
ROLLBACK
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Since the transaction failed, we ended up doing a &lt;code&gt;ROLLBACK&lt;/code&gt;. When checking the state of the database, we can see the state did not change:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;## \d ingredients;
           Table &quot;public.ingredients&quot;
 Column │ Type │ Collation │ Nullable │ Default
────────┼──────┼───────────┼──────────┼─────────
 name   │ text │           │ not null │
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Therefore, it&apos;s possible to fix our database content and rerun the migration procedure without being in a &lt;em&gt;half-migrated&lt;/em&gt; state.&lt;/p&gt;
&lt;h2&gt;A Database That Lies&lt;/h2&gt;
&lt;p&gt;When you&apos;re giving data to a database, you&apos;re trusting it. It&apos;d be awful if it were lying to you, right? Check this out:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;mysql&amp;gt; CREATE TABLE ingredients (name text NOT NULL);
Query OK, 0 rows affected (0.03 sec)

mysql&amp;gt; BEGIN;
Query OK, 0 rows affected (0.00 sec)

mysql&amp;gt; ALTER TABLE ingredients ADD COLUMN quantity integer;
Query OK, 0 rows affected (0.05 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql&amp;gt; ALTER TABLE ingredients ADD COLUMN unit text;
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql&amp;gt; ROLLBACK;
Query OK, 0 rows affected (0.00 sec)

mysql&amp;gt; DESC ingredients;
+----------+---------+------+-----+---------+-------+
| Field    | Type    | Null | Key | Default | Extra |
+----------+---------+------+-----+---------+-------+
| name     | text    | NO   |     | NULL    |       |
| quantity | int(11) | YES  |     | NULL    |       |
| unit     | text    | YES  |     | NULL    |       |
+----------+---------+------+-----+---------+-------+
3 rows in set (0.00 sec)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the output above, you can see that we issued two DDL statements inside a transaction and that we then rolled back that transaction. MySQL did not output any error at any time, making us think that it did not alter our table. However, when checking the schema of the database, we can see that nothing has been rolled back. Not only MySQL does not support transactional DDL, but it also fails you entirely and lie about what it&apos;s doing.&lt;/p&gt;
&lt;h2&gt;How Important is That?&lt;/h2&gt;
&lt;p&gt;Transactional DDL is a feature that is often ignored by software engineers, whereas it&apos;s a key feature for managing your database life cycle.&lt;/p&gt;
&lt;p&gt;I&apos;m writing this post today because I&apos;ve been hit by this multiple times over the last years. OpenStack made the choice years ago to go with MySQL, and in consequences, every database upgrade script that fails in the middle of the procedure leave the database is an inconsistence state. In that case, it means that either:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The operator have to determine where the upgrade script stopped, roll back the upgrade by itself, fix the failure, and rerun the upgrade procedure.&lt;/li&gt;
&lt;li&gt;The developer must anticipate every case of potential upgrade failure, write a roll back procedure for each of this case by and test every one of those cases.&lt;/li&gt;
&lt;li&gt;Use a database system that handles transactional DDL.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;No need to tell you that option 3. is the best, option 2. is barely possible to implement and option 1. is what reality looks like. In &lt;a href=&quot;https://gnocchi.xyz&quot;&gt;Gnocchi&lt;/a&gt;, we picked option 3. by recommending operators to use PostgreSQL.&lt;/p&gt;
&lt;p&gt;Next time you use a database, think carefully about what your upgrade procedure will look like!&lt;/p&gt;
</content:encoded><category>databases</category></item><item><title>Mastering PostgreSQL</title><link>https://julien.danjou.info/blog/mastering-postgresql/</link><guid isPermaLink="true">https://julien.danjou.info/blog/mastering-postgresql/</guid><description>A few months ago, my friend Dimitri Fontaine and I discussed writing books and sharing our knowledge.</description><pubDate>Tue, 07 Nov 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;A few months ago, my friend &lt;a href=&quot;http://tapoueh.org&quot;&gt;Dimitri Fontaine&lt;/a&gt; and I discussed writing books and sharing our knowledge. If you do not know Dimitri yet, he is an old-time PostgreSQL Major Contributor – meaning he writes code for the PostgreSQL software itself!&lt;/p&gt;
&lt;p&gt;I interviewed Dimitri a few years ago in &lt;a href=&quot;https://thehackerguidetopython.com&quot;&gt;The Hacker&apos;s Guide to Python&lt;/a&gt;, where he shared his insight about writing proper Python application code with relational database management system.&lt;/p&gt;
&lt;p&gt;All of this gave Dimitri the idea of writing his own book about PostgreSQL. And he released his book this week! If like me, you can&apos;t wait to read it, just scroll down below and grab a package with a &lt;strong&gt;15% discount&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;To celebrate the event, I went ahead and decided to ask him a few questions.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/03/dim-rounded.png&quot; alt=&quot;Dimitri Fontaine portrait&quot; /&gt;&lt;/p&gt;
&lt;h4&gt;Hey Dimitri! So what made you start writing this book in the first place?&lt;/h4&gt;
&lt;p&gt;&lt;em&gt;Dimitri&lt;/em&gt;: As a PostgreSQL consultant, I&apos;ve met with many developers for whom SQL just didn&apos;t click. They then tend to consider SQL much as they would consider HTML: some string you need to build dynamically then send over to an external part of the system, either the browser or the database server.&lt;/p&gt;
&lt;p&gt;As soon as you start on this path, SQL is more and more of a problem in your daily life and developer workflow. It doesn&apos;t integrate well with the usual testing and continuous integration tools, not to mention it&apos;s hard to review (as in code review) and hard to maintain.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;At the end of the day, when using a relational database system, you have to&lt;br /&gt;
know your SQL.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;As a developer, you need to be fluent in SQL and master window functions, common table expressions, recursive queries, time zone handling and advanced string and regexp processing functions, transaction behaviors and also how to build a query result set in JSON. And so much more.&lt;/p&gt;
&lt;p&gt;For most developers, it&apos;s a daunting task. Just too much to learn when they have so many other things to take care of. So many lines of code to write to implement that new product idea. Well, as Dijkstra put it, lines of code are “spent” on writing a new feature. When you master SQL, you spend much less of those lines of code.&lt;/p&gt;
&lt;p&gt;So I wrote &lt;strong&gt;Mastering PostgreSQL in Application Development&lt;/strong&gt; to teach SQL to developers. Focusing on real use cases and authentic data set, so that it&apos;s easier to grasp all those advanced features. The book also addresses the tooling you need to integrate SQL as another programming language with a decent worfklow, from code review to unit testing, including regression testing and production debugging.&lt;/p&gt;
&lt;h4&gt;Who should read this book? What are the prerequisites to get the most of it?&lt;/h4&gt;
&lt;p&gt;&lt;em&gt;Dimitri&lt;/em&gt;: The pre-requisites are quite easy to reach.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If you ever deployed an application that embeds SQL queries and talks to a&lt;br /&gt;
database server, you&apos;re in the target audience, the book is for you.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If you&apos;ve never used PostgreSQL before, reading &lt;strong&gt;Mastering PostgreSQL in Application Development&lt;/strong&gt; may convince you to have a look at that awesome piece of technology. My bet is on you switching to PostgreSQL and finding it much better at helping you in your daily work and challenges.&lt;/p&gt;
&lt;p&gt;Even if you&apos;ve been using MySQL all your life, you will learn about standard SQL features and how to use them in a way that applies to more than just PostgreSQL, so the book is going to help you in your daily life.&lt;/p&gt;
&lt;h4&gt;What&apos;s your next adventure now that this book is out?&lt;/h4&gt;
&lt;p&gt;&lt;em&gt;Dimitri&lt;/em&gt;: There are more things that I want to do that a lifetime allows, and I am in the process of choosing what is going to be my next adventure. I feel so lucky to be able to have that problem to solve… and it still isn&apos;t the easiest one for me.&lt;/p&gt;
&lt;p&gt;What I can tell you is that I have much more PostgreSQL knowledge to share after having been using, promoting, and contributing to this database server technology for about 20 years now. So if that first book sells well, I will get back to filling empty pages and deliver more contents to help developers making the best of SQL, to help developers on their road to Mastering PostgreSQL!&lt;/p&gt;
&lt;h4&gt;Thanks Dimitri!&lt;/h4&gt;
&lt;p&gt;I&apos;ve just read the book and found it fantastic. It contains tons of tips on how to use PostgreSQL correctly, and I discovered SQL features I had no clue about. The book uses real data that you can fetch and play with. It provides the data and a Docker container with everything included so you can edit the query yourself and try it out. There is no better way to learn things than to play with the examples that are included, in just a few clicks!&lt;/p&gt;
&lt;p&gt;The book also features a few interviews with SQL experts from the PostgreSQL community and from the development community, which gives great insight about how to use the software.&lt;/p&gt;
&lt;p&gt;Dimitri is offering &lt;strong&gt;15% off for my readers&lt;/strong&gt; during the next 48 hours for any of the edition of the book. Just use the &lt;strong&gt;PYTHON-LOVES-POSTGRESQL&lt;/strong&gt; coupon code in any of the following package:&lt;/p&gt;
&lt;p&gt;.product img { max-width: 100%; margin-top: 10px; } .col-sm-1 { width: 8.33333333%; float: left; } .col-sm-3 { width: 25%; float: left; } .col-sm-9 { width: 75%; float: left; } .col-sm-11 { width: 91.66666667%; float: left; /* should be on the div not here but well.. */ padding-left: 30px; padding-bottom: 20px; } .row { clear: both; } .btn.btn-default { background-color: #e6940e; color: #FFF; line-height: 46px; height: 50px; font-size: 19px; cursor: pointer; text-align: center; border-radius: 5px; border: 3px solid #e6940e; vertical-align: middle; display: inline-block; padding: 0 30px; position: relative; outline: none !important; transition: color .3s ease,background .3s ease,border-color .3s ease,opacity .3s ease; box-shadow: none; }&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://gumroad.com/a/623817843/szoX&quot;&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/03/MasteringPostgreSQLinAppDev-Cover.png&quot; alt=&quot;Mastering PostgreSQL – Enterprise Edition&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://gumroad.com/a/623817843/szoX&quot;&gt;&lt;/a&gt;Mastering PostgreSQL – Enterprise Edition&lt;/h3&gt;
&lt;p&gt;$179 &lt;strong&gt;$152&lt;/strong&gt;&lt;br /&gt;
with coupon code &lt;strong&gt;PYTHON-LOVES-POSTGRESQL&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The Enterprise Edition includes:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/03/ebook_reader.png&quot; alt=&quot;E-book reader icon&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The book in PDF, EPUB and MOBI formats.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/03/icon_mic.png&quot; alt=&quot;Microphone icon&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Interviews from industry veterans who began building web application in the previous century. They&apos;ve been there and have opinions to share about how to approach SQL.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/03/icon_database.png&quot; alt=&quot;Database icon&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The PostgreSQL database dump that you need to run the queries against, with a script to restore it easily. The database includes all the 12 datasets used in the book.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/03/docker-logo.png&quot; alt=&quot;Docker logo&quot; /&gt;&lt;/p&gt;
&lt;p&gt;A Docker container image of an already loaded PostgreSQL database with the whole 12 datasets in 56 tables, and the 265 SQL queries each in their own .sql file and a Web-based application for easily running and editing the SQL queries.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/03/certificate.png&quot; alt=&quot;Certificate icon&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Licence for you to share the book and the Docker set-up with up to 50 people, including you. That&apos;s everything you need for your whole team to master SQL!&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://gumroad.com/a/623817843/szoX&quot;&gt;Buy the Enterprise Edition&lt;/a&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;a href=&quot;https://gumroad.com/a/623817843/koprL&quot;&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/03/MasteringPostgreSQLinAppDev-Cover.png&quot; alt=&quot;Mastering PostgreSQL – Full Edition&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://gumroad.com/a/623817843/koprL&quot;&gt;&lt;/a&gt;Mastering PostgreSQL – Full Edition&lt;/h3&gt;
&lt;p&gt;$89 &lt;strong&gt;$75&lt;/strong&gt;&lt;br /&gt;
with coupon code &lt;strong&gt;PYTHON-LOVES-POSTGRESQL&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The Full Edition includes:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/03/ebook_reader.png&quot; alt=&quot;E-book reader icon&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The book in PDF, EPUB and MOBI formats.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/03/icon_mic.png&quot; alt=&quot;Microphone icon&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Interviews from industry veterans who began building web application in the previous century. They&apos;ve been there and have opinions to share about how to approach SQL.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/03/icon_database.png&quot; alt=&quot;Database icon&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The PostgreSQL database dump that you need to run the queries against, with a script to restore it easily. The database includes all the 12 datasets used in the book.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://gumroad.com/a/623817843/koprL&quot;&gt;Buy the Full Edition&lt;/a&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;a href=&quot;https://gumroad.com/a/623817843/WhNVv&quot;&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/03/MasteringPostgreSQLinAppDev-Cover.png&quot; alt=&quot;Mastering PostgreSQL&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://gumroad.com/a/623817843/WhNVv&quot;&gt;&lt;/a&gt;Mastering PostgreSQL&lt;/h3&gt;
&lt;p&gt;$39 &lt;strong&gt;$33&lt;/strong&gt;&lt;br /&gt;
with coupon code &lt;strong&gt;PYTHON-LOVES-POSTGRESQL&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The Standard Edition includes:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/03/ebook_reader.png&quot; alt=&quot;E-book reader icon&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The book in PDF, EPUB and MOBI formats.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://julien.danjou.info/content/images/03/icon_mic.png&quot; alt=&quot;Microphone icon&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Interviews from industry veterans who began building web application in the previous century. They’ve been there and have opinions to share about how to approach SQL.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://gumroad.com/a/623817843/WhNVv&quot;&gt;Buy the book&lt;/a&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;If you have any question, feel free to reach &lt;a href=&quot;mailto:dim@tapoueh.org&quot;&gt;Dimitri&lt;/a&gt; directly and he will be happy to reply. Or write in the comment section below!&lt;/p&gt;
&lt;p&gt;And don&apos;t worry: if the book is not what you expect it to be and has no value to you, then just say so and Dimitri will refund you, no questions asked.&lt;/p&gt;
</content:encoded><category>books</category><category>databases</category></item><item><title>From decimal to timestamp with MySQL</title><link>https://julien.danjou.info/blog/python-sqlalchemy-from-decimal-to-timestamp/</link><guid isPermaLink="true">https://julien.danjou.info/blog/python-sqlalchemy-from-decimal-to-timestamp/</guid><description>When working with timestamps, one question that often arises is the precision of those timestamps. Most software is good enough with a precision up to the second, and that&apos;s easy. But in some cases, l</description><pubDate>Thu, 08 Sep 2016 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;When working with timestamps, one question that often arises is the precision of those timestamps. Most software is good enough with a precision up to the second, and that&apos;s easy. But in some cases, like working on metering, a finer precision is required.&lt;/p&gt;
&lt;p&gt;I don&apos;t know exactly why, and it makes me suffer every day, but &lt;a href=&quot;http://openstack.org&quot;&gt;OpenStack&lt;/a&gt; is really tied to &lt;a href=&quot;http://mysql.com&quot;&gt;MySQL&lt;/a&gt; (and its clones). It hurts because MySQL is a very poor solution if you want to leverage your database to actually solve problems. But that&apos;s how life is, unfair. And in the context of the projects I work on, that boils down to that we can&apos;t afford to not support MySQL.&lt;/p&gt;
&lt;p&gt;So here we are, needing to work with MySQL and at the same time requiring timestamp with a finer precision than just seconds. And guess what: MySQL did not support that until 2011.&lt;/p&gt;
&lt;h2&gt;No microseconds in MySQL? No problem: DECIMAL!&lt;/h2&gt;
&lt;p&gt;MySQL 5.6.4 (released in 2011), a beta version of MySQL 5.6 (hello MySQL, ever heard of &lt;a href=&quot;http://semver.org&quot;&gt;Semantic Versioning&lt;/a&gt;?), brought microsecond precision to timestamps. But the first stable version supporting that, MySQL 5.6.10, was only released in 2013. So for a long time, there was a problem without any solution.&lt;/p&gt;
&lt;p&gt;The obvious workaround, in this case, is to reassess your choices in technologies, discover that &lt;a href=&quot;https://www.postgresql.org/docs/7.1/static/datatype-datetime.html&quot;&gt;PostgreSQL supports microsecond precision for at least a decade&lt;/a&gt; and problem solved.&lt;/p&gt;
&lt;p&gt;This is not what happened in our case, and in order to support MySQL, one had to find a workaround. And so did they in our &lt;a href=&quot;http://launchpad.net/ceilometer&quot;&gt;Ceilometer&lt;/a&gt; project, using a &lt;a href=&quot;https://dev.mysql.com/doc/refman/5.7/en/precision-math-decimal-characteristics.html&quot;&gt;&lt;code&gt;DECIMAL&lt;/code&gt;&lt;/a&gt; type instead of &lt;code&gt;DATETIME&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;DECIMAL&lt;/code&gt; type takes 2 arguments: the total number of digits you need to store, and how many in that total will be used for the fractional part. Knowing that the internal storage of MySQL uses 1 byte for 2 digits, 2 bytes for 4 digits, 3 bytes for 6 digits and 4 bytes for 9 digits, and that each part is stored independently, in order to maximize your storage space, you want to pick a number of digits that fits that correctly.&lt;/p&gt;
&lt;p&gt;This is why Ceilometer picked 14 for the integer part (9 digits on 4 bytes and 5 digits on 3 bytes) and 6 for the decimal part (3 bytes).&lt;/p&gt;
&lt;p&gt;Wait. It&apos;s stupid because:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;DECIMAL(20, 6)&lt;/code&gt; implies that you uses 14 digits for the integer part, which using epoch as a reference makes you able to encode timestamp &lt;code&gt;(10^14) - 1&lt;/code&gt; which is year 3170843. I am certain Ceilometer won&apos;t last that far.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;14 digits is 9 + 5 digits in MySQL which is 7 bytes, the same size that is used for 9 + 6 digits. So if you could have &lt;code&gt;DECIMAL(21, 6)&lt;/code&gt; for the same storage space (and go up to year 31690708 which is a nice bonus, right?)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Well, I guess the original author of the patch did not read the documentation entirely (&lt;code&gt;DECIMAL(20, 6)&lt;/code&gt; being on the MySQL documentation page as an example, I imagine it just has been copy-pasted blindly?).&lt;/p&gt;
&lt;p&gt;The best choice for this use case would have been &lt;code&gt;DECIMAL(17, 6)&lt;/code&gt; which would allow storing 11 digits for integer (5 bytes), supporting timestamp up to &lt;code&gt;(2^11)-1&lt;/code&gt; (year 5138), and 6 digits for decimal part (3 bytes), using only 8 bytes in total per timestamp.&lt;/p&gt;
&lt;p&gt;Nonetheless, this workaround has been implemented using a &lt;a href=&quot;http://sqlalchemy.org&quot;&gt;SQLAlchemy&lt;/a&gt; custom type and works as expected:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class PreciseTimestamp(sqlalchemy.types.TypeDecorator):
    &quot;&quot;&quot;Represents a timestamp precise to the microsecond.&quot;&quot;&quot;

    impl = sqlalchemy.DateTime

    def load_dialect_impl(self, dialect):
        if dialect.name == &apos;mysql&apos;:
            return sqlalchemy.dialect.type_descriptor(
                sqlalchemy.types.DECIMAL(precision=20,
                                         scale=6,
                                         asdecimal=True))
        return sqlalchemy.dialect.type_descriptor(self.impl)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Microseconds in MySQL? Damn, migration!&lt;/h2&gt;
&lt;p&gt;As I said, MySQL 5.6.4 brought microseconds precision to the table (pun intended). Therefore, it&apos;s a great time to migrate away from this hackish format to the brand new one.&lt;/p&gt;
&lt;p&gt;First, be aware that the default &lt;code&gt;DATETIME&lt;/code&gt; type has no microseconds precision: &lt;a href=&quot;http://dev.mysql.com/doc/refman/5.7/en/datetime.html&quot;&gt;you have to specify how many digits you want as an argument&lt;/a&gt;.&lt;br /&gt;
To support microseconds, you should therefore use &lt;code&gt;DATETIME(6)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If we were using a great RDBMS, let&apos;s say, hum, PostgreSQL, we could do that&lt;br /&gt;
very easily, see:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;postgres=# CREATE TABLE foo (mytime decimal);
CREATE TABLE
postgres=# \d foo
      Table &quot;public.foo&quot;
 Column │  Type   │ Modifiers
────────┼─────────┼───────────
 mytime │ numeric │
postgres=# INSERT INTO foo (mytime) VALUES (1473254401.234);
INSERT 0 1
postgres=# ALTER TABLE foo ALTER COLUMN mytime SET DATA TYPE timestamp with time zone USING to_timestamp(mytime);
ALTER TABLE
postgres=# \d foo
              Table &quot;public.foo&quot;
 Column │           Type           │ Modifiers
────────┼──────────────────────────┼───────────
 mytime │ timestamp with time zone │

postgres=# select * from foo;
           mytime
────────────────────────────
 2016-09-07 13:20:01.234+00
(1 row)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And since this is a pretty common use case, it&apos;s even &lt;a href=&quot;https://www.postgresql.org/docs/9.5/static/sql-altertable.html&quot;&gt;an example in the PostgreSQL documentation&lt;/a&gt;. The version from the documentation uses a calculation based on epoch, whereas my example here leverages the &lt;code&gt;to_timestamp()&lt;/code&gt; function. That&apos;s my personal touch.&lt;/p&gt;
&lt;p&gt;Obviously, doing this conversion in a single line is not possible with MySQL: it does not implement the &lt;code&gt;USING&lt;/code&gt; keyword on &lt;code&gt;ALTER TABLE … ALTER COLUMN&lt;/code&gt;. So what&apos;s the solution gonna be? Well, it&apos;s a 4 steps job:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create a new column of type &lt;code&gt;DATETIME(6)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Copy data from the old column to the new column, converting them to the new format&lt;/li&gt;
&lt;li&gt;Delete the old column&lt;/li&gt;
&lt;li&gt;Rename the new column to the old column name.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;But I know what you&apos;re thinking: there are 4 steps, but that&apos;s not a problem, we&apos;ll just use a transaction and embed these operations inside.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://dev.mysql.com/doc/refman/5.7/en/cannot-roll-back.html&quot;&gt;MySQL does not support transactions on data definition language (DDL)&lt;/a&gt;.&lt;br /&gt;
So if any of those steps fails, you&apos;ll be unable rollback steps 1, 3 and 4. Who knew that using MySQL was like living on the edge, right?&lt;/p&gt;
&lt;h2&gt;Doing this in Python with our friend Alembic&lt;/h2&gt;
&lt;p&gt;I like &lt;a href=&quot;http://alembic.zzzcomputing.com/&quot;&gt;Alembic&lt;/a&gt;. It&apos;s a Python library based on &lt;a href=&quot;http://sqlalchemy.org&quot;&gt;SQLAlchemy&lt;/a&gt; that handles schema migration for your favorite RDBMS.&lt;/p&gt;
&lt;p&gt;Once you created a new alembic migration script using &lt;code&gt;alembic revision&lt;/code&gt;, it&apos;s time to edit it and write something along those lines:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from alembic import op
import sqlalchemy as sa
from sqlalchemy.sql import func

class Timestamp(sa.types.TypeDecorator):
    &quot;&quot;&quot;Represents a timestamp precise to the microsecond.&quot;&quot;&quot;

    impl = sqlalchemy.DateTime

    def load_dialect_impl(self, dialect):
        if dialect.name == &apos;mysql&apos;:
            return dialect.type_descriptor(mysql.DATETIME(fsp=6))
        return self.impl

def upgrade():
    bind = op.get_bind()
    if bind and bind.engine.name == &quot;mysql&quot;:
        existing_type = sa.types.DECIMAL(
            precision=20, scale=6, asdecimal=True)
        existing_col = sa.Column(&quot;mytime&quot;, existing_type, nullable=False)
        temp_col = sa.Column(&quot;mytime_ts&quot;, Timestamp(), nullable=False)
        # Step 1: ALTER TABLE mytable ADD COLUMN mytime_ts DATETIME(6)
        op.add_column(&quot;mytable&quot;, temp_col)
        t = sa.sql.table(&quot;mytable&quot;, existing_col, temp_col)
        # Step 2: UPDATE mytable SET mytime_ts=from_unixtime(mytime)
        op.execute(t.update().values(mytime_ts=func.from_unixtime(existing_col)}))
        # Step 3: ALTER TABLE mytable DROP COLUMN mytime
        op.drop_column(&quot;mytable&quot;, &quot;mytime&quot;)
        # Step 4: ALTER TABLE mytable CHANGE mytime_ts mytime
        # Note: MySQL needs to have all the old/new information to just rename a column…
        op.alter_column(&quot;mytable&quot;,
                        &quot;mytime_ts&quot;,
                        nullable=False,
                        type_=Timestamp(),
                        existing_nullable=False,
                        existing_type=existing_type,
                        new_column_name=&quot;mytime&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In MySQL, the function to convert a float to a UNIX timestamp is &lt;code&gt;from_unixtime()&lt;/code&gt;, so the script leverages it to convert the data. As said, you&apos;ll notice we don&apos;t bother using any kind of transaction, so if anything goes wrong, there&apos;s no rollback, and it won&apos;t be possible to re-run the migration without a manual intervention.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;TimestampUTC&lt;/code&gt; is a custom class that implements &lt;code&gt;sqlalchemy.DateTime&lt;/code&gt; using a &lt;code&gt;DATETIME(6)&lt;/code&gt; type for MySQL, and a regular &lt;code&gt;sqlalchemy.DateTime&lt;/code&gt; type for other back-ends. It is used by the rest of the code (e.g. ORM model) but I&apos;ve pasted it in this example for a better understanding.&lt;/p&gt;
&lt;p&gt;Once written, you can easily test your migration using &lt;a href=&quot;https://github.com/jd/pifpaf&quot;&gt;&lt;em&gt;pifpaf&lt;/em&gt;&lt;/a&gt; to run a temporary database:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ pifpaf run mysql $SHELL
$ alembic -c alembic/alembic.ini upgrade 1c98ac614015 # upgrade to the initial revision
$ mysql -S $PIFPAF_MYSQL_SOCKET pifpaf
mysql&amp;gt; INSERT INTO mytable (mytime) VALUES (1325419200.213000);
Query OK, 1 row affected (0.00 sec)

mysql&amp;gt; SELECT * FROM mytable;
+-------------------+
| mytime            |
+-------------------+
| 1325419200.213000 |
+-------------------+
1 row in set (0.00 sec)

$ alembic -c alembic/alembic.ini upgrade head

$ mysql -S $PIFPAF_MYSQL_SOCKET pifpaf
mysql&amp;gt; SELECT * FROM mytable;
+----------------------------+
| mytime                     |
+----------------------------+
| 2012-01-01 13:00:00.213000 |
+----------------------------+
1 row in set (0.00 sec)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And voilà, we just migrated unsafely our data to a new fancy format. Thank you Alembic for solving a problem we would not have without MySQL. 😊&lt;/p&gt;
</content:encoded><category>python</category><category>databases</category><category>openstack</category></item><item><title>Overriding cl-json object encoding</title><link>https://julien.danjou.info/blog/cl-postmodern-dao-json/</link><guid isPermaLink="true">https://julien.danjou.info/blog/cl-postmodern-dao-json/</guid><description>CL-JSON provides an encoder for Lisp data structures and objects to JSON format. Unfortunately, in some case, its default encoding mechanism for CLOS objects isn&apos;t exactly doing the right thing.</description><pubDate>Fri, 11 Jan 2013 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;http://common-lisp.net/project/cl-json/&quot;&gt;CL-JSON&lt;/a&gt; provides an encoder for Lisp data structures and objects to JSON format. Unfortunately, in some case, its default encoding mechanism for CLOS objects isn&apos;t exactly doing the right thing. I&apos;ll show you how Common Lisp makes it easy to change that.&lt;/p&gt;
&lt;h2&gt;Identifying the problem&lt;/h2&gt;
&lt;h3&gt;CL-JSON &amp;amp; CLOS&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;CL-JSON&lt;/em&gt; mechanism encoding CLOS object is really neat. Let&apos;s see how it works for a simple case:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(defclass kitten ()
  ((tail :initarg :tail)))

(json:encode-json-to-string (make-instance &apos;kitten :tail &apos;black))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;will produce:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{&quot;tail&quot;:&quot;black&quot;}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Still using CL-JSON, we can also decode the JSON object to a CLOS object:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(slot-value
 (json:with-decoder-simple-clos-semantics
   (json:decode-json-from-string &quot;{\&quot;tail\&quot;:\&quot;black\&quot;}&quot;))
 :tail)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That code will return &lt;em&gt;&quot;black&quot;&lt;/em&gt;. Note that it&apos;s also possible to specify which class should be used when decoding objects, but that&apos;s beyond the purpose of this article.&lt;/p&gt;
&lt;h3&gt;Postmodern&lt;/h3&gt;
&lt;p&gt;Now, let&apos;s introduce &lt;a href=&quot;http://marijnhaverbeke.nl/postmodern/&quot;&gt;Postmodern&lt;/a&gt;, a wonderful Common Lisp system providing access to the wonderful &lt;a href=&quot;http://postgresql.org&quot;&gt;PostgreSQL&lt;/a&gt; database. It also provides a simple system to map rows in a database to CLOS classes, called DAO for &lt;em&gt;Database access objects&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;With this, we can easily store our &lt;em&gt;kitten&lt;/em&gt; into a table.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(defclass kitten ()
  ((tail :initarg :tail))
  (:metaclass postmodern:dao-class))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If we try to encode this to JSON, it will produce the exact same result seen previously.&lt;/p&gt;
&lt;p&gt;The problem is what happens when one of our column has a &lt;em&gt;NULL&lt;/em&gt; value. Postmodern encodes this using the &lt;em&gt;:null&lt;/em&gt; symbol.&lt;/p&gt;
&lt;p&gt;So this code:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(defclass kitten ()
  ((tail :initarg :tail :col-type (or s-sql:db-null text)))
  (:metaclass postmodern:dao-class))

(postmodern:deftable kitten
  (postmodern:!dao-def))

(postmodern:connect-toplevel …)

(postmodern:create-table &apos;kitten)

(json:encode-json-to-string
  (postmodern:make-dao &apos;kitten))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;will return:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&quot;{&quot;tail&quot;:&quot;null&quot;}&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Fail! The fact that the column is &lt;em&gt;NULL&lt;/em&gt; is represented by the &lt;em&gt;:null&lt;/em&gt; symbol. And CL-JSON encodes all symbols as string.&lt;/p&gt;
&lt;p&gt;This is not at all what we want here!&lt;/p&gt;
&lt;h2&gt;Overriding encode-json&lt;/h2&gt;
&lt;p&gt;CL-JSON provides and uses the &lt;em&gt;encode-json&lt;/em&gt; method to encode all kind of object. It is defined as a &lt;em&gt;generic function&lt;/em&gt;, and a lot of different methods are implemented to handle the different standard Common Lisp types. The one used for &lt;em&gt;standard-object&lt;/em&gt; is defined liked that:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(defmethod encode-json ((o standard-object)
                        &amp;amp;optional (stream *json-output*))
  &quot;Write the JSON representation (Object) of the CLOS object O to
STREAM (or to *JSON-OUTPUT*).&quot;
  (with-object (stream)
    (map-slots (stream-object-member-encoder stream) o)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;All we need to do here, is to create a new method for our &lt;em&gt;kitten&lt;/em&gt; objects, that handles correctly the &lt;em&gt;:null&lt;/em&gt; case.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(defclass kitten ()
  ((tail :initarg :tail :col-type (or s-sql:db-null text)))
  (:metaclass postmodern:dao-class))

(export &apos;kitten)

;; Switch package just to define the new method
(in-package :json)
(defmethod encode-json ((o cl-user:kitten)
                        &amp;amp;optional (stream json:*json-output*))
  &quot;Write the JSON representation (Object) of the postmodern DAO CLOS object
O to STREAM (or to *JSON-OUTPUT*).&quot;
  (with-object (stream)
    (map-slots (lambda (key value)
                 (as-object-member (key stream)
                   (encode-json (if (eq value :null) nil value) stream)))
               o)))

;; Go back into our package
(in-package :cl-user)

(postmodern:deftable kitten
  (postmodern:!dao-def))

(postmodern:connect-toplevel …)

(postmodern:create-table &apos;kitten)

(json:encode-json-to-string
  (postmodern:make-dao &apos;kitten))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With that new method, as soon as we encounter a &lt;em&gt;:null&lt;/em&gt; symbol as a value for an object&apos;s slot, we replace it by &lt;em&gt;nil&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Now if we try to encode another &lt;em&gt;kitten&lt;/em&gt;, we&apos;ll get:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{&quot;tail&quot;:null}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;which is far better for our JavaScript data consumers!&lt;/p&gt;
&lt;p&gt;In the end, I think that this kind of trick is feasible that easily because of the way CLOS provides its generic method implementation.&lt;br /&gt;
The fact that methods don&apos;t belong to any class makes the extension of every program, library and class so much easier. Doing this in another language like Java would likely by impossible, and in Python it would unlikely be as clean as it is done in Common Lisp.&lt;/p&gt;
&lt;p&gt;The ability to teach &lt;em&gt;any&lt;/em&gt; library about how it should handle your class just by defining a new method is really handy!&lt;/p&gt;
</content:encoded><category>lisp</category><category>web</category><category>databases</category></item></channel></rss>