Firefox PHP

Planet Phorum

This is a collection of the Phorum development team's personal blog posts that relate to Phorum.

Interview with WebDevRadio

Saturday, May 03, 2008

While I was at the MySQL Conference, I sat down with Michael Kimsal of WebDevRadio and recapped the two talks that I gave at the conference.  I have uploaded the slides so you can follow along if you want.

One to a Cluster - The evolution of the dealnews.com architecture.

MySQL Tips and Tricks - Some simple tips and some of the more advanced SQL we use in Phorum.

Thanks Michael.  Any time you need a guest, just let me know.

MySQL Conference Swag

Thursday, May 01, 2008

I was reading a post about The Swag Report and realized that I stayed so busy at the Phorum booth (and a little at the memcached booth) and preparing for my talks, I did not bother to go around and collect any swag from the conference.  So, if you are a vendor and want to mail me some swag that I missed, you can send it to: Brian Moon, 198 S. Hillcrest Rd., Odenville, AL  35120.  Of course, I expect nothing.  But, ya never know what product I might pimp because of a t-shirt. =)

2008 MySQL Conference, part 1

Thursday, April 17, 2008

It is always surprising what I learn when I go to a conference these days. Years ago, I could go to any talk and just suck it all in. Now, it is the little nuggets. The topics as a whole do more to confirm what I have already developed while running the Phorum project and building the infastructure for dealnews.com. That confirmation is still nice. You know you are not the only one that thought a particular solution was a good idea.

One of the confirmations I have had is that the big sites like Flickr, Wikipedia, Facebook and others don’t use exotic setups when it comes to their hardware and OS. During a keynote panel, they all commented that they did not do any virtualization on their servers. Most did not use SANs. Some ran older MySQL versions but some were running quite recent versions. I have kept thinking that I did not have the desire to get to fancy with that stuff and clearly I am not the only one.

One of the little nuggets that will likely change my world is index_merge in MySQL. I feel silly as this has been around since 5.0.3 but I was not aware of it. Basically MySQL will now use more than one key to resolve a where clause and possibly an order by depending on the query. This could lead to me removing several keys from tables in both Phorum and at dealnews.

There were others, but I am tired and trying to get OpenID into the Phorum trunk right now so I will have to think of more later.

Phorum turns 10

Thursday, April 17, 2008

So, I am at the MySQL Conference this week with my Phorum co-developers. We got to talking last night about how old Phorum is. We knew it was about 10 years. We pulled up some old archived zip file of version 1.5 and found in the this in the comment block.


* Created 04/16/1998

Whoa! That means that yesterday was the 10th birthday of the Phorum project. I would guess that is the date I originally put the code up on my personal web site for people to download. I remember sending that email to the PHP General mailing list. I told people they could have the code if they would help debug it. Later I officially made a GPL license and then a BSD style license as I became more knowledgeable about the open source and free software world.

So, for kicks we decided to install version 1.6 on the phorum.org site. Keep in mind the release date for that was March 30, 1999. The only hurdles were a default value on an auto increment column in the .sql file, needing register_globals and adding .php3 to be parsed as PHP. That got it up and running. I had hoped to post the URL for fun, but sadly, 5 lines in were sql injection vulnerabilties. Ah, the good ol’ days.

Sadly, I don’t have my emails from 1998. I lost everything in 2001 due to either a hard drive crash or some shady deal I had with someone hosting the Phorum site at the time. I can’t remember. If anyone happens to have UseNet archives or mailing list archives of the PHP General list from April 1998, please let me know. I would love to have that old stuff.

What to do in the Bay Area?

Tuesday, April 08, 2008

So, as I said before, I will be at the MySQL Conference next week.  I am renting a car this year so I don’t have to wait on cabs or deal with them at all.  So, I am mobile and being from a modern Southern US city, used to driving 30 minutes just to go to dinner.  So, where should we go?  Anything good in San Jose?  Should I go all the way to San Francisco?  I am willing to go where ever.  Help me locals, you are my only hope!

2008 MySQL Conference

Monday, March 31, 2008

In just two weeks I will be heading to the 2008 MySQL Conference.  I will be speaking this year.  My two talks are:

MySQL Hacks and Tricks to Make Phorum Fast
04/16/2008  4:25pm PDT Room: Ballroom A

From One Server to a Cluster
04/16/2008  5:15pm PDT Room: Ballroom C

I have to pull back to back talks.  *PHEW* I hope I can hold up.  To make it worse, they did not put me in the same room. If I remember right though, those are really close to each other.

Of course, the Phorum team will be in the Expo Hall in the DotOrg pavilion.  Just look for the big dog.

Big Dog

Phorum’s message tree sorting algorithm

Thursday, March 06, 2008

While figuring out what went wrong with reverse threading support in the Phorum PHP Extension, I drew up some information on how the tree sorting code does its job, to find out where my logic went wrong in the extension code. I figured that it might be useful to others, so here’s the annotated schematics. This is not the full code solution, but it explains how Phorum’s non-recursive tree sorting algorithm works.

The message tree that has to be sorted could look like this (multiple threads in a forum):

0 (virtual root node: forum)
|
+--1
|  |
|  +--5
|  |  |
|  |  +--6
|  |
|  +--8
|  .  |
|  .  +--9
|  .
|  ..(10)
|     .        \
|     ...11     |
|        |       > some broken stale data, e.g. because node
|        +--12  |  10 was removed incorrectly.
|              /
+--2
|  |
|  +--3
|
+--4
   |
   +--7

First pass: build a parent -> childs overview

First tree ordering step: build parent -> childs relations. This must work for any input array order. During this step, we also keep track of messages for which we do not encounter a parent (stale messages).

For the above tree, we get this relation table:

+--------+-------+--------+
| parent | stale | childs |
+--------+-------+--------+
| 0      |   *   | 1/2/4  |
| 1      |       | 5/8    |
| 2      |       | 3      |
| 3      |       | -      |
| 4      |       | 7      |
| 5      |       | 6      |
| 6      |       | -      |
| 7      |       | -      |
| 8      |       | 9      |
| 9      |       | -      |
| 10     |   *   | 11     |
| 11     |       | 12     |
| 12     |       | -      |
+--------+-------+--------+

Since there is no real parent 0 (that is the virtual parent id for all
thread starter messages), that one will be marked at stale too. But we
will not do any processing on that one.

The other stale items have to be taken care of, to ensure that our message tree is consistent. The handling for stale items is that they get promoted to a higher parent node. In case the starter message for the stale message’s thread exists, the message (and its childs) gets linked to that thread starter. In case the start message does not exist, the message gets linked to parent id 0 and thus effectively represents a separate thread from here on. This is wrong but, but it is the best way to prevent problems. And remember: this shouldn’t happen anyway.

After fixing the stale data, our tree would look like this (asuming that node 10 had thread id 1):

+--------+-------+--------+
| parent | stale | childs |
+--------+-------+--------+
| 0      |       | 1/2/4  |
| 1      |       | 5/8/10 | <-- 10 added to node 1
| 2      |       | 3      |
| 3      |       | -      |
| 4      |       | 7      |
| 5      |       | 6      |
| 6      |       | -      |
| 7      |       | -      |
| 8      |       | 9      |
| 9      |       | -      |
| 10     |       | 11     |
| 11     |       | 12     |
| 12     |       | -      |
+--------+-------+--------+

Second pass: generate the sorted tree

We start at parent node 0. From there we go into the child messages one by one. For each child record, we first go into that child’s children (so it’s a depth first tree walk). It is very tempting to handle this in a classic recursive call solution, however this is not good for performance.

The Phorum team hacked up a non recursive tree sort after some beers at the MySQL conference 2007. This method uses a single loop over the messages and a stack to keep track of the tree. Here’s what this looks like for our example tree (I kept the stale data out of here, but that would work the same way once it’s tied to an existing parent). I hope you can follow this somewhat hard looking schema.

Legenda: 

  * = add a new item to the tree
  > = move down to a child node
  < = move up to a parent node 

  (N):X:Y:Z = Node N, children to process are X, Y and Z. 

action  stack0     stack1     stack2     stack3    tree order
----------------------------------------------------------------------------
  *0    (0):1/2/4                                  0
  >1    (0):2/4    (1):5/8                         0
  *1    (0):2/4    (1):5/8                         0,1
  >5    (0):2/4    (1):8      (5):6                0
  *5    (0):2/4    (1):8      (5):6                0,1,5
  >6    (0):2/4    (1):8      (5)        (6)       0,1,5
  *6    (0):2/4    (1):8      (5)        (6)       0,1,5,6
  <5    (0):2/4    (1):8      (5)                  0,1,5,6
  <1    (0):2/4    (1):8                           0,1,5,6
  >8    (0):2/4    (1)        (8):9                0,1,5,6
  *8    (0):2/4    (1)        (8):9                0,1,5,6,8
  >9    (0):2/4    (1)        (8):9                0,1,5,6,8
  >9    (0):2/4    (1)        (8)        (9)       0,1,5,6,8
  *9    (0):2/4    (1)        (8)        (9)       0,1,5,6,8,9
  <8    (0):2/4    (1)        (8)                  0,1,5,6,8,9
  <1    (0):2/4    (1)                             0,1,5,6,8,9
  <0    (0):2/4                                    0,1,5,6,8,9
  >2    (0):4      (2):3                           0,1,5,6,8,9
  *2    (0):4      (2):3                           0,1,5,6,8,9,2
  >3    (0):4      (2)        (3)                  0,1,5,6,8,9,2
  *3    (0):4      (2)        (3)                  0,1,5,6,8,9,2,3
  <2    (0):4      (2)                             0,1,5,6,8,9,2,3
  <0    (0):4                                      0,1,5,6,8,9,2,3
  >4    (0)        (4):7                           0,1,5,6,8,9,2,3
  *4    (0)        (4):7                           0,1,5,6,8,9,2,3,4
  >7    (0)        (4)        (7)                  0,1,5,6,8,9,2,3,4
  *7    (0)        (4)        (7)                  0,1,5,6,8,9,2,3,4,7
  <4    (0)        (4)                             0,1,5,6,8,9,2,3,4,7
  <0    (0)                                        0,1,5,6,8,9,2,3,4,7
----------------------------------------------------------------------------

While this was an okay view for me when tracking the algorithm, this might not be very appealing to others. So I drew up an image of the path that we take while walking the tree. Click the image below for a full view:

Tree walk path

The resulting tree order corresponds to the top to bottom order for the nodes in the example tree at the start of this document. The stack depth at the points where we add an item to the tree can be used to track at what level the node in the tree is situated. This data combined, is enough to build the sorted tree.

So, what about the reverse threading?

If reverse threading is enabled, then the nodes would be added in reverse order. So for node 0, the child nodes would be processed in the order 4, 2, 1 instead of 1, 2, 4 that we showed above. The whole tree walking schema is the same for the rest of the processing.

Adding captcha to Phorum 3

Tuesday, March 04, 2008

I’m still running Phorum 3 on a few websites. I have customized it and I’m running PostgreSQL. Phorum 5 isn’t ready for me yet.

Yet the spammers don’t take any heed of that. They’re still coming strong. I’ve done several things to attempt to stop them, but nothing has taken the place of adding in captcha. In short, captcha requires that you enter a special phrase when completing the form. This is easy for people. Very difficult for computers.

In this post, I will highlight what I did to get captcha running on Phorum 3. Yesterday, there were 153 failed captchas. That’s a lot of spam I don’t have to deal with.

I warn you: this solution requires sessions to be enabled.

This solution stops the automated registrations I’ve been getting. Spammers have set up a robot that registers with the website, then posts to one of the phorume. Adding a captcha to the process causes the registration to fail, thereby stopping the spam that would have followed.

The code

It took me a while to find a simple solution. I did not want to write the code. I wanted to use an existing and easy to use solution. I found one at http://www.white-hat-web-design.co.uk/articles/php-captcha.php. I was pretty impressed with their approach.

The image file

The heart of the solution is CaptchaSecurityImages.php. This file generates the images. You also need to add monofont.ttf to your server. I’m sure there are various compile time options that you need in PHP, but I already had them, whatever they were. :)

Adding the image to the form

The following code adds the image to the registration form.

<tr>  

      <td <?php echo bgcolor($table_body_color_1); ?>><img src="CaptchaSecurityImages.php?width=100&height=40&characters=5" mce_src="CaptchaSecurityImages.php?width=100&height=40&characters=5" /><br />
      <td valign=top <?php echo bgcolor($table_body_color_1); ?> nowrap><font color="<?php echo $table_body_font_color_1; ?>">
       <label for="security_code">Security Code: </label></font><input id="security_code" name="security_code" type="text" /><br /></td>  

</tr>

The above code was added to register.php around line 270. See the call to CaptchaSecurityImages.php? That is what creates the image from which the user must obtain the passphrase. This value is supplied via the input field labelled security_code.

Where’s the answer?

You’ve seen how the image is added to the form. When the user posts the form how does the computer know what the answer is? Simple answer: session data. The call to the CaptchaSecurityImages.php code not only creates a random number and produces an image for the form, it also stores that random number in a SESSION variable on the webserver. Explaining sessions variables is beyond the scope of this article. Read up on it. Imagine it like a special cookie that uniquely identifies every user on the website.

To enable sessions for register.php, I added this entry around line 1:

session_start();

Processing the answer

The hardest part was finding a way to process the incoming answer. Here is the code I added around line 82:

if (IsSet($_POST['process'])) {
  if ($_SESSION['security_code'] == $_POST['security_code'] && !empty($_SESSION['security_code'] ) ) {
     // Insert you code for processing the form here, e.g emailing the submission, entering it into a database.
     unset($_SESSION['security_code']);
  } else {
     syslog(LOG_ERR, "captcha failure: user='$user' IP='" . $_SERVER['REMOTE_ADDR'] . "' email='$email'");
     die('wrong security code.  press back');
  }
}

Here, the code checks to verify that we are doing a post. It then compares the security code provided by the user against the code stored in the session variable. If it matches, it unsets the session variable and normal processing of the form resumes.

If the incorrect security code is supplied, syslog is invoked, and the user id, IP address, and email address are logged. The code then dies, and all processing finishes.

A log entry looks like this:

Mar  4 22:49:30 nyi httpd: captcha failure: user='Medoneax' IP='88.191.41.118' email='obw@compassunion.cn'

Creating reports is easy. How many failed captcha entries for Mar 3?

$ grep "Mar  3" /var/log/messages.0 | grep -c capt
62

That’s just on one server. :)

What about posting?

At present, this solution merely stops the spammers from registering with an automated process. They could register manually, then spam. But that is not cost effective. Should they try that approach, it would not take long to add captcha to the posting code as well.

Enjoy.

Forums are the red headed step child of a web site

Wednesday, February 20, 2008

I have seen it time and time again. And yet, every time, it irritates me to no end. You are on a professional web site. You are navigating around and at some point you hit the link for their forums. And just like that you feel transported to another place. The whole site design just changes. Colors, layout, navigation… everything. Here are some examples, including the new C7Y site from php|Architect which inspired this post. (I really do love you guys on the podcast I promise =)

  • php|architect’s C7Y - main site - forums
  • Zend’s Developer Zone - main site - forums
    Zend’s forums do at least use the Zend.com header, but you can’t get to the forums from the main Zend.com site. You have to go to the Developer Zone.
  • TextPad (great windows editor) - main site - forums
    The header is kind of the same. Fonts and link colors change slightly though which is worse in some ways than a wholesale change. It looks like they just wedged in their HTML into the phpBB template.

I could continue to list some here, but you get the idea.   So, what is the problem?  Does most message board software make it too hard to edit their templates?  Are forums an after thought and some underling is given the task to make them work and not allowed access to the main site’s templates?

Some people do better at it.  MySQL for example.  Their’s is still not perfect.  And ad awkwardly appears in the forums in a way that makes it look like an error.  However, thanks to Phorum (cha-ching), MySQL was able to make their own log in system work with their forums.  Heck, even at dealnews I have not done that.  Mostly because our forum logins predate our site accounts for email alerts and newsletters.  I am not asking for perfection though.  I would just like to feel like the company/entitiy gave some love to making their forums part of their site and not an afterthought.

So, I call for all web sites to start treating their forums like real pages.  Give them the same love and attention you give that front page or any other page.  And, if your message board software makes that hard, give Phorum a try.

Speaking at MySQL Conference 2008

Wednesday, February 20, 2008

I had mentioned a while back that I submitted three proposals for the 2008 MySQL Conference.  Well, two were accepted.

From one server to a cluster

In the last 10 years, dealnews.com has grown from a single shared hosting account to an entire rack of equipment. Luckily, we started using PHP and MySQL very early in the company’s history.

From the early days of growing a forum to surviving Slashdotting, Digging and even a Yahoo! front page mention, we have had to adapt both our hardware and software many times to keep up with the growth.

I will discuss the traps, bottlenecks, and even some big wins we have encountered along the way using PHP and MySQL. From the small scale to using replication and even some MySQL Cluster.  We have done many interesting things to give our readers (and our content team) a good experience when using our web site.

MySQL hacks and tricks to make Phorum fast

Phorum is the message board software used by MySQL. One reason they chose Phorum was because of its speed. We have to use some tricks and fancy SQL to make this happen. Things we will talk about in this session include:

  • Using temporary tables for good uses.
  • Why PHP and MySQL can be a bad mix with large data sets.
  • What mysqlnd will bring to the table with the future of PHP and MYSQL.
  • How Phorum uses full text indexing and some fancy SQL to make our search engine fast.
  • Forcing MySQL to use indexes to ensure proper query performance.

You can find my conference page here.  (as Terry would say, me, me, me!)

GoDaddy support is awful

Thursday, February 07, 2008

Luckily, I don’t have personal experience with them.  But, based on the 2 to 3 users per week that come to the Phorum support forums and IRC, they have the worst support of any host on the internet.

Example 1

A user comes to the forums having trouble with his Phorum install.  In the user’s words, GoDaddy tells him “they couldnt help me costumize my scripts because it wasnt their job”.  In this case “customize” meant filling in the MySQL permissions into the Phorum config files.  In the end, GoDaddy had to move him to a Linux hosting account.  They claimed that the Windows hosting accounts do not support PHP.  However, they are clearly wrong about their own hosting as this all started because the user received a PHP error about not connecting to MySQL.

Example 2

This user found that GoDaddy is using MySQL 4 on their servers.  Their web site does not mention a version anywhere.  So, users are locked in to a hosting plan before knowing this.

Example 3

This happened today in IRC.  It was much like the first example.  In this case, GoDaddy support told him “permissions are set via ftp”.  Um, MySQL permissions are set via FTP?  The user had a MySQL server name.  For some reason it did not exist.  So, either he typed it wrong or they gave him the wrong server name.  Either way, their support should recognize this and be able to help their clients.

Example 4

This is less a support issue and just plain crappy of them IMO.  GoDaddy does not allow the creation of temporary tables.  The Phorum search engine makes use of them to save lots of CPU and memory on the PHP side.  Luckily for their users, Thomas felt sorry enough for them to make a module that used good old fashioned slow LIKE queries.  So, that will work until their account is shut off because they have search queries clogging up the database servers.

So, if you are on GoDaddy, I feel for you.  From where we sit, it really seems like they do not provide very good support.  We end up having to support their users for things that should be able to answer.

How NOT to get support and how to turn the other cheek.

Monday, February 04, 2008

So, I checked my email this morning and found this jewel:

I might use Phorum if you brain deads knew how to upload or download your files via FTP. Your documentation has no order to it, its all a mess. I even dropped a release level to see if it was just that release. Ill give you a clue, DONT TRANSFER YOUR FILES VIA AUTO, EXPECIALY YOUR TXT FILES. TRANSFER THEM IN ASCII MODE ONLY, THIS INCLUDES YOUR PHP FILES. Then you just f—ing* MIGHT get readable files. Now you might say hey wait a min, we have full documentation on our web site, but you forget, someone has to open the sample.config.php file and read the crap that resides there.

* edited for content

Should I respond?  If so, how?  I decided to respond in as nice a way as I could.

 I normally don’t answer direct support emails.  Neither do I normally answer very angry emails.  However, I view this as an educational experience.

Judging by your email, I would say you are using Notepad on Windows to edit and read files.  That is mistake number one.  Notepad only reads one file format: Windows text files.  Windows natively uses a CRLF for it’s line endings.  It is the only operating system that does so. Notepad is the only application on the Windows platform that only reads that format.  If you would use Wordpad instead, this would not have been a problem for you.  For some reading on the subject, you may want to read:

http://en.wikipedia.org/wiki/Newline
http://www.cs.toronto.edu/~krueger/csc209h/tut/line-endings.html

Because PHP scripts are most commonly deployed on a Linux platform, the Unix line feed (LF or \n) is best for PHP applications.  Here are some suggestions for some great text editors for Windows.

TextPad - http://www.textpad.com/
Metapad - http://www.liquidninja.com/metapad/
PSPad   - http://www.pspad.com/en/

I hope this has helped educate you on the world of new lines and how real programming works.  In the future, a kind word in the forums would be much more appreciated than an email like this.  Not all people would be as kind as I am being and want to help you grow.

What do you think?  Should have just let this guy go?  Should have been as ugly to him as he was to me?

Responsible use of the $_REQUEST variable.

Thursday, January 17, 2008

A recent thread split on the PHP Internals list has been about the use of the $_REQUEST variable. I have seen more than one person make the following logic mistake:

  1. I may get data via GET
  2. I may get data via POST
  3. Ah, I should use $_REQUEST as it will catch both.

There is a problem with that logic. Cookies! Cookies are also put ino $_REQUEST. In fact, they are put into $_REQUEST last. So, any data that was sent via GET or POST is overwritten by cookies of the same name.

When does this cause a problem? Well, let’s say you have a script that has a form that asks for a user name. You call the field username. So, you are looking for that data in $_REQUEST. Unknown to you, another member of your team makes a cookie named username on a totally unrelated application. His cookie needs to be accessible from several parts of the site, so he assigned the cookie to the path /. So, now, when a user submits your form, the data comes in looking like this:

$_GET[”username”] = “user input”;
$_COOKIE[”username”] = “Tom”;
$_REQUEST[”username”] = “Tom”;

So, now you have bad data for the username you wanted. This becomes even more menacing when you start thinking about security issues like XSS or CRSF. As Stefan Esser, a strong PHP Security advocate, wrote in another reply to the thread:

Just imagine my example…

switch ($_REQUEST[’action’])
{
case ‘logout’:
logout();
break;

}

When someone injects you a cookie like +++action=logout through an
XSS or through a feature like foobar.co.kr can set cookies for *.co.kr
(in FF atleast).
Then you CANNOT use the application anymore. This is a DOS. You cannot
defeat this problem except detecting and telling the user to delete his
cookies manually…

Yikes! So, now you have all kinds of problems with using $_REQUEST.

So, what is the best way to handle both GET and POST data? Well, here are a couple options.

Merge GET and POST data

You could use array_merge() to merge the $_GET and $_POST variables into one. I would use a new variable for this data. You can overwrite super globals. Some think it is a bad idea. I can’t argue that it could cause confusion if you did this in an environment where several parts of the application are going to be using user input. If you do want to do this you could do the following.

$user_input = array_merge($_GET, $_POST);
// or overwrite $_REQUEST - not recommended
$_REQUEST = array_merge($_GET, $_POST);

Use GET OR POST, not both

I personally like to only use either $_GET or $_POST. I have very rarely seen a case where using both made sense.  I normally favor $_POST if it is set.

if(!empty($_POST)){
$user_input = $_POST;
} elseif {
$user_input = $_GET;
}

Now we have a save array that can be used and we know that the data only came from one place.

Charity for our little team?

Wednesday, January 16, 2008

I don’t often beg for stuff, but this is not for me per se.  The Phorum team is raising money to get all of our team (all 3 of us) to Santa Clara for MySQL Conference.  We will be part of the DotOrg Pavilion again this year.  We thank MySQL for inviting us.  We just about have all we need for that part of our fund raising.
We also have need of a new server.  We don’t need much.  But, our old Celeron is feeling the pressure of all the new things we are doing with our documentation system.   This is where I am hoping some of you out there can help.  Surely somewhere, someone has a dual Xeon with an older raid card in it that they don’t need anymore.  We do have a need for cpu power and for RAID.  We lost a hard drive a few years ago and while we had backups, it was a hassle.  We were down for days.  We have hosting (from my employer, dealnews), but I guess if the deal was right, I might consider it.  I do run my personal email and another hobby site on the server.  But, 90+% of the usage is for Phorum.

So, if anyone can help us out,  either with hardware or a donation, we thank you.  You can email me at brian@phorum.org.

Expanding Phorum

Tuesday, January 08, 2008

I want to expand Phorum.  I want to be able to relate specific phorum threads to one specific entry on my FreeBSD Diary website.  I do this for article feedback.  This is very much like comments on a weblog.

To see this features in action, look at Phorum - how to install and customize it. This article is about Phorum 3, so you might not find much there for your existing Phorum 5 installation. Note the link to the comments under the date in the top right corner. If you click on it, you will find it links to http://www.freebsddiary.org/phorum/list.php?f=3&article_id=258. Note the additional URL paramter article_id. This uniquely identifies the article you were reading.

In the FreeBSD Diary database (freebsdiary.org), there is an article table:

freebsddiary.org=# \d articles
                               Table "public.articles"
    Column    |     Type     |                       Modifiers
--------------+--------------+-------------------------------------------------------
 id           | integer      | not null default nextval('articles_id_seq'::regclass)
 actual_date  | date         | not null
 name         | text         | not null
 completed    | character(1) | not null default 'N'::bpchar
 visible_date | text         | not null
 link         | text         | not null
 filename     | text         | not null
 description  | text         |
 author       | text         | default ''::text
Indexes:
    "articles_pkey" PRIMARY KEY, btree (id)
Check constraints:
    "articles_completed" CHECK (completed = 'Y'::bpchar OR completed = 'N'::bpchar)  

freebsddiary.org=#

This table is referenced from the article_feedback_xref table:

freebsddiary.org=# \d article_feedback_xref
Table "public.article_feedback_xref"
   Column   |  Type   | Modifiers
------------+---------+-----------
 article_id | integer | not null
 thread_id  | integer | not null
Indexes:
    "article_feedback_xref_pkey" PRIMARY KEY, btree (article_id, thread_id)
Foreign-key constraints:
    "$2" FOREIGN KEY (thread_id) REFERENCES article_feedback(id) ON UPDATE CASCADE ON DELETE CASCADE 

freebsddiary.org=#

I have customized the Phorum 3 code to restrict message selection to those related to this particular article. The entry in the cross reference table is added when a new post is made to the phorum.

I want Phorum 5 to provide the same functionality. I am not yet sure of how I am going to achieve this goal. It may be with a table similar to the able. It could be with custom fields on the message table.

I’m still in the idea phase. Ideas? Comments?

PostgreSQL - flexible and fast

Tuesday, January 08, 2008

I’m a PostgreSQL fan. I have been so since 2000.  It is fast.  Reliable.  And best of all, it treats your data right.

I’ve been using Phorum with PostgreSQL since 2000.  I’ve also been blogging since before the term blog was invented.  I called it a diary.

In this blog I shall outline my ideas and intentions with PostgreSQL.  It is my way of documenting what I am going to do.  At the same time, it allows Phorum users to provide feedback on what they want out of PostgreSQL.  I think PostgreSQL has the potential to handle large forums in a very fast and efficient manner. PostgreSQL 8.3, due out within a few weeks, will have full-text search built-in (current versions have full-text search as add-on modules).

Enjoy. Comment.  Learn.  Have fun.