<?xml version="1.0" encoding="UTF-8" standalone="yes"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-us"><id>https://blog.pgxn.org/tags/postgresql/</id><title>PostgreSQL</title><updated>2023-02-18T22:53:46Z</updated><link rel="self" type="application/atom+xml" href="https://blog.pgxn.org/tags/postgresql/feed.xml"/><link rel="alternate" type="text/html" href="https://blog.pgxn.org/tags/postgresql/"/><author><name>The PGXN Maintainers</name></author><generator uri="https://gohugo.io/" version="0.167.0">Hugo</generator><entry><id>https://blog.pgxn.org/post/709635160523620352</id><title type="html">Hello Mastodon 🐘</title><link rel="alternate" type="text/html" href="https://blog.pgxn.org/2023/hello-mastodon/"/><updated>2026-10-07T16:13:48Z</updated><published>2023-02-18T22:53:46Z</published><author><name>David E. Wheeler</name></author><category scheme="https://blog.pgxn.org/tags" term="pgxn" label="PGXN"/><category scheme="https://blog.pgxn.org/tags" term="mastodon" label="Mastodon"/><category scheme="https://blog.pgxn.org/tags" term="twitter" label="Twitter"/><category scheme="https://blog.pgxn.org/tags" term="postgresql" label="PostgreSQL"/><category scheme="https://blog.pgxn.org/tags" term="listen/notify" label="LISTEN/NOTIFY"/><summary type="html"><![CDATA[<p>Hey all you Postgres people out there! Just wanted to make a quick post
regarding the PGXN <a href="https://twitter.com/pgxn">twitter bot</a>. In light of the recent announcements by
Twitter to charge for API use, I updated <a href="https://manager.pgxn.org">PGXN Manager</a> to also post to
Mastodon! If you&rsquo;re have joined the exodus to the Fediverse, give it a follow:</p>
<p><a href="https://mastodon.social/@pgxn">@pgxn@mastodon.social</a></p>
<p>In fact, I made some time to rewrite the notification bits of the manager
service. Previously there was just some code jammed into the upload controller
that would make an API call to Twitter. I ripped that out, and added a trigger
to the distributions table that posts a a <a href="https://www.postgresql.org/docs/current/sql-notify.html">LISTEN/NOTIFY</a> message.</p>]]></summary><content type="html" xml:base="https://blog.pgxn.org/" xml:space="preserve"><![CDATA[<p>Hey all you Postgres people out there! Just wanted to make a quick post
regarding the PGXN <a href="https://twitter.com/pgxn">twitter bot</a>. In light of the recent announcements by
Twitter to charge for API use, I updated <a href="https://manager.pgxn.org">PGXN Manager</a> to also post to
Mastodon! If you&rsquo;re have joined the exodus to the Fediverse, give it a follow:</p>
<p><a href="https://mastodon.social/@pgxn">@pgxn@mastodon.social</a></p>
<p>In fact, I made some time to rewrite the notification bits of the manager
service. Previously there was just some code jammed into the upload controller
that would make an API call to Twitter. I ripped that out, and added a trigger
to the distributions table that posts a a <a href="https://www.postgresql.org/docs/current/sql-notify.html">LISTEN/NOTIFY</a> message.</p>
<p>Then I wrote a little service that checks for new notifications every 5
seconds and dispatches to one mor more configured consumers. Today there are
just two: Twitter and Mastodon; in the future the might be more, especially
since I also added triggers to the users and mirrors tables, so we could have
the bot announce new mirrors and users. Should be pretty easy to do, might put
in the time in the next few weeks.</p>
<p>Oh, and for fun, I also added some emoji to the Mastodon posts, as well as the
abstract from new releases. Makes the messages more informative than on
Twitter. Of course, we could probably do the same, there, especially since the
post length was extended to 280 characters sometime after the original bot. I
have in mind to make a little library that allows the customization of
messages via configuration.</p>
]]></content></entry><entry><id>https://blog.pgxn.org/post/15710159951</id><title type="html">PGXN Has a New Home</title><link rel="alternate" type="text/html" href="https://blog.pgxn.org/2012/pgxn-moved/"/><updated>2026-10-07T16:13:48Z</updated><published>2012-01-12T04:51:04Z</published><author><name>David E. Wheeler</name></author><category scheme="https://blog.pgxn.org/tags" term="server" label="Server"/><category scheme="https://blog.pgxn.org/tags" term="postgresql" label="PostgreSQL"/><category scheme="https://blog.pgxn.org/tags" term="depesz" label="depesz"/><category scheme="https://blog.pgxn.org/tags" term="community" label="Community"/><category scheme="https://blog.pgxn.org/tags" term="migration" label="Migration"/><summary type="html"><![CDATA[<p>Day before yesterday, I finally got all of <a href="https://pgxn.org/">PGXN</a> moved to a new server. I had
been using a small server owned by my company, <a href="https://kineticode.com/">Kineticode</a>, and hosted by
<a href="https://commandprompt.com/">Command Prompt</a>. That was fine for a while, but CMD was needing its rack
space back, and what with my <a href="https://justatheory.com/autobiographical/iovationeering.html">new job</a>, I was shutting down Kineticode, too.
It was time to move PGXN elsewhere.</p>
<p>For a while, I got a lot of support and assistance towards moving PGXN to a
<a href="https://www.postgresql.org/">PostgreSQL</a> community server. <a href="https://pgsnake.blogspot.com/">Dave</a>, <a href="https://blog.hagander.net/">Magnus</a>, and <a href="https://www.kaltenbrunner.cc/blog/">Stefan</a> kindly spun up a
VM for me, and gave me permission to install Perl modules from <a href="https://cpan.org">CPAN</a>,
provided I supply them with a script to report to Nagios when Perl modules
were out of date, which of course I did. This was necessary because I built
PGXN with some pretty recent versions of CPAN modules that are not yet
available in Debian stable. I was looking forward to getting things running
and integrating with the community authentication service.</p>]]></summary><content type="html" xml:base="https://blog.pgxn.org/" xml:space="preserve"><![CDATA[<p>Day before yesterday, I finally got all of <a href="https://pgxn.org/">PGXN</a> moved to a new server. I had
been using a small server owned by my company, <a href="https://kineticode.com/">Kineticode</a>, and hosted by
<a href="https://commandprompt.com/">Command Prompt</a>. That was fine for a while, but CMD was needing its rack
space back, and what with my <a href="https://justatheory.com/autobiographical/iovationeering.html">new job</a>, I was shutting down Kineticode, too.
It was time to move PGXN elsewhere.</p>
<p>For a while, I got a lot of support and assistance towards moving PGXN to a
<a href="https://www.postgresql.org/">PostgreSQL</a> community server. <a href="https://pgsnake.blogspot.com/">Dave</a>, <a href="https://blog.hagander.net/">Magnus</a>, and <a href="https://www.kaltenbrunner.cc/blog/">Stefan</a> kindly spun up a
VM for me, and gave me permission to install Perl modules from <a href="https://cpan.org">CPAN</a>,
provided I supply them with a script to report to Nagios when Perl modules
were out of date, which of course I did. This was necessary because I built
PGXN with some pretty recent versions of CPAN modules that are not yet
available in Debian stable. I was looking forward to getting things running
and integrating with the community authentication service.</p>
<p>I got the server built, and everything was working reasonably well. Magnus and
I were just working out some issues with the proxy server configuration, and I
was starting to think about how to migrate the data over. But first, I decided
to refactor the Perl module script to use a <a href="https://metacpan.org/module/ExtUtils::Installed">more efficient implementation</a>. I
fired it off and piped its output to the <code>cpan</code> utility to just get everything
updated. Unfortunately, unlike my first implementation, which reported only on
CPAN-installed modules, this version of the script also reported when
Debian-installed modules were out-of-date. And since I have my CPAN build
configuration set up to remove previous installations, I upgraded all those
modules, replacing them with new versions.</p>
<p>Well, this was a major fuckup on my part. Turns out there&rsquo;s no simple way to
restore Debian-distributed versions of the modules without rebuilding the
entire system. Worse, this was exactly the sort of thing the community
sysadmins feared. They have to maintain a <em>lot</em> of servers. So they naturally
prefer that they all be as similar as possible. The new PGXN server had been
<em>mostly</em> similar to what they had before, and Dave and company had been
willing to compromise quite a bit to get PGXN going, but I, unfortunately,
demonstrated how easy it is to ruin the whole thing.</p>
<p>So we decided that a community server isn&rsquo;t the right place for PGXN. At least
not yet. Perhaps in a year or two the Debian distribution will be updated to
have all the prerequisites I need. Better yet, maybe someone create a PGXN
debian distribution! (Volunteers welcomed.) Then I won&rsquo;t have to do anything
special and we can try again (without any <code>sudo</code> privileges for me!). But in
the meantime, I still needed to move things.</p>
<p>Fortunately, <a href="https://depesz.com/">depesz</a> came to the rescue. He has a very nice box hosting his
blog, <a href="https://explain.depesz.com/">explain.depesz.com</a>, and a few other things, and would I like to set
things up there? Depesz used <a href="https://www.perlbrew.pl/">perlbrew</a> to set up a Perl install just for the
PGXN system accounts, meaning I could install any Perl modules I needed
without interfering with the system Perl. And each account has its own
privileges to run the services it needs (<a href="https://manager.pgxn.org/">Manager</a>, <a href="https://api.pgxn.org/">API</a>, <a href="https://pgxn.org/">Site</a>)
without the risk of breaking anything else. A few days after getting access,
we had everything set up and ready to go. I pulled the trigger on Monday, and
it went of without a hitch.</p>
<p>My thanks to depesz for the server and all the assistance, not to mention his
<a href="https://www.pgxn.org/donors/">donation</a>! PGXN now has a very nice home where it can mature.</p>
<p>And as for the future, I have some thoughts about that, too.</p>
<ul>
<li>I&rsquo;d like to blog about the migration itself, and how easy it is (and isn&rsquo;t)
to build PGXN.</li>
<li>There are <a href="https://github.com/pgxn/pgxn-manager/issues">some</a> <a href="https://github.com/pgxn/pgxn-api/issues">bugs</a> to be fixed and <a href="https://github.com/pgxn/pgxn-manager/issues">minor improvements</a> to be
had. Interested in helping out?</li>
<li>I&rsquo;d love to hear your ideas about how to improve PGXN. What would make it
better? What doesn&rsquo;t work quite right for you now?</li>
</ul>
<p>And yes, now that this migration is finally done, I expect I&rsquo;ll have more time
to blog and work on PGXN going forward. Please leave your thoughts and ideas in
the comments. This thing is wide open to any kind of idea, and I would greatly
appreciate your feedback.</p>
]]></content></entry><entry><id>https://blog.pgxn.org/post/1368261274</id><title type="html">Reserved Extensions</title><link rel="alternate" type="text/html" href="https://blog.pgxn.org/2010/reserved-extensions/"/><updated>2026-10-07T16:13:48Z</updated><published>2010-10-21T20:43:00Z</published><author><name>David E. Wheeler</name></author><category scheme="https://blog.pgxn.org/tags" term="reserved-words" label="Reserved Words"/><category scheme="https://blog.pgxn.org/tags" term="reserved-extensions" label="Reserved Extensions"/><category scheme="https://blog.pgxn.org/tags" term="extensions" label="Extensions"/><category scheme="https://blog.pgxn.org/tags" term="postgresql" label="PostgreSQL"/><category scheme="https://blog.pgxn.org/tags" term="procedural-languages" label="Procedural Languages"/><category scheme="https://blog.pgxn.org/tags" term="pl/pgsql" label="PL/pgSQL"/><category scheme="https://blog.pgxn.org/tags" term="pl/perl" label="PL/Perl"/><category scheme="https://blog.pgxn.org/tags" term="contributed-modules" label="Contributed Modules"/><summary type="html"><![CDATA[<p>I&rsquo;m thinking about how to add support for reserved extensions. These are
extensions that one needs to depend on, but aren&rsquo;t distributed via PGXN.
Primarily, this means stuff distributed with the PostgreSQL core, including:</p>
<ul>
<li>PostgreSQL itself</li>
<li>Bundled procedural languages (plpgsql, plperl, etc.)</li>
<li>All <a href="https://www.postgresql.org/docs/current/static/contrib.html">contributed modules</a></li>
</ul>
<p>Basically, anything that an extension might want to declare as a dependency,
but that isn&rsquo;t on PGXN itself.</p>
<p>There are a number of ways to do this. Which do you think would be the best
approach?</p>]]></summary><content type="html" xml:base="https://blog.pgxn.org/" xml:space="preserve"><![CDATA[<p>I&rsquo;m thinking about how to add support for reserved extensions. These are
extensions that one needs to depend on, but aren&rsquo;t distributed via PGXN.
Primarily, this means stuff distributed with the PostgreSQL core, including:</p>
<ul>
<li>PostgreSQL itself</li>
<li>Bundled procedural languages (plpgsql, plperl, etc.)</li>
<li>All <a href="https://www.postgresql.org/docs/current/static/contrib.html">contributed modules</a></li>
</ul>
<p>Basically, anything that an extension might want to declare as a dependency,
but that isn&rsquo;t on PGXN itself.</p>
<p>There are a number of ways to do this. Which do you think would be the best
approach?</p>
<ol>
<li>Hard-code a list into the source code</li>
<li>Include an editable list in the runtime configuration file</li>
<li>Add a database table reserved for them and an API to edit it</li>
<li>Create a &ldquo;pgdev&rdquo; user and upload a distribution declaring all those
extensions in a <code>META.json</code> file</li>
<li>Same as 4, but actually upload the PostgreSQL source</li>
</ol>
<p>I&rsquo;m leaning towards #2, perhaps having it automatically maintain a list in the
database and a metadata file on the mirrors.</p>
<p>But what do you think? Opinions wanted!</p>
]]></content></entry><entry><id>https://blog.pgxn.org/post/1053165383</id><title type="html">ALIAS Back in Vogue</title><link rel="alternate" type="text/html" href="https://blog.pgxn.org/2010/alias-in-vogue/"/><updated>2026-10-07T16:13:48Z</updated><published>2010-09-02T13:00:00Z</published><author><name>David E. Wheeler</name></author><category scheme="https://blog.pgxn.org/tags" term="alias" label="Alias"/><category scheme="https://blog.pgxn.org/tags" term="postgresql-9" label="PostgreSQL 9"/><category scheme="https://blog.pgxn.org/tags" term="pl/pgsql" label="PL/pgSQL"/><category scheme="https://blog.pgxn.org/tags" term="postgresql" label="PostgreSQL"/><category scheme="https://blog.pgxn.org/tags" term="function" label="Function"/><category scheme="https://blog.pgxn.org/tags" term="parameter" label="Parameter"/><category scheme="https://blog.pgxn.org/tags" term="named-parameter" label="Named Parameter"/><summary type="html"><![CDATA[<p>I&rsquo;ve been hard at work on <a href="https://github.com/theory/pgxn-manager">PGXN Manager</a>, the app for users to upload
distributions to PGXN. I am of course following my own dictum: &ldquo;the database
<em>is</em> the model.&rdquo; As a result, I&rsquo;ve been creating an API for creating,
updating, and deleting entities, as well as generating JSON (more on that
later).</p>
<p>I&rsquo;m also using PostgreSQL 9. The motivation to make the jump to 9.0 was to to
try to use the <a href="https://commitfest.postgresql.org/action/patch_view?id=351">JSON data type patch</a>, but I abandoned it when I couldn&rsquo;t get
it to compile. (I might come back to it later, but right now I&rsquo;m trying to
practice <a href="https://en.wikipedia.org/wiki/YAGNI">YAGNI</a> and <a href="https://www.urbandictionary.com/define.php?term=JFDI">JFDI</a> so that I don&rsquo;t end up owning a yak farm). But
there are other reasons to stick with 9.0, like improved <a href="https://developer.postgresql.org/pgdocs/postgres/hstore.html">hstore</a> support, the
<a href="https://developer.postgresql.org/pgdocs/postgres/sql-do.html">DO</a> statement, and <a href="https://developer.postgresql.org/pgdocs/postgres/sql-syntax-calling-funcs.html#SQL-SYNTAX-CALLING-FUNCS-NAMED">named parameters</a>.</p>]]></summary><content type="html" xml:base="https://blog.pgxn.org/" xml:space="preserve"><![CDATA[<p>I&rsquo;ve been hard at work on <a href="https://github.com/theory/pgxn-manager">PGXN Manager</a>, the app for users to upload
distributions to PGXN. I am of course following my own dictum: &ldquo;the database
<em>is</em> the model.&rdquo; As a result, I&rsquo;ve been creating an API for creating,
updating, and deleting entities, as well as generating JSON (more on that
later).</p>
<p>I&rsquo;m also using PostgreSQL 9. The motivation to make the jump to 9.0 was to to
try to use the <a href="https://commitfest.postgresql.org/action/patch_view?id=351">JSON data type patch</a>, but I abandoned it when I couldn&rsquo;t get
it to compile. (I might come back to it later, but right now I&rsquo;m trying to
practice <a href="https://en.wikipedia.org/wiki/YAGNI">YAGNI</a> and <a href="https://www.urbandictionary.com/define.php?term=JFDI">JFDI</a> so that I don&rsquo;t end up owning a yak farm). But
there are other reasons to stick with 9.0, like improved <a href="https://developer.postgresql.org/pgdocs/postgres/hstore.html">hstore</a> support, the
<a href="https://developer.postgresql.org/pgdocs/postgres/sql-do.html">DO</a> statement, and <a href="https://developer.postgresql.org/pgdocs/postgres/sql-syntax-calling-funcs.html#SQL-SYNTAX-CALLING-FUNCS-NAMED">named parameters</a>.</p>
<p>Actually, this last one is very nice, as it allows me to use SQL syntax to
specify function parameters instead of using an <code>hstore</code> value to hack it. For
example, I have this function for update a user record:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sql" data-lang="sql"><span class="line"><span class="cl"><span class="k">CREATE</span><span class="w"> </span><span class="k">OR</span><span class="w"> </span><span class="k">REPLACE</span><span class="w"> </span><span class="k">FUNCTION</span><span class="w"> </span><span class="n">update_user</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">nick</span><span class="w">  </span><span class="n">LABEL</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">name</span><span class="w">  </span><span class="nb">TEXT</span><span class="w">  </span><span class="k">DEFAULT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">email</span><span class="w"> </span><span class="n">EMAIL</span><span class="w"> </span><span class="k">DEFAULT</span><span class="w"> </span><span class="k">NULL</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">uri</span><span class="w">   </span><span class="n">URI</span><span class="w">   </span><span class="k">DEFAULT</span><span class="w"> </span><span class="k">NULL</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">)</span><span class="w"> </span><span class="k">RETURNS</span><span class="w"> </span><span class="nb">BOOLEAN</span><span class="w"> </span><span class="k">LANGUAGE</span><span class="w"> </span><span class="n">plpgsql</span><span class="w"> </span><span class="k">SECURITY</span><span class="w"> </span><span class="k">DEFINER</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="err">$$</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="k">DECLARE</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">_email</span><span class="w"> </span><span class="k">ALIAS</span><span class="w"> </span><span class="k">FOR</span><span class="w"> </span><span class="n">email</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">_uri</span><span class="w">   </span><span class="k">ALIAS</span><span class="w"> </span><span class="k">FOR</span><span class="w"> </span><span class="n">uri</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="k">BEGIN</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="k">UPDATE</span><span class="w"> </span><span class="n">users</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">SET</span><span class="w"> </span><span class="n">full_name</span><span class="w">  </span><span class="o">=</span><span class="w"> </span><span class="n">COALESCE</span><span class="p">(</span><span class="n">name</span><span class="p">,</span><span class="w">   </span><span class="n">full_name</span><span class="p">),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">email</span><span class="w">      </span><span class="o">=</span><span class="w"> </span><span class="n">COALESCE</span><span class="p">(</span><span class="n">_email</span><span class="p">,</span><span class="w"> </span><span class="n">users</span><span class="p">.</span><span class="n">email</span><span class="p">),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">uri</span><span class="w">        </span><span class="o">=</span><span class="w"> </span><span class="n">COALESCE</span><span class="p">(</span><span class="n">_uri</span><span class="p">,</span><span class="w">   </span><span class="n">users</span><span class="p">.</span><span class="n">uri</span><span class="p">),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="n">updated_at</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">NOW</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">WHERE</span><span class="w"> </span><span class="n">nickname</span><span class="w">   </span><span class="o">=</span><span class="w"> </span><span class="n">nick</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="k">AND</span><span class="w"> </span><span class="n">status</span><span class="w">     </span><span class="o">=</span><span class="w"> </span><span class="s1">&#39;active&#39;</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="k">RETURN</span><span class="w"> </span><span class="k">FOUND</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="k">END</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="err">$$</span><span class="p">;</span><span class="w">
</span></span></span></code></pre></div><p>The nice thing about named parameters is that I can call this function like
so:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sql" data-lang="sql"><span class="line"><span class="cl"><span class="k">SELECT</span><span class="w"> </span><span class="n">update_user</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">nick</span><span class="w">  </span><span class="p">:</span><span class="o">=</span><span class="w"> </span><span class="s1">&#39;theory&#39;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">name</span><span class="w">  </span><span class="p">:</span><span class="o">=</span><span class="w"> </span><span class="s1">&#39;David E. Wheeler&#39;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">email</span><span class="w"> </span><span class="p">:</span><span class="o">=</span><span class="w"> </span><span class="s1">&#39;justatheory@pgxn.org&#39;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">uri</span><span class="w">   </span><span class="p">:</span><span class="o">=</span><span class="w"> </span><span class="s1">&#39;https://www.justatheory.com/&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">);</span><span class="w">
</span></span></span></code></pre></div><p>Hell, since the parameters are named, I can specify them in any order. And
because there are defaults, I can omit one or more of them:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sql" data-lang="sql"><span class="line"><span class="cl"><span class="k">SELECT</span><span class="w"> </span><span class="n">update_user</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">name</span><span class="w">  </span><span class="p">:</span><span class="o">=</span><span class="w"> </span><span class="s1">&#39;David E. Wheeler&#39;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">email</span><span class="w"> </span><span class="p">:</span><span class="o">=</span><span class="w"> </span><span class="s1">&#39;justatheory@pgxn.org&#39;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">nick</span><span class="w">  </span><span class="p">:</span><span class="o">=</span><span class="w"> </span><span class="s1">&#39;theory&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">);</span><span class="w">
</span></span></span></code></pre></div><p>And it will just work. Nice!</p>
<p>One thing I did discover, though: Now that I&rsquo;m using named parameters, I don&rsquo;t
want to use <a href="https://en.wikipedia.org/wiki/Hungarian_notation">Hungarian notation</a> for the parameter names. Back before 9.0,
when callers never saw argument names when calling a function, I could call
them whatever I wanted. This was especially important when executing queries
in PL/pgSQL, because one needs to be aware of parameter (and variable!) names
that conflict with SQL identifiers, especially columns. (Another nice feature
in 9.0 is that it will throw an exception if you create a PL/pgSQL function
with conflicting parameter and identifier names.) But now that the parameter
names are more likely to be exposed and <em>used</em> to the function caller, I want
them to be meaningful.</p>
<p>I messed with this for a while. I was okay with using &ldquo;nick&rdquo; for &ldquo;nickname&rdquo;
and &ldquo;pass&rdquo; for &ldquo;password&rdquo;, but was annoyed with the alternatives for &ldquo;email&rdquo;
and &ldquo;uri,&rdquo; especially since they&rsquo;re used with those names elsewhere (queries
against the table, generated JSON). I really wanted to use parameter names
that were the same as the columns. I tried just using the dollar variables
(<code>$1</code>, <code>$2</code>, etc.), but got errors for them, too: they seem to be compiled
into the parameter names.</p>
<p>Then, on a guess, I tried creating aliases for the variables. From the example
above, its:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sql" data-lang="sql"><span class="line"><span class="cl"><span class="w">    </span><span class="n">_email</span><span class="w"> </span><span class="k">ALIAS</span><span class="w"> </span><span class="k">FOR</span><span class="w"> </span><span class="n">email</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="n">_uri</span><span class="w">   </span><span class="k">ALIAS</span><span class="w"> </span><span class="k">FOR</span><span class="w"> </span><span class="n">uri</span><span class="p">;</span><span class="w">
</span></span></span></code></pre></div><p>Then I used <code>_email</code> and <code>_uri</code> in my <code>UPDATE</code> statement. And what do you
know, it worked! I found this somewhat humorous, given the history of <code>ALIAS</code>.</p>
<p>It used to be, long ago, that you couldn&rsquo;t use the parameter names in the body
of PL/pgSQL functions, so <code>ALIAS</code> was there to let you alias the dollar
variable names to other names. But somewhere around, oh, 8.0 or so, we were
blessed with the ability to use the parameter names directly. Suddenly <code>ALIAS</code>
seemed superfluous. I&rsquo;ve hardly ever used it myself. It&rsquo;s just been sitting
there, like my appendix, waiting for another use.</p>
<p>And now there is one. A really good one! I can safely use parameter names that
are the same as column names in my PL/pgSQL functions as long as I alias them.
And it just works!</p>
<p>Well, almost. It seems that <code>ALIAS</code> means what it says: the parameter names
are still around can can be used. So sometimes you might run into an error
like</p>
<pre tabindex="0"><code>ERROR:  column reference &#34;email&#34; is ambiguous
</code></pre><p>Even though you&rsquo;re not using the variable. I ran into this in the update
function where I was using the column names in the left-hand side of the <code>SET</code>
expressions. The solution, fortunately, is simple: table-qualify the column
names as appropriate:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sql" data-lang="sql"><span class="line"><span class="cl"><span class="k">UPDATE</span><span class="w"> </span><span class="n">users</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">   </span><span class="k">SET</span><span class="w"> </span><span class="n">full_name</span><span class="w">  </span><span class="o">=</span><span class="w"> </span><span class="n">COALESCE</span><span class="p">(</span><span class="n">name</span><span class="p">,</span><span class="w">   </span><span class="n">full_name</span><span class="p">),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">       </span><span class="n">email</span><span class="w">      </span><span class="o">=</span><span class="w"> </span><span class="n">COALESCE</span><span class="p">(</span><span class="n">_email</span><span class="p">,</span><span class="w"> </span><span class="n">users</span><span class="p">.</span><span class="n">email</span><span class="p">),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">       </span><span class="n">uri</span><span class="w">        </span><span class="o">=</span><span class="w"> </span><span class="n">COALESCE</span><span class="p">(</span><span class="n">_uri</span><span class="p">,</span><span class="w">   </span><span class="n">users</span><span class="p">.</span><span class="n">uri</span><span class="p">),</span><span class="w">
</span></span></span></code></pre></div><p>Note the use of <code>users.email</code> instead of just <code>email</code> in the <code>COALESCE()</code>
function. Seems like a reasonable workaround in exchange for the ability to
have parameter names that match column names. I&rsquo;m sold!</p>
<p>Now just to consider whether to change the <code>nick</code> and <code>pass</code> parameter names
to <code>nickname</code> and <code>password</code> in order to be completely consistent. I guess
it&rsquo;s a good idea.</p>
<p>More next week. I&rsquo;ve been doing lots of hacking and have much to share, but
have another project that will take up my time between now and Monday, so I&rsquo;ll
have to come back to it.</p>
<p><strong>Update 2010-08-07:</strong> I turns out that there is a much better way to do this:
Just function-name-qualify parameter names where they might conflict with
database object names:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sql" data-lang="sql"><span class="line"><span class="cl"><span class="k">UPDATE</span><span class="w"> </span><span class="n">users</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">   </span><span class="k">SET</span><span class="w"> </span><span class="n">full_name</span><span class="w">  </span><span class="o">=</span><span class="w"> </span><span class="n">COALESCE</span><span class="p">(</span><span class="n">name</span><span class="p">,</span><span class="w">   </span><span class="n">full_name</span><span class="p">),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">       </span><span class="n">email</span><span class="w">      </span><span class="o">=</span><span class="w"> </span><span class="n">COALESCE</span><span class="p">(</span><span class="n">update_users</span><span class="p">.</span><span class="n">email</span><span class="p">,</span><span class="w"> </span><span class="n">users</span><span class="p">.</span><span class="n">email</span><span class="p">),</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">       </span><span class="n">uri</span><span class="w">        </span><span class="o">=</span><span class="w"> </span><span class="n">COALESCE</span><span class="p">(</span><span class="n">update_users</span><span class="p">.</span><span class="n">uri</span><span class="p">,</span><span class="w">   </span><span class="n">users</span><span class="p">.</span><span class="n">uri</span><span class="p">),</span><span class="w">
</span></span></span></code></pre></div><p>No need for the aliases at all! I had no idea about this feature. Many thanks
to Colin &rsquo;t Hart for the comment below about how this is available in Oracle
and to Tom Lane for <a href="https://archives.postgresql.org/pgsql-hackers/2010-09/msg00404.php">smacking me upside the head</a> with <a href="https://www.postgresql.org/docs/9.0/static/plpgsql-structure.html">the fine manual</a> (look
for the &ldquo;note&rdquo; at the bottom) when I asked about it.</p>
]]></content></entry></feed>