I’ve been digging into the guts of Magento 1’s setup resource migration system, and I’ve run into some unexpected behavior. Unexpected is probably the wrong word, because I treated a lot of these details as black boxes until now. I’m documenting this here for myself, but reserve the right to come back later if my understanding of this sometimes opaque system turns out to be incorrect.
There are two types of setup resource scripts, install scripts and upgrade scripts. It turns out install scripts only run the first time Magento sees a module. Programmatically, this means Magento will choose to run the install scripts when it can’t find any version number in the core_resource
table.
When the setup resource class decides it needs to run an install script, it will look for the install script with the version number that’s closest to the module version in config.xml
, without going over. Only one install script is ever run.
Finally, when the setup resource class takes the install code path — after running the single install script it then also runs the upgrade script next, using the version from the install script name as a starting point. This happens here (the comments are mine)
#File: app/code/core/Mage/Core/Model/Resource/Setup.php
protected function _installData($newVersion)
{
#runs a single install script
$oldVersion = $this->_modifyResourceDb(self::TYPE_DATA_INSTALL, '', $newVersion);
#runs all upgrades. Starts from the version in the install script,
#goes to the `$newVersion` (which is the `config.xml` version)
$this->_modifyResourceDb(self::TYPE_DATA_UPGRADE, $oldVersion, $newVersion);
//...
}
Example Surprises
If you look a the catalog_setup
install scripts, you’ll see there’s three of them
catalog_setup/install-1.6.0.0.php
catalog_setup/mysql4-install-1.4.0.0.0.php
catalog_setup/mysql4-install-0.7.0.php
If you’re installing Magento 1.8 today without the sample data, Magento will start with the install-1.6.0.0.php
script, because 1.6.0.0
is the closest version to what’s in the config.xml
file
#File: app/code/core/Mage/Catalog/etc/config.xml
//...
<Mage_Catalog>
<version>1.6.0.0.18</version>
</Mage_Catalog>
//...
The mysql4-install-0.7.0.php
and mysql4-install-1.4.0.0.0.php
are never run. Then, the following upgrade scripts are run
catalog_setup/upgrade-1.6.0.0-1.6.0.0.1.php
catalog_setup/upgrade-1.6.0.0.1-1.6.0.0.2.php
catalog_setup/upgrade-1.6.0.0.10-1.6.0.0.11.php
catalog_setup/upgrade-1.6.0.0.11-1.6.0.0.12.php
catalog_setup/upgrade-1.6.0.0.14-1.6.0.0.15.php
catalog_setup/upgrade-1.6.0.0.15-1.6.0.0.18.php
catalog_setup/upgrade-1.6.0.0.2-1.6.0.0.3.php
catalog_setup/upgrade-1.6.0.0.3-1.6.0.0.4.php
catalog_setup/upgrade-1.6.0.0.4-1.6.0.0.5.php
catalog_setup/upgrade-1.6.0.0.5-1.6.0.0.6.php
catalog_setup/upgrade-1.6.0.0.6-1.6.0.0.7.php
catalog_setup/upgrade-1.6.0.0.7-1.6.0.0.8.php
catalog_setup/upgrade-1.6.0.0.9-1.6.0.0.10.php
That is, only upgrade scripts which apply after 1.6.0.0.0
and before 1.6.0.0.8
, inclusive. The other upgrade scripts in the sql
folder never run.
However, if you’re installing with the sample data, that means core_resource
has a value for catalog_setup
. That means with sample data pre-installed, Magento would never run an install script, and instead run all upgrade scripts between your current version and the new version in config.xml
. This is why there’s also an upgrade script to 1.6.0.0
catalog_setup/mysql4-upgrade-1.5.9.9-1.6.0.0.php
Dropping in new install scripts appears to be a way to speed up the non-sample data installation process.
Finally, if Magento thinks it needs to install a module for the first time (nothing in core_resource
), but there’s no install scripts to run, it appears to grab all the upgrade scripts. It’s not clear if this is an intended design descision, or just fell out of the implementation detail of “first install”, “then upgrade”.