<?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>Bacon and Tech</title>
	<atom:link href="http://www.baconandtech.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.baconandtech.com</link>
	<description>Because everything's better with bacon</description>
	<lastBuildDate>Wed, 28 Jul 2010 23:08:07 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Contributing to the PostgreSQL Documentation</title>
		<link>http://www.baconandtech.com/2010/07/28/postgresql-html-docs-on-ubuntu/</link>
		<comments>http://www.baconandtech.com/2010/07/28/postgresql-html-docs-on-ubuntu/#comments</comments>
		<pubDate>Wed, 28 Jul 2010 22:55:09 +0000</pubDate>
		<dc:creator>gabrielle</dc:creator>
				<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://www.baconandtech.com/?p=182</guid>
		<description><![CDATA[Sign up to be a proofreader:
http://wiki.postgresql.org/wiki/Documentation_Proofreading
Or just submit fixes as you find them.
References for building the docs:
http://www.postgresql.org/docs/current/static/docguide-toolsets.html
http://www.postgresql.org/docs/current/static/docguide-build.html
To build the PostgreSQL docs on Ubuntu, I had to install the following packages* additional to my base install:
- docbook
- docbook-utils (contains the collateindex.pl script)
- jade
Build the html docs from your top-level pg source dir:
./configure [options]
make html
&#8230;make is actually [...]]]></description>
			<content:encoded><![CDATA[<p>Sign up to be a proofreader:<br />
<a href="http://wiki.postgresql.org/wiki/Documentation_Proofreading">http://wiki.postgresql.org/wiki/Documentation_Proofreading</a></p>
<p>Or just submit fixes as you find them.</p>
<p>References for building the docs:<br />
<a href="http://wiki.postgresql.org/wiki/Documentation_Proofreading">http://www.postgresql.org/docs/current/static/docguide-toolsets.html</a><br />
<a href="http://www.postgresql.org/docs/current/static/docguide-build.html">http://www.postgresql.org/docs/current/static/docguide-build.html</a></p>
<p>To build the PostgreSQL docs on Ubuntu, I had to install the following packages* additional to my base install:<br />
- docbook<br />
- docbook-utils (contains the collateindex.pl script)<br />
- jade</p>
<p>Build the html docs from your top-level pg source dir:<br />
<code>./configure [options]<br />
make html</code><br />
&#8230;make is actually gmake on ubuntu.</p>
<p>This puts the html doc files in /path/to/pg_src/doc/src/sgml/html;  view them with your favorite browser.</p>
<p>Make corrections on the sgml source files in /path/to/pg_src/doc/src/sgml;  `make html` to re-generate the html docs.</p>
<p>I work with a git repo.  Here&#8217;s how I create a patch:<br />
<code>git format-patch [id of version I want to patch]</code><br />
The id is usually the version prior to my most recent commit.</p>
<p><small>*next time:<br />
<code>apt-get build-dep postgresql-doc</code><br />
should pull down the packages needed to build the docs.  Keep in mind this is going to pull the build requirements for the packaged version, which may not be the one you want (e.g., if the build requirements changed between versions;  but this is unlikely).<br />
</small></p>
]]></content:encoded>
			<wfw:commentRss>http://www.baconandtech.com/2010/07/28/postgresql-html-docs-on-ubuntu/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>OSBridge 2010 Braindump</title>
		<link>http://www.baconandtech.com/2010/06/10/osbridge-2010-braindump/</link>
		<comments>http://www.baconandtech.com/2010/06/10/osbridge-2010-braindump/#comments</comments>
		<pubDate>Fri, 11 Jun 2010 03:11:00 +0000</pubDate>
		<dc:creator>gabrielle</dc:creator>
				<category><![CDATA[Conferences]]></category>
		<category><![CDATA[Talks We've Given]]></category>

		<guid isPermaLink="false">http://www.baconandtech.com/?p=175</guid>
		<description><![CDATA[Conference website:  http://opensourcebridge.org/  Many of the sessions have user-submitted notes;  check the &#8220;session notes&#8221; link from the session info box on the upper right side of each session&#8217;s page.
Year 2 of OSBridge was almost as good as Year 1.  I say almost, because I spent Monday (my first day off, completely [...]]]></description>
			<content:encoded><![CDATA[<p>Conference website:  <a href="http://opensourcebridge.org/" target="new">http://opensourcebridge.org/</a>  Many of the sessions have user-submitted notes;  check the &#8220;session notes&#8221; link from the session info box on the upper right side of each session&#8217;s page.</p>
<p>Year 2 of OSBridge was almost as good as Year 1.  I say almost, because I spent Monday (my first day off, completely to myself, in a loooong time) laid up with a nasty cold, and completely missed <B>Tuesday</B>, the first day of the conference.  Bummer, because I was really looking forward to another installment of Hal Pomeranz&#8217;s <a href="http://opensourcebridge.org/sessions/349" target="new">Command Line Kung Fu</a> .  I&#8217;d caught this talk up at LFNW and it was truly excellent.</p>
<p><B>Wednesday</B></p>
<p>I arrived most of the way through <a href="http://opensourcebridge.org/sessions/495" target="new">The Rise of Hackerspaces</a>  (Leigh Honeywell), just in time to hear about chalkboard paint.  How have I not known about this?  More importantly, is there <I>whiteboard</I> paint?  Oh yes, yes, <a href="http://www.rustoleum.com/CBGProduct.asp?pid=128" target="new">there is</a>.  Leigh&#8217;s book recommendation:  _Python for Software Design_:  a good intro to programming concepts that just happens to use Python to illustrate.</p>
<p>Next, I participated in the <a href="http://opensourcebridge.org/sessions/440" target="new">Organizing User Groups panel</a>.  Eric Wilhelm briefly mentioned t-shirts, but I didn&#8217;t get the opportunity to thank him in public for ordering women&#8217;s versions of the <a href="http://pdx.pm.org" target="new">pdx.pm</a> t-shirts (twice!).  Apparently there is a Drupal UG here in Portland, but they don&#8217;t advertise.  We talked about ways to publicize groups, all-ages post-meeting activities, and presentation ideas.  Sam Keen reports that having a few shorter talks instead of one long one is working well for <a href="http://pdxphp.org/" target="new">PDXPHP</a>.</p>
<p>The silliness of the compression algorithm and the overall entertainment value of Markus Roberts&#8217; talk (<a href="http://opensourcebridge.org/sessions/453" target="new">Copyright Lawyers Can Goedel</a>) both lived up to the high expectations I have for him.</p>
<p>chromatic&#8217;s <a href="http://opensourcebridge.org/sessions/399" target="new">Using Modern Perl</a> made me want to try it out.  You can<br />
<code><br />
use Modern::Perl;<br />
</code><br />
and have access to 5.10 features and (soon) 5.12 features, such as say, the &#8216;//&#8217; operator, and named captures. </p>
<p>Best idea I got from this talk:  put your module library in git, so if you upgrade something &#038; it breaks, it&#8217;s super-easy to revert back to a working copy.</p>
<p>chromatic&#8217;s book is available on github, and he wants us to read it.</p>
<p>Schwern <a href="http://opensourcebridge.org/sessions/412" target="new">How to Report a Bug</a>:  I was disappointed that we didn&#8217;t get to see Schwern&#8217;s &#8220;REPENT! For the end of the UNIX Epoch is Nigh!&#8221; (I hear it&#8217;s showing at OSCON) but I will take <a href="http://twitter.com/demew/status/15282624277" target="new">this</a> as a substitute.   The basic premise is:  it&#8217;s about empowering your users.  There are a lot of gates (or filters, use your preferred terminology) in place to keep people from filing bugs.  I ran into this a mere two days later, trying to file a bug report about pgadmin.</p>
<p>I skipped the last session so I could get dinner at the food carts &#038; get back in time for <a href="http://opensourcebridge.org/sessions/492" target="new">Move Your Asana</a>.  We did this last year, and it&#8217;s a great way to do a quick decompression mid-conference.</p>
<p>Next up was the <a href="http://opensourcebridge.org/sessions/502" target="new">PostgreSQL BoF</a>.  Most of what we talked about was 9.0 &#8211; beta2 is coming out next week.  (It actually came out June 4.)</p>
<p><B>Thursday</B></p>
<p>I had to work in the morning, and showed up for the afternoon sessions.  I dropped in on Christof Pettus&#8217;s <a href="http://opensourcebridge.org/sessions/358" target="new">Introduction to PostgreSQL</a>, because I&#8217;m planning to give a similar talk at LFNW next year.  I have a pretty good idea what I want to cover, but figured I should make sure there wasn&#8217;t anything big I was missing.  45 minutes is only long enough for the briefest overview, but Christof covered it well, including some gotchas.</p>
<p>Next up, Jacinta Richardson&#8217;s <a href="http://opensourcebridge.org/sessions/384" target="new">Teach Your Class to Fish</a>.  This was geared more toward people giving multi-day intensive training sessions, but there&#8217;s good material that applies even to shorter one-day sessions.  Like, <i>be organized</I>.  I learned some new terms (eg &#8220;cognitive load&#8221;).  Jacinta also stressed that it&#8217;s really important for students to take breaks &#8211; the kind where they actually leave the classroom &#038; walk around.  People who fall behind &#038; try to catch up during lunch tend to fall even further behind.  Put the most essential topics at the start of the day, because that&#8217;s when people are paying the most attention;  save the easy topics for the end.</p>
<p>In <a href="http://opensourcebridge.org/sessions/378" target="new">You Shall Not Pass</a>, Amye Scavarda and Chris Strahl talked about managing client expectations.  I&#8217;m not a freelancer, but any lesson in boundary-setting is applicable to most work situations IMO.  &#8220;If it&#8217;s not documented, it doesn&#8217;t exist&#8221; is a good rule of thumb to follow.</p>
<p>Paul &#8220;not a stalker; just a very nice man, who knows an awful lot about you&#8221; Fenwick taught us <a href="http://opensourcebridge.org/sessions/425" target="new">Practical Facebook Stalking</a>.  See the session notes &#038; Paul&#8217;s blog for tips on tightening up your FB settings.</p>
<p>The <a href="http://opensourcebridge.org/sessions/506" target="new">Code-n-Splode BoF</a> that night was basically a meet &#038; greet and discussion of some things from the conference.</p>
<p><B>Friday</B></p>
<p>Voodoo donut truck!  Woohoo!  I ate too many donuts.  </p>
<p>Went to Lance&#8217;s ShowOff presentation.  I may try it&#8230;Mark Wong keep making me use Beamer for our presentations, which I guess is cool, but the layout gives me fits sometimes.  I really like ShowOff&#8217;s syntax highlighting.</p>
<p>During the next session &#038; into lunch (before I ran down to my favorite cart, the <a href="http://www.thewholebowl.com/" target="new">Whole Bowl</a>), I worked on Maryanne&#8217;s Postgres install &#8211; got her logged in, and got her up to speed with the basic SQL to create &#038; fill tables.</p>
<p>I&#8217;d intended to go home, but a couple of the after lunch sessions were just too juicy:  Selena &#038; Bart&#8217;s Advanced Trolling, followed by Audrey&#8217;s NSFW.  You really Had to Be There &#8482; to fully experience these.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.baconandtech.com/2010/06/10/osbridge-2010-braindump/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>das keyboard</title>
		<link>http://www.baconandtech.com/2010/06/09/das-keyboard/</link>
		<comments>http://www.baconandtech.com/2010/06/09/das-keyboard/#comments</comments>
		<pubDate>Thu, 10 Jun 2010 05:15:34 +0000</pubDate>
		<dc:creator>gabrielle</dc:creator>
				<category><![CDATA[Hardware]]></category>

		<guid isPermaLink="false">http://www.baconandtech.com/?p=171</guid>
		<description><![CDATA[My beloved and yet much-abused Model M keyboard has been on its last legs (or springs) for a while now.  I really need that esc key, and the left bracket, and the space bar, and the letter &#8220;m&#8221;, and so on&#8230;knowing my love for the clickety-clack, a friend recommended I replace it with one [...]]]></description>
			<content:encoded><![CDATA[<p>My beloved and yet much-abused Model M keyboard has been on its last legs (or springs) for a while now.  I really need that esc key, and the left bracket, and the space bar, and the letter &#8220;m&#8221;, and so on&#8230;knowing my love for the clickety-clack, a friend recommended I replace it with one of <a href="http://www.daskeyboard.com/model-s-ultimate/">these</a>.  </p>
<p>It is indeed very clicky, but it&#8217;s more of a light ticking sound than a deep thud like the M.  You&#8217;ll wake up somebody in the next room, but not the neighbors.  Unlike the M, it will not double as a personal defense device.  But whooo boy, can I type fast, fast, fast on this thing.  Sorta like driving a sports car for the first time, when the rear end cuts loose going around the corners.</p>
<p>Bonus:  no markings on the keys means other people are afraid to use your computer.</p>
<p>Bottom line:  I would definitely purchase one of these again.  (But I sure hope it lasts over a decade like my M.)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.baconandtech.com/2010/06/09/das-keyboard/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using rrdgraph&#8217;s &#8211;right-axis options</title>
		<link>http://www.baconandtech.com/2010/06/08/using-rrdgraphs-right-axis-options/</link>
		<comments>http://www.baconandtech.com/2010/06/08/using-rrdgraphs-right-axis-options/#comments</comments>
		<pubDate>Wed, 09 Jun 2010 02:47:24 +0000</pubDate>
		<dc:creator>gabrielle</dc:creator>
				<category><![CDATA[Network Management]]></category>
		<category><![CDATA[nms]]></category>
		<category><![CDATA[rrdtool]]></category>

		<guid isPermaLink="false">http://www.baconandtech.com/?p=119</guid>
		<description><![CDATA[So, say I have an interface that's dropping packets.  Not too many, but the ideal number is zero, so I'd like to see them in the graphs in our NMS (which is based on <a href="http://oss.oetiker.ch/rrdtool/" target="new">rrdtool</a>  as all decent NMSes are).  I can read the average rate of dropped packets in the graph key at the bottom,  and there are tiny little blips in the graph, but I don't have a strong visual cue that something is off.]]></description>
			<content:encoded><![CDATA[<p>(Note:  This is a very simplified (but real-life!) example.  Usually we&#8217;ll include the &#8220;in&#8221; data on the same graph, and Errors and QueueDrops etc, but that clutters up the example.)</p>
<p>So, say we have an interface that&#8217;s dropping packets.  Not too many, but the ideal number is zero, so we&#8217;d like to see them in the graphs in our NMS (which is based on <a href="http://oss.oetiker.ch/rrdtool/" target="new">rrdtool</a>  as all decent NMSes are).  We use rrdgraph to show packets out in black and packets that should have gone out, but were discarded instead in purple:</p>
<p><code>rrdtool graph images/router-errors-unscaled.png \<br />
    --title "unscaled" \<br />
    --vertical-label 'Pkts/Second' \<br />
    --start end-2day \<br />
    --end -1hr \<br />
    --width 800 \<br />
    --height 250 \<br />
    --imgformat PNG \<br />
    --interlace \<br />
    DEF:ifOutUcastPkts=router.rrd:ifOutUcastPkts:AVERAGE \<br />
    DEF:ifOutNUcastPkts=router.rrd:ifOutNUcastPkts:AVERAGE \<br />
    DEF:ifOutDiscards=router.rrd:ifOutDiscards:AVERAGE \<br />
    CDEF:ifOutPkts=ifOutUcastPkts,ifOutNUcastPkts,+ \<br />
    LINE1:ifOutPkts#003300:ifOutPkts/sec \<br />
    LINE1:ifOutDiscards#990099:ifOutDiscards/sec\\n \<br />
    GPRINT:ifOutPkts:AVERAGE:"Avg ifOutPkts %1.2lf\\n" \<br />
    GPRINT:ifOutDiscards:MAX:"Max ifOutDiscards %1.2lf"</code></p>
<p>That produces a graph like this:</p>
<p><a href="http://www.baconandtech.com/wp-content/uploads/2010/06/router-errors-unscaled.png"><img src="http://www.baconandtech.com/wp-content/uploads/2010/06/router-errors-unscaled-150x150.png" alt="unscaled example graph" title="router-errors-unscaled" width="150" height="150" class="alignnone size-thumbnail wp-image-120" /></a></p>
<p>(Click on the thumbnails to get the full graphs.)</p>
<p>We can read the average rate of discarded packets in the graph key at the bottom,  and there are tiny little blips in the purple line that represents discards , but we don&#8217;t have a strong visual cue that something is off.</p>
<p>One possible solution is to scale up the discard values relative to the total packets.  A factor of 100 ought to do it.  Then we&#8217;ll use the <a href="http://oss.oetiker.ch/rrdtool/doc/rrdgraph.en.html" target="new">&#8211;right-axis options to rrdgraph</a> to label the right-hand y-axis accordingly.</p>
<p>We add this CDEF to provide the scaling (the LINE1 etc commands will need to be altered accordingly;  you&#8217;ll see those in the final snippet):</p>
<p><code>CDEF:scaled_ifOutDiscards=ifOutDiscards,100,*</code></p>
<p>That gives us a graph that looks like this:</p>
<p><a href="http://www.baconandtech.com/wp-content/uploads/2010/06/router-errors-scaled.png"><img src="http://www.baconandtech.com/wp-content/uploads/2010/06/router-errors-scaled-150x150.png" alt="scaled example graph" title="router-errors-scaled" width="150" height="150" class="alignnone size-thumbnail wp-image-121" /></a></p>
<p>Note that it now looks like we&#8217;re dropping up to 70 packets/second &#8211; we still have to read the stats in the key at the bottom of the graph.  So let&#8217;s get the secondary y-axis correctly labeled &#038; scaled, with the following commands:</p>
<p><code>--right-axis-label 'Discards/Second'<br />
--right-axis 0.01:0</code></p>
<p>&#8211;right-axis-label prints the specified text along the right-hand axis.<br />
&#8211;right-axis [scale:shift] scales and/or shifts the tickmarks on the right axis <em>relative to the left axis</em>.  In this case, the new values we&#8217;re displaying are 100X the original values, so we need to scale our axis accordingly:  0.01.  More simply:  left/right = 1/100.  We don&#8217;t need to start at a value other than 0, so we set the shift value to 0.</p>
<p><a href="http://www.baconandtech.com/wp-content/uploads/2010/06/router-right-axis.png"><img src="http://www.baconandtech.com/wp-content/uploads/2010/06/router-right-axis-150x150.png" alt="example graph with second y-axis" title="router-right-axis" width="150" height="150" class="alignnone size-thumbnail wp-image-122" /></a></p>
<p>Hmmm&#8230;rrdtool has automatically converted our values to milli-units.  (Note the lower-case m in the labels.)  Let&#8217;s fix that with the &#8211;right-axis-format command:</p>
<p><code>--right-axis-format %1.1lf</code></p>
<p><a href="http://www.baconandtech.com/wp-content/uploads/2010/06/router-right-axis-format.png"><img src="http://www.baconandtech.com/wp-content/uploads/2010/06/router-right-axis-format-150x150.png" alt="example graph with second y-axis, formatted" title="router-right-axis-format" width="150" height="150" class="alignnone size-thumbnail wp-image-123" /></a></p>
<p>And that&#8217;s all there is to it!</p>
<p>The final rrdgraph command looks like this:<br />
<code>rrdtool graph images/router-right-axis-format.png \<br />
    --title "right-axis-format" \<br />
    --vertical-label 'Pkts/Second' \<br />
    --right-axis-label 'Discards/Second' \<br />
    --right-axis 0.01:0 \<br />
    --right-axis-format %1.1lf \<br />
    --start end-2day \<br />
    --end -1hr \<br />
    --width 800 \<br />
    --height 250 \<br />
    --imgformat PNG \<br />
    --interlace \<br />
    DEF:ifOutUcastPkts=router.rrd:ifOutUcastPkts:AVERAGE \<br />
    DEF:ifOutNUcastPkts=router.rrd:ifOutNUcastPkts:AVERAGE \<br />
    DEF:ifOutDiscards=router.rrd:ifOutDiscards:AVERAGE \<br />
    CDEF:scaled_ifOutDiscards=ifOutDiscards,100,* \<br />
    CDEF:ifOutPkts=ifOutUcastPkts,ifOutNUcastPkts,+ \<br />
    LINE1:ifOutPkts#003300:ifOutPkts/sec \<br />
    LINE1:scaled_ifOutDiscards#990099:ifOutDiscards/sec\\n \<br />
    GPRINT:ifOutPkts:AVERAGE:"Avg ifOutPkts %1.2lf\\n" \<br />
    GPRINT:ifOutDiscards:MAX:"Max ifOutDiscards %1.2lf"</code></p>
]]></content:encoded>
			<wfw:commentRss>http://www.baconandtech.com/2010/06/08/using-rrdgraphs-right-axis-options/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Array Sorting</title>
		<link>http://www.baconandtech.com/2010/01/12/array-sorting/</link>
		<comments>http://www.baconandtech.com/2010/01/12/array-sorting/#comments</comments>
		<pubDate>Tue, 12 Jan 2010 07:03:13 +0000</pubDate>
		<dc:creator>gabrielle</dc:creator>
				<category><![CDATA[PostgreSQL]]></category>

		<guid isPermaLink="false">http://www.baconandtech.com/?p=107</guid>
		<description><![CDATA[I have this little sorting problem that had been bothering me for a month, but as it&#8217;s only a minor annoyance, I hadn&#8217;t spared the cycles to work on it.  Last Friday I decided I needed an instant gratification project, and set about solving it.
I have a table that contains hostnames, cards, and the [...]]]></description>
			<content:encoded><![CDATA[<p>I have this little sorting problem that had been bothering me for a month, but as it&#8217;s only a minor annoyance, I hadn&#8217;t spared the cycles to work on it.  Last Friday I decided I needed an instant gratification project, and set about solving it.</p>
<p>I have a table that contains hostnames, cards, and the slots on the host chassis those cards are installed in.  All datatypes are varchars.  The sorting problem arises because I have some cards that are actually installed on other cards;  those are referenced by a slot/subslot designation.</p>
<p>Here&#8217;s some sample data:</p>
<pre>testytest=# SELECT * FROM cards ORDER BY card_slot;
hostname | card_slot |   card_model
----------+-----------+----------------
zucchini | 0         | card
zucchini | 0/0       | daughter card
zucchini | 0/1       | daughter card
zucchini | 1         | card
zucchini | 1/0       | daughter card
zucchini | 1/1       | daughter card
zucchini | 1/15      | daughter card
zucchini | 1/2       | daughter card
zucchini | 17        | something else
zucchini | 18        | something else
zucchini | 2         | another card
zucchini | 3         | another card
zucchini | 4         | another card
(13 rows)</pre>
<p>I&#8217;d like to see 1/15 come after 1/2, and 17 &amp; 18 come after 2, 3, &amp; 4.  (Like I said, it&#8217;s a minor annoyance.  But still an annoyance.)  I need to be able to sort both pieces in numerical order.  I went through some weird gymnastics writing functions to split out &amp; return each piece, but each of my solutions introduced other problems.  (These instant gratification projects so rarely are, eh.)</p>
<p>Before I wrapped things up for the day, I read the PostgreSQL docs about <a href="http://www.postgresql.org/docs/8.3/static/functions-array.html">array functions &amp; operators</a>.  That percolated around in my brain and a solution came to me while I was out hiking over the weekend:</p>
<p>First, I reCAST string_to_array &amp; made it return a set of integers:<br />
<code>CREATE OR REPLACE function foo(varchar(15)) RETURNS integer[]<br />
AS $$<br />
SELECT CAST(string_to_array($1, '/') AS integer[])<br />
$$<br />
LANGUAGE SQL;</code></p>
<p>Since Pg includes &lt; and &gt; array functions, I expected to be able to sort by the array my function returned:</p>
<pre>testytest=# SELECT hostname, card_slot, card_model, foo(card_slot) AS sort_value
FROM cards
ORDER BY sort_value;
hostname | card_slot |   card_model   | sort_value
----------+-----------+----------------+------------
zucchini | 0         | card           | {0}
zucchini | 0/0       | daughter card  | {0,0}
zucchini | 0/1       | daughter card  | {0,1}
zucchini | 1         | card           | {1}
zucchini | 1/0       | daughter card  | {1,0}
zucchini | 1/1       | daughter card  | {1,1}
zucchini | 1/2       | daughter card  | {1,2}
zucchini | 1/15      | daughter card  | {1,15}
zucchini | 2         | another card   | {2}
zucchini | 3         | another card   | {3}
zucchini | 4         | another card   | {4}
zucchini | 17        | something else | {17}
zucchini | 18        | something else | {18}
(13 rows)</pre>
<p>Voila.  Works as expected on my small (~2000 rows) data set.  It also fails as expected when passed bad data (eg something with a text string).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.baconandtech.com/2010/01/12/array-sorting/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Refactoring!</title>
		<link>http://www.baconandtech.com/2009/11/06/refactoring/</link>
		<comments>http://www.baconandtech.com/2009/11/06/refactoring/#comments</comments>
		<pubDate>Sat, 07 Nov 2009 01:35:51 +0000</pubDate>
		<dc:creator>gabrielle</dc:creator>
				<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[databases]]></category>
		<category><![CDATA[hackathon]]></category>

		<guid isPermaLink="false">http://www.baconandtech.com/?p=92</guid>
		<description><![CDATA[Last night at the hackathon,  we refactored one of our queries from my review of Refactoring SQL Applications.*
First, we had a duplicate field name in the original select.  Not a problem if you&#8217;re just doing a select, but if you want to create a table (temp or otherwise) from the data, it won&#8217;t work.  So [...]]]></description>
			<content:encoded><![CDATA[<p>Last night at the <a href="http://calagator.org/events/1250457973" target="_blank">hackathon</a>,  we refactored one of our queries from my review of <a href="http://www.baconandtech.com/2009/06/06/book-review-part-i-refactoring-sql-applications-with-bonus-queries/" target="_blank">Refactoring SQL Applications</a>.*</p>
<p>First, we had a duplicate field name in the original select.  Not a problem if you&#8217;re just doing a select, but if you want to create a table (temp or otherwise) from the data, it won&#8217;t work.  So we replaced the first num_rows with rows_in_bytes.</p>
<p>Also, reading over this 5 months after the original attemp, I realize it&#8217;s a lot clearer if we don&#8217;t use table aliases in the outer SELECTs.</p>
<p>Then, we got some advice from Greg Smith that we shouldn&#8217;t do joins on pg_class.relname &#8211; this can screw you up if you have different schemas with identical table names.  You want to use oids (which I&#8217;d always thought was not desirable, but I&#8217;m assured it&#8217;s ok if you&#8217;re doing it with the system tables &#8211; you don&#8217;t want your application to depend on them, though. <img src='http://www.baconandtech.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  )  So, instead, we match pg_namespace.oid with pg_class.relnamespace.</p>
<p>Selena&#8217;s illustration of how this works:<br />
<code>SELECT relname, relkind FROM pg_class<br />
JOIN pg_namespace ON pg_namespace.oid = pg_class.relnamespace WHERE relkind = 'r' AND pg_namespace.nspname = 'public';</code></p>
<p>The new &amp; improved version of the query can be found on the <a href="http://wiki.postgresql.org/wiki/Index_Maintenance" target="_blank">Pg wiki</a>.</p>
<p>I wanted to compare the new query against the old, so I created a couple of temp tables containing the results&#8230; and discovered we had a couple of data discrepancies:  a few of our tables were listed twice in the original query results, with different values for num_rows, only one of which was correct for the current schema:</p>
<p><code>portal=# SELECT tablename, rows_in_bytes, num_rows FROM index_experiment_1<br />
WHERE tablename IN  ('detectorid_count','stations','test_agg')<br />
ORDER BY 1;<br />
tablename     | rows_in_bytes | num_rows<br />
------------------+---------------+----------<br />
detectorid_count | 0 bytes       |        0<br />
detectorid_count | 631 bytes     |      631<br />
stations         | 22 bytes      |       22<br />
stations         | 350 bytes     |      350<br />
test_agg         | 0 bytes       |        0<br />
test_agg         | 1386 bytes    |     1386<br />
(6 rows)</code></p>
<p>portal=# SELECT count(*) from detectorid_count;<br />
count<br />
&#8212;&#8212;-<br />
0<br />
(1 row)</p>
<p>portal=# SELECT count(*) from stations;<br />
count<br />
&#8212;&#8212;-<br />
350<br />
(1 row)</p>
<p>portal=# SELECT count(*) from test_agg ;<br />
count<br />
&#8212;&#8212;-<br />
0<br />
(1 row)</p>
<p>It turns out we&#8217;d run into the exact problem that Greg had warned us about.  The additional rows were from identically-named tables in other namespaces.</p>
<p>Find your namespaces:<br />
<code>portal=# SELECT nspname from pg_namespace order by 1;<br />
nspname<br />
--------------------<br />
information_schema<br />
pg_catalog<br />
pg_temp_1<br />
pg_temp_2<br />
pg_toast<br />
pg_toast_temp_1<br />
pg_toast_temp_2<br />
public<br />
selena<br />
wendell<br />
(10 rows)</code></p>
<p>Find your data:<br />
<code>portal=# SELECT count(*) from selena.detectorid_count ;<br />
count<br />
-------<br />
631<br />
(1 row)</code></p>
<p>portal=# SELECT count(*) from wendell.stations ;<br />
count<br />
&#8212;&#8212;-<br />
22<br />
(1 row)</p>
<p>portal=# SELECT count(*) from selena.test_agg ;<br />
count<br />
&#8212;&#8212;-<br />
1386<br />
(1 row)</p>
<p>Note that these match the additional data from our original query.</p>
<p>Thanks, Greg!</p>
<p>&#8211;<br />
<small>* No, I haven&#8217;t finished reading it yet&#8230;I don&#8217;t read during the summer, I ride my bike.</small></p>
]]></content:encoded>
			<wfw:commentRss>http://www.baconandtech.com/2009/11/06/refactoring/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PgWest:  Sunday</title>
		<link>http://www.baconandtech.com/2009/10/19/pgwest-sunday/</link>
		<comments>http://www.baconandtech.com/2009/10/19/pgwest-sunday/#comments</comments>
		<pubDate>Mon, 19 Oct 2009 22:46:20 +0000</pubDate>
		<dc:creator>gabrielle</dc:creator>
				<category><![CDATA[Conferences]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[community]]></category>
		<category><![CDATA[conference]]></category>

		<guid isPermaLink="false">http://www.baconandtech.com/?p=88</guid>
		<description><![CDATA[We arrived at the conference site to find that the XML Data Warehousing had been canceled, so I spent that session in the Hackers&#8217; Lounge attempting to continue work on pg_proctab, while getting kicked off the commie college wireless.
In Lists and Recursions and Trees, Oh My!, David Fetter gave us some example of old kludges [...]]]></description>
			<content:encoded><![CDATA[<p>We arrived at the conference site to find that the XML Data Warehousing had been canceled, so I spent that session in the Hackers&#8217; Lounge attempting to continue work on pg_proctab, while getting kicked off the commie college wireless.</p>
<p>In Lists and Recursions and Trees, Oh My!, David Fetter gave us some example of old kludges to get row numbers out of Pg &#8211; &#8220;Not only is it slow, but it&#8217;s wrong&#8221; &#8211; but you may not notice that subtle wrongness in huge data sets.  This really illustrated the value of testing your data.</p>
<p>After lunch, I went to Josh Berkus&#8217;s 5 steps to PostgreSQL Performance Tuning.</p>
<p>He gave us some rules of thumb for figuring out how much RAM &amp; CPU you need, but also recommends hiring a hardware geek to design your system for you &#8211; because vendors lie. <img src='http://www.baconandtech.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />   Try hardware out before you purchase it, or definitely test them within the warranty period.  And, here&#8217;s another use case for pg_proctab (other than my own amusement):  capacity planning.</p>
<p>Tip:  Don&#8217;t use autovacuum for data warehousing applications, or where you have large number of writes happening at once.  Manually vacuum those.</p>
<p>(An additional tip from me:  if you&#8217;re using linux, try increasing the default readahead buffer from 1024K to at least 1M for an ~80% performance improvement.  See our [in]famous file systems talk for the graphs to back this up.)</p>
<p>&#8211;</p>
<p>Thanks for another wonderful conference experience, PgPeeps!  See you again soon!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.baconandtech.com/2009/10/19/pgwest-sunday/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PGWest:  Saturday</title>
		<link>http://www.baconandtech.com/2009/10/19/pgwest-saturday/</link>
		<comments>http://www.baconandtech.com/2009/10/19/pgwest-saturday/#comments</comments>
		<pubDate>Mon, 19 Oct 2009 22:35:23 +0000</pubDate>
		<dc:creator>gabrielle</dc:creator>
				<category><![CDATA[Conferences]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[community]]></category>
		<category><![CDATA[conference]]></category>
		<category><![CDATA[databases]]></category>

		<guid isPermaLink="false">http://www.baconandtech.com/?p=85</guid>
		<description><![CDATA[This past weekend was the 3rd annual PgWest.  The conference moved up to Seattle this year, and I think it was the biggest it&#8217;s ever been.  As usual, there were more interesting talks scheduled than I had time to attend.  (This is the 21st century;  where&#8217;s my time machine?)
For my first tech conferences a few [...]]]></description>
			<content:encoded><![CDATA[<p>This past weekend was the 3rd annual <a href="http://www.postgresqlconference.org/2009/west">PgWest</a>.  The conference moved up to Seattle this year, and I think it was the biggest it&#8217;s ever been.  As usual, there were more interesting talks scheduled than I had time to attend.  (This is the 21st century;  where&#8217;s my time machine?)</p>
<p>For my first tech conferences a few years ago, I only went to sessions that were meaningful for my job.  I&#8217;ve since had a much better time (and learned more) by choosing which sessions I&#8217;ll attend based on the following criteria, in this order:<br />
1) topic interestingness<br />
2) speaker interestingess<br />
3) relevance to my job duties</p>
<p>(See Tips #1 and #2 in Skud&#8217;s recent <a href="http://infotrope.net/blog/2009/10/15/ten-tips-for-tech-conference-attendees/" target="_blank">Ten tips for tech conference attendees</a> post.)</p>
<p>So, right out of the gate at PgWest, I&#8217;m in a python talk* &#8211; Adrian K&#8217;s (of LinuxFestNW fame) discussion on <a href="http://dabodev.com/" target="_blank">Dabo</a>.  Dabo&#8217;s a python desktop framework;  I program primarily in Perl, and I&#8217;ve never touched a desktop app.  Adrian&#8217;s example project was a management system for a plant nursery, which I *do* understand, so I had a point of reference into the material (the methods &amp; options used to track plants made sense to me).  I really wanted to talk to him more about this app, but never caught up with him.  (The hallway track felt kind of rushed for me this time.)  I got a good idea for form validation &#8211; if user tries to enter a blank value where one is not allowed, they get a pop-up immediately and the original text (if there was any) is put back in the field, forcing the user to accept the original input or enter something new before they can proceed to the next field.  This is a step up from giving the user the error message after they&#8217;ve submitted the form.</p>
<p>Next we were on to JD&#8217;s keynote, featuring the usual heckling of and by the podium.</p>
<p>Then Mark&#8217;s &amp; my talk about pg_proctab, which ended with some live demos &amp; some audience participation, the way I like it.</p>
<p>A bunch of us went to lunch at Honeyhole Sandwiches, where I tried the &#8220;Texas Tease&#8221; &#8211; BBQ chicken.  The sandwich was excellent.  I *highly* recommend the fries.</p>
<p>Scott Bailey&#8217;s Temporal Data talk was *packed*.  He talked about the &#8220;period&#8221; datatype, featured in both his own (Chronos) and Jeff Davis&#8217;s PgTemporal project.  You can do unions &amp; intersects on time periods.  I am thinking this would be a useful datatype for searching large tables of log entries.</p>
<p>Based on Scott&#8217;s talk, I decided to go to Jeff&#8217;s &#8220;Not Just UNIQUE&#8221; talk, because he would be discussing this in a little more detail.  This meant I missed the session on backup &amp; recovery.  (See comment above about more material than I can fit in my schedule.)</p>
<p>I spent the last session partly in the hackers&#8217; lounge, working on some pg_proctab wrapper scripts with Mark.</p>
<p>Then it was off to the EDB-sponsored after-party, where I caught up with Lloyd Albin, who <a href="http://pugs.postgresql.org/node/460" target="_blank">spoke at PDXPUG about a year ago</a>.  He brought me up-to-date on the work he&#8217;s done on the project, including a twitter feed to let clients know of updates, which I think is really cool.</p>
<p>&#8211;</p>
<p><small>*Which I was late to, because we were installing the snacks in the Hackers&#8217; Lounge (thanks, Mark!)</small></p>
]]></content:encoded>
			<wfw:commentRss>http://www.baconandtech.com/2009/10/19/pgwest-saturday/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PDX.pm meeting notes</title>
		<link>http://www.baconandtech.com/2009/10/15/pdx-pm-meeting-notes/</link>
		<comments>http://www.baconandtech.com/2009/10/15/pdx-pm-meeting-notes/#comments</comments>
		<pubDate>Fri, 16 Oct 2009 01:17:33 +0000</pubDate>
		<dc:creator>gabrielle</dc:creator>
				<category><![CDATA[LUGs]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[perl mongers]]></category>

		<guid isPermaLink="false">http://www.baconandtech.com/?p=82</guid>
		<description><![CDATA[Jeff (aka @duckyd) gave a presentation about CPAN Awesomeness at last night&#8217;s pdx.pm.
Slides are on github!  Your homework is to find them.    Here are some highlights.
There are over 16K modules on the CPAN as of 11 Oct 2009.  Wow.
Jeff&#8217;s recommended changes from the default cpan shell configuration:
- auto_commit 1
- prerequisites_policy follow
- build_requires_install_policy yes
- [...]]]></description>
			<content:encoded><![CDATA[<p>Jeff (aka @<a href="http://twitter.com/duckyd" target="_blank">duckyd</a>) gave a presentation about CPAN Awesomeness at last night&#8217;s <a href="http://pdx.pm.org" target="_blank">pdx.pm</a>.</p>
<p>Slides are on github!  Your homework is to find them. <img src='http://www.baconandtech.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />   Here are some highlights.</p>
<p>There are over 16K modules on the CPAN as of 11 Oct 2009.  Wow.</p>
<p>Jeff&#8217;s recommended changes from the default cpan shell configuration:<br />
- auto_commit 1<br />
- prerequisites_policy follow<br />
- build_requires_install_policy yes<br />
- prefer_installer MB (Module::Build)<br />
- change your make_install_make_command and mbuild_install_mbuild_command to include your sudo command.</p>
<p>&#8211;</p>
<p>Spend 10 minutes &amp; give something back to CPAN every time you install a module:  Simply set up CPAN::Reporter!</p>
<p>Recommendations:<br />
- make sure that you set cc_author to &#8216;no&#8217;.  (In the latest version, that&#8217;s the default.)<br />
- set it to prompt you to edit/send the report if the tests fail.  This way you can judge if the failure is due to your own<br />
boneheadedness.<br />
- you can set the transport value to a file to run reports without sending them.<br />
- for help:  perldoc CPAN::Reporter::Config</p>
<p>For automatic continuous testing, set up CPAN::Reporter::Smoker.  (Doesn&#8217;t actually install anything, justs runs tests.)</p>
<p>Recommendations:<br />
- don&#8217;t run it as root;  you are the canary in the coal mine.<br />
- create a dedicated user that has essentially no privs on your machine.<br />
- run it on a separate Perl install (core modules only).<br />
- this is a cool place to use that RAND option for prefer_installer in CPAN.</p>
<p>&#8211;</p>
<p>Another cool tip that I REALLY DIG because I have systems with multiple perls &amp; users associated with them:<br />
Set your shebang line to:</p>
<p>#!/usr/bin/env perl</p>
]]></content:encoded>
			<wfw:commentRss>http://www.baconandtech.com/2009/10/15/pdx-pm-meeting-notes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>My picks for PgWest</title>
		<link>http://www.baconandtech.com/2009/10/13/my-picks-for-pgwest/</link>
		<comments>http://www.baconandtech.com/2009/10/13/my-picks-for-pgwest/#comments</comments>
		<pubDate>Wed, 14 Oct 2009 00:24:37 +0000</pubDate>
		<dc:creator>gabrielle</dc:creator>
				<category><![CDATA[Conferences]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[conference]]></category>

		<guid isPermaLink="false">http://www.baconandtech.com/?p=79</guid>
		<description><![CDATA[(I&#8217;ll be missing Friday&#8217;s tutorials.)
Saturday:
9am:  Jeff Davis:  PostgreSQL, Extensible to the Nth Degree.  Jeff&#8217;s talks usually melt my brain, and I like that.
10:15:  Conference Keynote.
11:30am:  Mark Wong: pg_proctab.  Turns out I&#8217;m giving this talk with Mark, even though my name&#8217;s not on the schedule.  I should probably show up.
1:45pm:  Scott Bailey:  Temporal Data or Magnus [...]]]></description>
			<content:encoded><![CDATA[<p>(I&#8217;ll be missing Friday&#8217;s tutorials.)</p>
<p>Saturday:<br />
9am:  Jeff Davis:  PostgreSQL, Extensible to the Nth Degree.  Jeff&#8217;s talks usually melt my brain, and I like that.<br />
10:15:  Conference Keynote.<br />
11:30am:  Mark Wong: pg_proctab.  Turns out I&#8217;m giving this talk with Mark, even though my name&#8217;s not on the schedule.  I should probably show up.<br />
1:45pm:  Scott Bailey:  Temporal Data or Magnus Hagander:  Secure PostgreSQL Deployment.  There will be a coin toss.<br />
3:00pm:  Kevin Kempter:  Backup and Recovery.  There&#8217;s always something else to learn about this topic.<br />
4:00pm:  Bill Karwin:  Practical Full-text Search.</p>
<p>Sunday:<br />
9:00am:  Aaron Sheldon:  XML Data Warehousing.<br />
10:15am:  David Fetter:  Lists and Recursion and Trees (Oh, My!)  I want to learn about Windowing functions, new with 8.4<br />
11:15am:  Matt Smiley:  Basic Query Tuning Primer.  Another topic I could stand to learn more about.<br />
1:30pm:  Tossup between David Wheeler:  pgTAP Unit Testing Best Practices and Josh Berkus:  5 Steps to PostgreSQL Performance.  I&#8217;ll probably go to Berkus&#8217;s talk because Wheeler is a sport about repeating his talks for PDXPUG.</p>
<p>Other fun stuff:</p>
<p>The Hacker lounge will be open for two days of geekery:  7:30 am &#8211; 4:30pm Saturday, and 9-4 on Sunday.<br />
EnterpriseDB has stepped up to provide entertainment after the Saturday sessions.<br />
I haven&#8217;t heard if there are Lightning Talks, but I have a couple of ideas for one.  You should too.</p>
<p>See you there!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.baconandtech.com/2009/10/13/my-picks-for-pgwest/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
