Updaters
I blogged about picking up Tim’s new installer branch last summer. I worked on it with a lot of help from Max and demo’d it in Berlin. Since Berlin, Ævar, Siebrand and Mark have joined in and it’s getting a whole lot closer to being done. It’s in trunk, the installation runs pretty smoothly. Updates are still a pain in the ass.
Database upgrades suck when you have to maintain them for multiple DBMSes. In working on the new installer (and associated updater refactoring), we’ve come up against a very annoying wall: maintaining versioned updates for databases gets to be difficult. With varying levels of support, the only schema that is guaranteed to work–provided someone didn’t break trunk–is mySQL. We maintain a list of of patch files to be applied, in order, on each upgrade. This list is kept up to date for mySQL; SQLite generally just works with mySQL’s syntax so it’s pretty close behind in support. Postgres tends to lag a few hours or days (and maintains its own set of update sequences, actually). Oracle doesn’t do patch files, but does update its default schema…so updates aren’t really possible except manually. Ibm_Db2 is all but abandoned, and Mssql was removed.
I briefly experimented with abstracting the whole schema to a big array of table definitions, but this was going to take too much work so the work was split off into a branch. One day I’d like to go back to this–done properly, it would cure our schema woes forever. Left with no other solution, Max forced the current updaters to run from the web, grabbing the output and throwing it back at the user. This is bad for a couple of reasons.
- Updates can take a long time to run, especially if you have big tables. The fact that we run every update every time you try to upgrade wastes cycles.
- It makes it impossible to localize along with the rest of the installer, all of the updaters output is hardcoded.
- Without a clearly defined interface, it’s hard to get information back to the user and they’re left reading the output from update.php. Did the script warn or fail completely? Can we proceed?
So I decided to refactor things a bit. First I changed the updatelog table to contain an optional ul_value column (it already had ul_key). I moved the array of updates into their own class, so we can at least visually separate the list from the implementation. I then moved some of the core logic out of updaters.inc into a new Update class. Issue number one is pretty much mitigated now, since the new class logs which updates are performed, so it won’t needlessly repeat updates. Issues 2 and 3 are more possible now, since we could (haven’t yet) implement an output callback system like I did for Installer::performInstallation().
SQLite was easy, and Oracle just has a dummy implementation for now. Postgres is another beast entirely. Like I mentioned above, it maintains its own update sequence. Parts of it make sense, parts of it don’t, but none of it is designed like the others. Basically needs to be rewritten entirely.
For the new-installer to be complete by the time 1.17 rolls out, we need to pick up the pace. The time for new features is pretty much over and we need to start closing up the last few bugs. Updates are a blocker still. They’re a bit better than they were, but it’s still got a lonnnggg way to go before we’re done maintaining patch files for each DBMS. As always, bugs in the new installer can go here or in Bugzilla.
