Fun with Self-Joins

In the course of doing a data migration yesterday, I was presented with an interesting challenge: I had a junction table creating a many-to-many relationship between people and counties. I needed to create a similar table, but with an extra column: an integer value, starting at zero, which ordered the counties for each person. E.g., for the (person, county) values { (1,1), (1,2), (2,1), (3,1) }, the resulting (person, county, position) values would need to be { (1,1,0), (1,2,1), (2,1,0), (3,1,0) } or { (1,1,1), (1,2,0), (2,1,0), (3,1,0) }. The straightforward approach, in my opinion, is procedural; select the distinct person values from the source table, then do queries for that person’s counties and just increment a variable to get the position value. Unfortunately, this would also be slow, and require more lines of SQL code, which means more possibility for error. So, I wondered if there was a non-procedural way to do it. After a few minutes of thought, I came up with the following:


SELECT j1.person, j1.county, COUNT(*)-1
  FROM junction_table j1
  INNER JOIN junction_table j2
    ON j1.person = j2.person
     AND j2.county < = j1.county   GROUP BY j1.person, j1.county;

It seems to have worked. 🙂

Remove Non-viewable Menu Items in Drupal

Out of the box, Drupal has no ability to restrict viewing of site content, beyond a blanket “this role can/cannot access site content”. Unsurprisingly, then, the menu system does not ensure that users can actually view a node that a custom menu item refers to before placing it in the menu. If you’re using an add-on access control module like Taxonomy Access Control Lite or Category Access Control Lite (included in the Category package), this will have the undesirable effect of leaving menu items visible for content the user has no access to, creating a usability and minor security problem.

This module goes through the {menu} table, finds nodes which are inaccessible to the user, and adds them to the navigation menu with the access attribute set to FALSE, preventing them from appearing. I’ll hopefully be putting this up on http://drupal.org soon, but for now, you can get it here. Not available in stores! Download today!

remove_nonviewable_items-5.x-1.0.tar.gz

Hubcaps, Streetlights, and Aliasing

I was driving back from dancing tonight and I noticed that the hubcaps on the car next to me appeared to be spinning slowly backwards. I figured this was probably aliasing due to 60Hz flicker from the streetlights. After a brief moment of confusion (no way were the guy’s tires spinning close to 60 times a second!), I realized that the hubcaps probably had some degree of rotational symmetry, and it wouldn’t be hard to figure out how much.

I know that we were both going around 50mph, maybe a little slower. I’m assuming that our wheels were about the same size; mine are 2.00 feet in diameter. That’s about a 6.28 ft circumference. 50 miles/hour = 264000 ft/hr = 73.3 ft/sec. So my wheels (and presumably the other guy’s as well) were rotating about 11.7 times/sec. If the wheels appeared to rotating slowly backward, the effective frequency must have been just a little under 60Hz, so I’m guessing that the other guy’s hubcaps had 5-fold rotational symmetry.

Who ever said math isn’t important?

Make Drupal act like a Content Management System

Before you say, “Drupal is a content management system!”, let me agree with you. It certainly does manage content, in roughly the same way that my “to do”/”to file” piles manage my paperwork. However, it lacks many features that I would consider critical for a CMS for a non-trivial website. Most fundamentally, it has no sense of hierarchy. Documents you create are just node/number. Files you upload all go in one directory (probably “files”). Any hierarchy in your navigation menus or URL aliases (which you will have to create manually!) exists only in your mind, not in Drupal. (To be fair, if you go to a document which has a menu item, it does highlight that as the “active” menu item.)

Out of the box, Drupal does come with support for categorization of documents, feed aggregation, and syndication. The default front page is a list of the most recently posted items. And, the two content types you can create are “Pages” and “Stories”. By now, this is probably starting to sound familiar: at its core, Drupal is a blogging engine…and not much more.

However, if you’re stuck using this product to create a non-blog website, it is possible to make it behave more like a fully-featured CMS through use of a few non-core modules. Specifically:

  1. Download and install these two modules.
  2. From Site Building→Modules, turn on “Category Menu”, “Category Pathauto”, and all dependencies
  3. From Site Building→Modules, turn off “Taxonomy” (Category replaces it)
  4. Under Site Configuration→Pathauto→Node Path Settings, set the Container and Category paths to “[categorypath]”
  5. If you haven’t already, under Site Configuration→Clean URLs, enable Clean URLs.

Now, create your content as type “Container”. (“Category” will also work, if you have already categorized pages that you’d like to show up as parts of the category page.) Two caveats:

  • When you’re setting the menu options for these items, do it under “Container information”, not menu settings. The latter will be overridden by the former.
  • This doesn’t solve the problem of a lack of hierarchy for uploaded files. Maybe there is a way to solve this; I haven’t really looked.

One other tip: the default input formats on a Drupal site leave something to be desired. If you want to be able to put in raw HTML, do this:

  1. Go to Site Configuration→Input Formats→Add Input Format
  2. Create a new format called Raw HTML with no filters selected
  3. Optionally, make it the default.

“Interesting” Linux Applications

In a small “introduction to Linux” class I was helping out with recently, I did a short demo of how Wireshark can show you what happens when you load a webpage (and, also, what gets broadcast on wireless networks 🙂 ). (No, it’s not a Linux-only program, but it is a mature, easy-to-use open-source application that runs on Linux and is in most software repositories.) I was asked for examples of other interesting (presumably, to broad swaths of geeks) applications, so here are a few:

I Use It And Like It

Wireshark
The continuation of Ethereal. Analyzes traffic going through your network interfaces.
Audacity
Easy-to-use audio-editing tool.
Totem (with Xine backend)
Totem is the GNOME movie player. It integrates nicely with the GNOME environment, but at least as of a year or so ago, you were better off using the version compiled using the Xine libraries because of broader media support. If you use Fedora, you may wish to add Livna to your repositories, as it includes totem-xine. It would also be worth checking out Stanton Finley’s Fedora Core 5 Release Notes for information on how to extend the number of codecs supported.
OpenOffice
Cross-platform open-source office productivity suite.
Firefox
Open-source, highly-extensible web browser. (I posted recently about a couple of my favorite extensions.)
Thunderbird
Open-source email client.

I Hear Good Things About It

Azureus
A popular and full-featured BitTorrent client. It’s Java-based, so it runs everywhere (*giggle*).
Eclipse
Eclipse seems to be the graphical open-source IDE for doing development in Java and C/C++ right now. It appears that there are also plugins for PHP, Python, and others, but I don’t know how mature they are.

It Sure Looks Cool

Ekiga
Open-source SIP/H.323 a audio- and video-conferencing program. Interoperates with programs like Microsoft’s Messenger and NetMeeting and Apple’s iChat.

Feel free to jump in with your thoughts and favorite applications.

A Remarkably Inefficient Gift-Giving Algorithm

For the past few years, I’ve created technological solutions to a problem clearly in need of the might of modern technology: choosing secret santa gift recipients for my girlfriend’s immediate family. (She’s proposed a solution involving a hat.)

In previous years, I’ve taken the easy and obvious approach: generate a random permutation, and see if anyone ends up giving themselves a gift. If they do, try again.

This approach has two flaws:

  1. It may take multiple tries to get a valid permutation. It could take three, four, or even more attempts! We could be delayed by milliseconds waiting to know the results.
  2. It’s way too efficient.

Fortunately, I found a way around both of these problems: generate all permutations that don’t fix any elements, then choose a random one. I’ve been poking around with learning Common Lisp, so I decided to write a solution in it.

I haven’t figured out exactly how inefficient this is, but I’m guessing it grows exponentially with the size of the input set. The number of permutations of the set is obviously exponential (Stirling’s approximation), and eliminating the permutations that fix an element doesn’t take out too many of the branches:

Input size Non-fixing permutations
1 0
2 1
3 2
4 9
5 44
6 265
7 1854
8 14833
9 133496

Conclusion: It’s a good thing her family isn’t too big.

Make the Web a Quiet Place In Firefox

A combination of three add-ons and a configuration tweak can go a long way toward making the Web a quiet, calm place.

Add-Ons

In the NoScript preferences page, go the Advanced tab and select Forbid Macromedia Flash and Forbid other plugins.

Animated GIFs

Unfortunately, some people still feel the need to put animated GIFs up on their web pages. Fortunately, there’s a hidden configuration option that will let you stop them from playing more than once or from playing at all. Go to about:config and find the image.animation_mode preference. Set it to once to let images animate once, or none to prevent them from animating at all. (Kudos to the mozillaZine article on animated images for documenting this.)

Java and Certificates

In setting up Wildfire at work, I discovered an unfortunate “feature” of Java: it encourages you to store certificates and private keys in Java Keystores rather than simple, easily-manipulated PEM-encoded files. This wouldn’t be terrible, since the Java Runtime Environment includes a keytool for manipulating the keystores, except for one thing: the keytool provides no way to import private keys into a keystore! I ended up having to write my own utility to do just that; I’ve posted the source on this site. Enjoy!