Upgrading from pre-5.47 to 5.48+ isn't re-runnable in certain situations
Since sketching out the below, I think I can see there is a quick solution, but now that I've written the description already I'll still post the whole thing. Short version: This line should have a check that is_autorun
exists in the table before running the query: https://github.com/civicrm/civicrm-core/blob/88e3bfdfc52aa1e117160b6592597510af446d1a/CRM/Upgrade/Incremental/php/FiveFortyEight.php#L60
Problem
Typical sysadmin: "Goin' to upgrade now. Let me make a backup... ok, done. Upgrade, and ... oh that failed. Ok let me reload my sql file and apply this patch and try again... Oh that failed - something about queues. Repeat. Fail again. Hmm."
For a dev doing testing this might not come up, because they might "start from scratch" when repeating (or use trickery like devs do).
The difference is the reload db, and in particular when upgrading pre-5.47 to 5.48+. And given the history to-date, that reload-and-try-again cycle is likely to come up more with 5.47 than usual.
In 5.47, the civicrm_queue
table is created, but ONLY if it doesn't exist. I.e. as opposed to DROP TABLE IF EXISTS civicrm_queue
, followed by the creation. Since this table might have long-term data, you don't want to drop it if an upgrade is being re-run some time in the future.
(Aside: That create table statement probably shouldn't enforce utf8mb4 yet, but that's separate.)
So now let's think about the sequence for the sysadmin:
- Before first attempt, civicrm_queue didn't exist.
- After first attempt, it now exists.
- Reload db. Note something important: The backup sql file does NOT have anything about civicrm_queue. There is no DROP TABLE statement for it. So after reloading the sql file, civicrm_queue DOES exist, which is different from before the first run.
- If you're the type of sysadmin who drops the whole db before reloading the sql file, you won't run into this. I don't know what percentage that covers.
So now, there's an upgrade step in 5.48 that assumes that the field is_autorun
is going to exist. But it doesn't because civicrm_queue at this point is the already upgraded table.
SECONDARY ISSUE
There's another issue here too for similar reasons, but I haven't confirmed the specific problem, but at the moment I think there is one.
Something new in 5.47 is that civi will auto-install search kit and afform. These both create database tables. So you have a similar situation where after reloading the db, you have an already upgraded table present when it shouldn't be, so you get a similar problem when something tries to act on it in a way that isn't re-runnable.