<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Lukáš Lalinský &#187; MusicBrainz</title>
	<atom:link href="http://oxygene.sk/lukas/category/musicbrainz/feed/" rel="self" type="application/rss+xml" />
	<link>http://oxygene.sk/lukas</link>
	<description>Random notes and stuff</description>
	<lastBuildDate>Thu, 02 Feb 2012 20:17:03 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>MusicBrainz/Acoustid integration</title>
		<link>http://oxygene.sk/lukas/2011/08/musicbrainz-acoustid-integration/</link>
		<comments>http://oxygene.sk/lukas/2011/08/musicbrainz-acoustid-integration/#comments</comments>
		<pubDate>Sun, 14 Aug 2011 13:06:56 +0000</pubDate>
		<dc:creator>Lukáš Lalinský</dc:creator>
				<category><![CDATA[Acoustid]]></category>
		<category><![CDATA[MusicBrainz]]></category>
		<category><![CDATA[acoustid]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[userscript]]></category>

		<guid isPermaLink="false">http://oxygene.sk/lukas/?p=1604</guid>
		<description><![CDATA[Update: As of Jan 12, 2012, Acoustid links are now displayed on MusicBrainz by default. While the Acoustid database is reimporting, I wanted to do something fun, so tried to integrate Acoustid links into the MusicBrainz website. I wrote a &#8230; <a href="http://oxygene.sk/lukas/2011/08/musicbrainz-acoustid-integration/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><em><strong>Update: </strong>As of <a href="http://blog.musicbrainz.org/?p=1244">Jan 12, 2012</a>, Acoustid links are now displayed on MusicBrainz by default.</em></p>
<p>While the Acoustid database is reimporting, I wanted to do something fun, so tried to integrate Acoustid links into the MusicBrainz website. I wrote a simple <a href="http://userscripts.org/scripts/show/110183">user script</a> that calls the Acoustid API, loads all IDs linked to a recording and displays the data right next to the list of PUIDs. If you install the script, the &#8220;PUIDs&#8221; page will now look like this:</p>
<p><a href="http://oxygene.sk/lukas/blog/wp-content/uploads/mbacoustid-mb.png"><img class="aligncenter size-medium wp-image-1605" title="MusicBrainz/Acoustid integration" src="http://oxygene.sk/lukas/blog/wp-content/uploads/mbacoustid-mb-300x230.png" alt="" width="300" height="230" /></a></p>
<p>It links back to the Acoustid track pages, which you can see for example <a href="http://acoustid.org/track/c149da2b-91fb-4253-80fe-c9645fe8e92f">here</a>. The database is still very small, so you will probably not see the links too often, but that should get better soon.</p>
<p>The next step, which is probably not going to be this easy, will be adding the &#8220;Remove&#8221; links to the pages also for Acoustid tracks and actually making them work.</p>
]]></content:encoded>
			<wfw:commentRss>http://oxygene.sk/lukas/2011/08/musicbrainz-acoustid-integration/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Easier MusicBrainz NGS database setup</title>
		<link>http://oxygene.sk/lukas/2011/03/easier-musicbrainz-ngs-database-setup/</link>
		<comments>http://oxygene.sk/lukas/2011/03/easier-musicbrainz-ngs-database-setup/#comments</comments>
		<pubDate>Tue, 29 Mar 2011 06:03:16 +0000</pubDate>
		<dc:creator>Lukáš Lalinský</dc:creator>
				<category><![CDATA[MusicBrainz]]></category>
		<category><![CDATA[ngs]]></category>
		<category><![CDATA[postgresql]]></category>
		<category><![CDATA[replication]]></category>

		<guid isPermaLink="false">http://oxygene.sk/lukas/?p=1307</guid>
		<description><![CDATA[Some time ago I wrote a couple of tools that help me set up and update a mirror of the MusicBrainz database on the Acoustid server. It turned out to be work really well. Recently I&#8217;ve seen a few people &#8230; <a href="http://oxygene.sk/lukas/2011/03/easier-musicbrainz-ngs-database-setup/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://oxygene.sk/lukas/2010/10/musicbrainz-database-replication/">Some time ago</a> I wrote a couple of tools that help me set up and update a mirror of the MusicBrainz database on the Acoustid server. It turned out to be work really well. Recently I&#8217;ve seen a few people struggling with setting up the NGS database using the original server codebase. The official route assumes you are going to run a MB server instance, which makes things a little bit more complicated than it has to be. You have to install a number Perl modules, you have to compile the MusicBrainz-specific PostgreSQL extensions, even though you most likely don&#8217;t need them, you are forced to setup a <code>musicbrainz_db_raw</code> database that you are definitely not going to use, because there is no data in it, etc.</p>
<p>If you just want to have a local copy of the MB NGS database, don&#8217;t want to mess with CPAN or compiling PostgreSQL extensions, you can try the <a href="https://github.com/lalinsky/mbslave">NGS version of mbslave</a>. You only need Python, psycopg2 and PostgreSQL. The number of steps you have to do manually is probably larger than with the official way, but on any Unix-based OS it should be just copy&#038;paste from the <a href="https://github.com/lalinsky/mbslave/blob/master/README.txt">README</a> file and it should really just work, with the benefit of being able to customize everything.</p>
]]></content:encoded>
			<wfw:commentRss>http://oxygene.sk/lukas/2011/03/easier-musicbrainz-ngs-database-setup/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Picard 0.13 released</title>
		<link>http://oxygene.sk/lukas/2011/03/picard-0-13-released/</link>
		<comments>http://oxygene.sk/lukas/2011/03/picard-0-13-released/#comments</comments>
		<pubDate>Sun, 06 Mar 2011 13:26:07 +0000</pubDate>
		<dc:creator>Lukáš Lalinský</dc:creator>
				<category><![CDATA[Announce]]></category>
		<category><![CDATA[MusicBrainz]]></category>
		<category><![CDATA[picard]]></category>
		<category><![CDATA[release]]></category>

		<guid isPermaLink="false">http://oxygene.sk/lukas/?p=1232</guid>
		<description><![CDATA[MusicBrainz Picard wasn&#8217;t under active development for a long time. In fact, the last release was in November 2009. Even due to the situation, some bug fixes accumulated in the source control repository over the time, so the primary goal &#8230; <a href="http://oxygene.sk/lukas/2011/03/picard-0-13-released/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>MusicBrainz Picard <a href="http://forums.musicbrainz.org/viewtopic.php?id=2540">wasn&#8217;t under active development</a> for a long time. In fact, the last release was in November 2009. Even due to the situation, some bug fixes accumulated in the source control repository over the time, so the primary goal of this release is to publish these bug fixes. There were also a few larger patches, such us the <a href="http://article.gmane.org/gmane.comp.audio.musicbrainz.devel/4105">sorting support by Aaron Lambers</a>, but these are not included in this release. I&#8217;m hoping that patches like that will get committed now that 0.13 is released and a new release will follow in less than a year from now. :)</p>
<p>Download:</p>
<ul>
<li><a href="http://ftp.musicbrainz.org/pub/musicbrainz/picard/picard-setup-0.13.exe">Windows Installer</a> (9.0M)</li>
<li><a href="http://ftp.musicbrainz.org/pub/musicbrainz/picard/picard-0.13.tar.gz">Source Code Tarball</a> (1.4M)</li>
</ul>
<p>Changes since the last release:</p>
<ul>
<li>Changed Picard icon license to CC by-sa.</li>
<li>Small UI consistency changes.</li>
<li>Albums with tracks linked to more than one file are never marked as &#8220;completed&#8221;.</li>
<li>Fixed matching of scanned files to tracks while the album is still loading.</li>
<li>Support for properly embedded FLAC pictures.</li>
<li>Existing embedded images in APE and ASF files are removed only if there are new images to replace them.</li>
<li>More strict tagger script validation.</li>
<li>Fixed the $truncate tagger script function.</li>
<li>Proper rounding of track durations.</li>
<li>Fixed a bug with saving images larger than 64k to WMA files.</li>
<li>Added a $swapprefix tagger script function.</li>
<li>Release events with a date are preferred over the ones without a date.</li>
<li>Files that are being saved as marked as pending.</li>
<li>Updated .desktop file to allow opening Picard with multiple files.</li>
<li>Handle the &#8220;open file&#8221; event on Mac OS X.</li>
<li>Added timeouts to the HTTP web service client.</li>
<li>Fixed a bug with albums missing the expand/collapse icons.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://oxygene.sk/lukas/2011/03/picard-0-13-released/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>MusicBrainz database replication</title>
		<link>http://oxygene.sk/lukas/2010/10/musicbrainz-database-replication/</link>
		<comments>http://oxygene.sk/lukas/2010/10/musicbrainz-database-replication/#comments</comments>
		<pubDate>Sat, 30 Oct 2010 09:06:17 +0000</pubDate>
		<dc:creator>Lukáš Lalinský</dc:creator>
				<category><![CDATA[MusicBrainz]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[Database]]></category>
		<category><![CDATA[postgresql]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[replication]]></category>

		<guid isPermaLink="false">http://oxygene.sk/lukas/?p=833</guid>
		<description><![CDATA[I wanted to work on the Acoustid lookup web service and for this I needed to setup a MusicBrainz replicated database slave. Normally I&#8217;d use the Perl code from mb_server, but I didn&#8217;t want to mess up the setup I &#8230; <a href="http://oxygene.sk/lukas/2010/10/musicbrainz-database-replication/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I wanted to work on the Acoustid lookup web service and for this I needed to setup a MusicBrainz replicated database slave. Normally I&#8217;d use the Perl code from mb_server, but I didn&#8217;t want to mess up the setup I have on the machine hosting <a href="http://acoustid.org/">acoustid.org</a> with CPAN packages. I had a plan to write a non-Perl version of the replicated code earlier, but only yesterday I really needed it. It turned out to be easier than I expected, so I already have a working version that I use to update my local MB database. <a href="https://github.com/lalinsky/mbslave">Get it from GitHub</a>, if you would like to give it a try.</p>
<p>It has scripts for importing the database dumps as well as applying replication packets, so it can be used creating a MB database from scratch as well as updating an existing one. Instructions for setting up a new database can be found in the <a href="https://github.com/lalinsky/mbslave/blob/master/README.txt">README</a> file.</p>
<p>There are a few differences between these scripts and <a href="http://bugs.musicbrainz.org/browser/mb_server/branches/RELEASE_20090524-BRANCH/admin">mb_server</a>:</p>
<ol>
<li>Depends only on Python and <a href="http://initd.org/psycopg/">psycopg2</a>. Should be easy to set it up on non-Linux platforms, but I&#8217;ve not tested that.</li>
<li>Doesn&#8217;t require additional space for extracting the database dump tarballs. It decompresses and imports the files on-the-fly.</li>
<li>Can be configured to import the MB database into any schema, not just &#8220;public&#8221;.</li>
<li>Can be configured to not replicate specific tables (e.g. direct search indexes, PUIDs).</li>
<li>Regrouped transactions. The MB replication packet consists of multiple transactions (each of which has multiple database operations). The original replication code in mb_server imports the transactions exactly as they were executed in the master database. My code applies the whole packet in a single transaction. This is a small disadvantage, but from an external point of view (external scripts, triggers), there is no practical difference.</li>
<li>New code, possibly buggy.</li>
</ol>
<p>The code currently assumes that you know how to setup the MusicBrainz database, so it doesn&#8217;t do many checks. It it turns out it&#8217;s useful also to somebody else, I can make it more robust.</p>
]]></content:encoded>
			<wfw:commentRss>http://oxygene.sk/lukas/2010/10/musicbrainz-database-replication/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>libmusicbrainz 3.0.3 released</title>
		<link>http://oxygene.sk/lukas/2010/09/libmusicbrainz-3-0-3-released/</link>
		<comments>http://oxygene.sk/lukas/2010/09/libmusicbrainz-3-0-3-released/#comments</comments>
		<pubDate>Mon, 27 Sep 2010 18:14:17 +0000</pubDate>
		<dc:creator>Lukáš Lalinský</dc:creator>
				<category><![CDATA[Announce]]></category>
		<category><![CDATA[MusicBrainz]]></category>
		<category><![CDATA[libmusicbrainz]]></category>

		<guid isPermaLink="false">http://oxygene.sk/lukas/?p=674</guid>
		<description><![CDATA[I&#8217;ve just released libmusicbrainz 3.0.3. Most of the code was done a long time ago, but I never convinced myself to release it. It would have probably stayed that way, if it wasn&#8217;t for Yury G. Kudryashov&#8217;s patches (thank you!). &#8230; <a href="http://oxygene.sk/lukas/2010/09/libmusicbrainz-3-0-3-released/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve just released libmusicbrainz 3.0.3. Most of the code was done a long time ago, but I never convinced myself to release it. It would have probably stayed that way, if it wasn&#8217;t for <a href="http://thread.gmane.org/gmane.comp.audio.musicbrainz.devel/4031">Yury G. Kudryashov&#8217;s patches</a> (thank you!).</p>
<ul>
<li><a href="http://ftp.musicbrainz.org/pub/musicbrainz/libmusicbrainz-3.0.3.tar.gz">Source code</a> (104K)</li>
<li><a href="http://users.musicbrainz.org/~luks/docs/libmusicbrainz3/">API documentation</a></li>
</ul>
<p>The following things were changed in this version:</p>
<ul>
<li>Use <code>Requires.private</code> instead of <code>Requires</code> for dependencies in <code>libmusicbrainz3.pc</code></li>
<li>Support for reading and submitting ISRCs</li>
<li>Support for reading ratings for all entity type</li>
<li>Full release group and label support</li>
<li>C wrappers for <code>extractFragment</code> and <code>extractUuid</code></li>
<li>Support for filtering by any Lucene query</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://oxygene.sk/lukas/2010/09/libmusicbrainz-3-0-3-released/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Submit tags from Quod Libet to MusicBrainz</title>
		<link>http://oxygene.sk/lukas/2010/07/submit-tags-from-quod-libet-to-musicbrainz/</link>
		<comments>http://oxygene.sk/lukas/2010/07/submit-tags-from-quod-libet-to-musicbrainz/#comments</comments>
		<pubDate>Sun, 18 Jul 2010 13:58:15 +0000</pubDate>
		<dc:creator>Lukáš Lalinský</dc:creator>
				<category><![CDATA[MusicBrainz]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[quod libet]]></category>

		<guid isPermaLink="false">http://oxygene.sk/lukas/?p=514</guid>
		<description><![CDATA[I wanted to write something like this for a long time, but for some reason never did it. MusicBrainz has support for folksonomy tagging since 2007, but the coverage of track tags is still not very good. I try to &#8230; <a href="http://oxygene.sk/lukas/2010/07/submit-tags-from-quod-libet-to-musicbrainz/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I wanted to write something like this for a long time, but for some reason never did it. MusicBrainz has support for folksonomy tagging since 2007, but the coverage of track tags is still not very good. I try to keep some tags in the &#8220;genre&#8221; tag in audio files, but even with one-time import tool, I&#8217;m sure I&#8217;d not remember to run this on new files. So the idea here is to submit these tags to MusicBrainz as I listen to the files in my music player (<a href="http://code.google.com/p/quodlibet/">Quod Libet</a>). It&#8217;s inspired by a Quod Libet plugin called <a href="http://code.google.com/p/thisfred-quodlibet-plugins/">LastFMTagger</a>, which does something similar, but for Last.fm. I had some free time today, so I wrote a <a href="http://dl.dropbox.com/u/5215054/mbtagsubmit.py">plugin</a> that does one-way synchronization of tags from Quod Libet to MusicBrainz. You can install the plugin using the following commands:</p>
<pre>
mkdir -p ~/.quodlibet/plugins/events/
cd ~/.quodlibet/plugins/events/
wget http://dl.dropbox.com/u/5215054/mbtagsubmit.py
</pre>
<p>After you enable it and let it know your MusicBrainz username and password (Music → Plugins), it will watch the songs you listen and if any of them has a &#8220;musicbrainz_trackid&#8221; and at least one &#8220;genre&#8221; tag, it will use the MusicBrainz web service to submit them. The submission normally happens only every half an hour, but if you change many files in a short time, it will submit them in batches of 20 tracks (the maximum number allowed by the web service) every 2 minutes.</p>
]]></content:encoded>
			<wfw:commentRss>http://oxygene.sk/lukas/2010/07/submit-tags-from-quod-libet-to-musicbrainz/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MusicBrainz server code history</title>
		<link>http://oxygene.sk/lukas/2010/04/musicbrainz-server-code-history/</link>
		<comments>http://oxygene.sk/lukas/2010/04/musicbrainz-server-code-history/#comments</comments>
		<pubDate>Sun, 04 Apr 2010 18:14:44 +0000</pubDate>
		<dc:creator>Lukáš Lalinský</dc:creator>
				<category><![CDATA[MusicBrainz]]></category>
		<category><![CDATA[gource]]></category>
		<category><![CDATA[video]]></category>

		<guid isPermaLink="false">http://oxygene.sk/lukas/?p=460</guid>
		<description><![CDATA[After seeing Gource videos for Perl and Twisted today, I wanted to make a similar video for the MusicBrainz server code. Well, and for some of my personal projects, but those turned out to be boring :). Anyway, here is &#8230; <a href="http://oxygene.sk/lukas/2010/04/musicbrainz-server-code-history/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>After seeing <a href="http://code.google.com/p/gource/">Gource</a> videos for <a href="http://www.youtube.com/watch?v=jl9HVEJl_-w">Perl</a> and <a href="http://vimeo.com/10661539">Twisted</a> today, I wanted to make a similar video for the MusicBrainz server code. Well, and for some of my personal projects, but those turned out to be boring :). Anyway, here is the result (<a href="http://www.youtube.com/watch?v=EGe2MyaLNzE">YouTube link</a>):</p>
<p style="text-align: center;"><object width="640" height="505"><param name="movie" value="http://www.youtube.com/v/EGe2MyaLNzE&#038;hl=cs_CZ&#038;fs=1&#038;rel=0&#038;hd=1"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/EGe2MyaLNzE&#038;hl=cs_CZ&#038;fs=1&#038;rel=0&#038;hd=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="505"></embed></object></p>
]]></content:encoded>
			<wfw:commentRss>http://oxygene.sk/lukas/2010/04/musicbrainz-server-code-history/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>UUID generator in PL/pgSQL</title>
		<link>http://oxygene.sk/lukas/2009/10/uuid-generator-in-plpgsql/</link>
		<comments>http://oxygene.sk/lukas/2009/10/uuid-generator-in-plpgsql/#comments</comments>
		<pubDate>Wed, 21 Oct 2009 07:39:18 +0000</pubDate>
		<dc:creator>Lukáš Lalinský</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[MusicBrainz]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[plpgsql]]></category>
		<category><![CDATA[postgresql]]></category>
		<category><![CDATA[sql]]></category>
		<category><![CDATA[uuid]]></category>

		<guid isPermaLink="false">http://oxygene.sk/lukas/blog/?p=38</guid>
		<description><![CDATA[While writing an SQL script to upgrade the MusicBrainz database for the last release, I needed a way to generate new UUIDs from SQL. PostgreSQL has a native UUID data type and a contrib module for generating UUIDs since version &#8230; <a href="http://oxygene.sk/lukas/2009/10/uuid-generator-in-plpgsql/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>While writing an <a href="http://bugs.musicbrainz.org/browser/mb_server/branches/RELEASE_20090524-BRANCH/admin/sql/updates/20090402-2.sql">SQL script</a> to upgrade the MusicBrainz database for the last release, I needed a way to generate new <a href="http://en.wikipedia.org/wiki/Universally_Unique_Identifier">UUIDs</a> from SQL. PostgreSQL has a native UUID data type and a contrib module for generating UUIDs since version 8.3, but this wouldn&#8217;t help me, because I needed it to work with at least version 8.1. I had this idea to write PL/pgSQL functions to generate UUIDs, so I skimmer over the <a href="http://www.ietf.org/rfc/rfc4122.txt">RFC 4122</a> that documents them and found out that it isn&#8217;t actually that hard.</p>
<p>MusicBrainz uses random-based UUIDs (version 4) for all it&#8217;s new IDs, so the first idea was to implement the same. I know I can&#8217;t use this code in the end, because I need a good pseudo-random number generator, but I couldn&#8217;t resist to write it anyway. Messing with bits in high-level languages is always fun :) Here is the result (<em>because of the use of the <code>random()</code> function, don&#8217;t use the code for anything serious</em>):</p>
<pre>CREATE OR REPLACE FUNCTION generate_uuid_v4() RETURNS uuid
    AS $$
DECLARE
    value VARCHAR(36);
BEGIN
    value =          lpad(to_hex(ceil(random() * 255)::int), 2, '0');
    value = value || lpad(to_hex(ceil(random() * 255)::int), 2, '0');
    value = value || lpad(to_hex(ceil(random() * 255)::int), 2, '0');
    value = value || lpad(to_hex(ceil(random() * 255)::int), 2, '0');
    value = value || '-';
    value = value || lpad(to_hex(ceil(random() * 255)::int), 2, '0');
    value = value || lpad(to_hex(ceil(random() * 255)::int), 2, '0');
    value = value || '-';
    value = value || lpad((to_hex((ceil(random() * 255)::int &amp; 15) | 64)), 2, '0');
    value = value || lpad(to_hex(ceil(random() * 255)::int), 2, '0');
    value = value || '-';
    value = value || lpad((to_hex((ceil(random() * 255)::int &amp; 63) | 128)), 2, '0');
    value = value || lpad(to_hex(ceil(random() * 255)::int), 2, '0');
    value = value || '-';
    value = value || lpad(to_hex(ceil(random() * 255)::int), 2, '0');
    value = value || lpad(to_hex(ceil(random() * 255)::int), 2, '0');
    value = value || lpad(to_hex(ceil(random() * 255)::int), 2, '0');
    value = value || lpad(to_hex(ceil(random() * 255)::int), 2, '0');
    value = value || lpad(to_hex(ceil(random() * 255)::int), 2, '0');
    value = value || lpad(to_hex(ceil(random() * 255)::int), 2, '0');
    RETURN value::uuid;
END;
$$ LANGUAGE 'plpgsql';</pre>
<p>It turned out that we need deterministic IDs to be generated from the script, so V4 was out of question. That was good, because we would need a better PNRG for the final version.</p>
<p>The next idea was to create the URL on which the new rows will be server and generate name-based UUIDs using the URL namespace. The idea is to concatenate a namespace and a name, calculate a cryptographic hash of the result, and use it&#8217;s bits to generate the UUID.  There are two options for hashing, either MD5 (version 3) or SHA-1 (version 5). SHA-1 is preferred by the RFC, but PostgreSQL only has a built-in function for MD5, so the decision for us was easy. The code doesn&#8217;t depend any random numbers, so it&#8217;s good enough to use in production.</p>
<pre>CREATE OR REPLACE FUNCTION from_hex(t text) RETURNS integer
    AS $$
DECLARE
    r RECORD;
BEGIN
    FOR r IN EXECUTE 'SELECT x'''||t||'''::integer AS hex' LOOP
        RETURN r.hex;
    END LOOP;
END
$$ LANGUAGE plpgsql IMMUTABLE STRICT;

CREATE OR REPLACE FUNCTION generate_uuid_v3(namespace varchar, name varchar) RETURNS uuid
    AS $$
DECLARE
    value varchar(36);
    bytes varchar;
BEGIN
    bytes = md5(decode(namespace, 'hex') || decode(name, 'escape'));
    value = substr(bytes, 1+0, 8);
    value = value || '-';
    value = value || substr(bytes, 1+2*4, 4);
    value = value || '-';
    value = value || lpad(to_hex((from_hex(substr(bytes, 1+2*6, 2)) &amp; 15) | 48), 2, '0');
    value = value || substr(bytes, 1+2*7, 2);
    value = value || '-';
    value = value || lpad(to_hex((from_hex(substr(bytes, 1+2*8, 2)) &amp; 63) | 128), 2, '0');
    value = value || substr(bytes, 1+2*9, 2);
    value = value || '-';
    value = value || substr(bytes, 1+2*10, 12);
    return value::uuid;
END;
$$ LANGUAGE 'plpgsql' IMMUTABLE STRICT;</pre>
<p>This code should be easy enough to modify to generate UUIDv5, if you have a way to calculate SHA-1 hashes. To use the function, you need to pass it a namespace and a name. The namespace itself is a UUID, it can be anything, but there are a few well-known options:</p>
<ul>
<li><strong>URL</strong><br />
<code>'6ba7b8119dad11d180b400c04fd430c8'</code></li>
<li><strong>DNS</strong> (fully-qualified domain name)<br />
<code>'6ba7b8109dad11d180b400c04fd430c8'</code></li>
<li><strong>ISO OID</strong><br />
<code>'6ba7b8129dad11d180b400c04fd430c8'</code></li>
<li><strong>X.500 DN</strong> (in DER or a text output format)<br />
<code>'6ba7b814-9dad-11d1-80b4-00c04fd430c8'</code></li>
</ul>
<p>The URL one is probably the most useful. So, to generate UUIDv3 for <code>http://www.example.com/foo/1</code>, you can use the following:</p>
<pre>SELECT generate_uuid_v3('6ba7b8119dad11d180b400c04fd430c8', 'http://www.example.com/foo/1');</pre>
]]></content:encoded>
			<wfw:commentRss>http://oxygene.sk/lukas/2009/10/uuid-generator-in-plpgsql/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

