Ok, new Answer. It's not so much that the bounty makes me more creative, rather I feel less of a restraint to suggest a solution I don't consider straight :)
(I am still assuming you want to avoid stored routines at all cost)
Solution #1: using prepared statements
Suppose your uprades script is a simple:
ALTER TABLE t ADD COLUMN c INT DEFAULT 1
Then how about this:
SET @version := '1';
SELECT CASE val
WHEN @version THEN
'ALTER TABLE t ADD COLUMN c INT DEFAULT 1'
ELSE 'SELECT ''Wrong version. Nothing to upgrade.'''
END
INTO @stmt
FROM meta
WHERE name = 'Version';
PREPARE stmt FROM @stmt;
EXECUTE stmt;
Obvious drawbacks:
- sever clutter and overhead as you have to write this for each individual statement (
PREPARE
cannot batch multiple statements)
- additional annoyance because you have to write each statement from your upgrade script as a string...yuck
- not all statements can be written and executed with
PREPARE
Solution #2: usa one prepared statement to KILL the connection
You already pointed out that you dislike the solution you linked too...is that because of the KILL
statement, or because of the stored function? If it's because of the stored function, you can get around that:
SET @version := '1';
SELECT CASE val
WHEN @version THEN 'SELECT ''Performing upgrade...'''
ELSE CONCAT('KILL CONNECTION', connection_id())
END
INTO @stmt
FROM meta
WHERE name = 'Version';
PREPARE stmt FROM @stmt;
EXECUTE stmt; -- connection is killed if the version is not correct.
-- remainder of the upgrade script goes here...
mysql
must be started with the --skip-reconnect
option to ensure that no statements can be executed if the connection is killed
I tried to work around this drawback, and use PREPARE
for other things that would block out the current connection, such as dropping the user and revoking his privileges. Unfortunately, that does not work as intended (no, also not after FLUSH PRIVILEGES
)
Solution #3: use mysql proxy to intercept
Yet another solution: use a proxy. With mysql proxy (see: http://forge.mysql.com/wiki/MySQL_Proxy), you can write a custom intercept script in lua that interprets your custom commands. Using that you could add the necessary control structures. Drawback: you now have to design your own mini language, and learn lua to interpret it :)