<?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/pl/pgsql/</id><title>PL/PgSQL</title><updated>2010-10-21T20:43:00Z</updated><link rel="self" type="application/atom+xml" href="https://blog.pgxn.org/tags/pl/pgsql/feed.xml"/><link rel="alternate" type="text/html" href="https://blog.pgxn.org/tags/pl/pgsql/"/><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/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>