After a couple of months of putting in an hour here and two there, I've finally ported Subtext to MySQL. Note, that this is NOT an official Subtext release.
This post is a digital catharsis of sorts. It's an attempt to "out" some of the knowledge I've gained from the port. And someday, when I forget all about the port, this post might serve as a reference for why I did something that seems dumb. But first things first. While we figure out where the source should reside, here are the downloads.
!!! UPDATE - March 30, 2008 !!!
I've released an update. Download the software here instead.
Binaries (3.69 MB)
Source (22.7 MB)
MySQL 5.x - previous versions did not support stored procedures.
Anything else that the regular Subtext requires.
If you need help/support, either post on the Subtext Open Discussion or hit me up via the Contact link in the upper right corner.
I ported the 1.9.5 version of Subtext, along with the recently released security patch. The solution structure remains the same, except for the extra project (MySQL port of the Microsoft Data Application block).
When I started out, I was contemplating on porting the Subtext 2.0 trunk code. But there was too much turbulence there. Eventually I settled on a strategy of modifying version 1.9.5, because it was already done/baked/released/written in stone. This decision turned out to be the right one, because the Subtext team temporarily gave up on the 2.0 branch in favor of a smaller 1.9.6 release.
The idea was to use the 1.9.5 port to learn the code, learn MySQL and use the knowledge in the later versions. Another strategy was to change the Subtext code and its structures as little as possible.
I've documented various issues that I ran into with MySQL a while ago. One of the more onerous problems is that anytime you request a COUNT(*) from MySQL, it returns a long (int64) data type, but Microsoft SQL Server returns an int (int32). Subtext, of course, expects an int, which led to hacky code like this:
entry.FeedBackCount = Convert.ToInt32(ReadInt64(reader, "FeedBackCount"));
On the whole, Subtext is actually is a very good shape. It's well commented and the coding style is very consistent for an OSS or an in-house project.
Having said that, the data layer is not very friendly to databases other than Microsoft SQL Server. Initially, when I surveyed the code, I thought that I could write the a MySQL data provider, plop it into the solution, do the dependency injection thing and pat myself on the back. As it stands, right now that's not possible. The main problem is that the data layer leaks references all over the place.
In other words, just because the data layer is using System.Data.SqlClient to interface with a data store, why should the business layer know about it? But currently it does, because the data layer expects parameters whose types reside in the System.Data.SqlClient namespace. There are helper classes which are dependent upon SqlClient as well. In addition, the exceptions are propagated as SqlException objects, with code looking for certain values in the exceptions and acting accordingly.
The solution to Data Layer woes is to push it deeper into isolation. Hopefully, at some point, I'll spend some time to make Subtext more hospitable to other databases.
So the solution for now was to simply rip out SqlClient and MS Application Block and replace it with MySQL analogs.
Unit tests don't run. I haven't ported them yet. Simply no time at this point.
Subtext performance against the MySQL database is basically on par with MS SQL version, according to my completely unscientific observations.