putyourlightson / craft-blitz

Intelligent static page caching for creating lightning-fast sites with Craft CMS.
https://putyourlightson.com/plugins/blitz
Other
149 stars 36 forks source link

Syntax error or access violation: 1280 Incorrect index name 'craft_blitz_elementexpirydates_elementId_unq_idx' #240

Closed michaeljoy closed 4 years ago

michaeljoy commented 4 years ago

Describe the bug

Fatal schema migration failure updating Blitz plugin from craft cms UI.

MariaDB 10.4.8

Doesn't seem to be permissions related, tried running the alter table statement with a super user and got the same result.

craftdb> ALTER TABLE craft_blitz_elementexpirydates ADD CONSTRAINT craft_blitz_elementexpirydates_elementId_pk PRIMARY KEY (elementId)

Incorrect index name 'craft_blitz_elementexpirydates_elementId_unq_idx'

Current table DDL...

create table craft_blitz_elementexpirydates
(
    elementId int not null,
    expiryDate datetime null,
    constraint craft_blitz_elementexpirydates_elementId_unq_idx
        unique (elementId),
    constraint craft_blitz_elementexpirydates_elementId_fk
        foreign key (elementId) references craft_elements (id)
            on update cascade on delete cascade
)
charset=utf8;

create index craft_blitz_elementexpirydates_expiryDate_idx
    on craft_blitz_elementexpirydates (expiryDate);

Error output from Craft...

Database Exception: SQLSTATE[42000]: Syntax error or access violation: 1280 Incorrect index name 'craft_blitz_elementexpirydates_elementId_unq_idx'
The SQL being executed was: ALTER TABLE craft_blitz_elementexpirydates ADD CONSTRAINT craft_blitz_elementexpirydates_elementId_pk PRIMARY KEY (elementId)

Migration: putyourlightson\blitz\migrations\m200721_120000_add_primary_keys

Output:

> add primary key craft_blitz_elementcaches_cacheId_elementId_pk on {{%blitz_elementcaches}} (cacheId,elementId) ... done (time: 0.399s)
> add primary key craft_blitz_elementexpirydates_elementId_pk on {{%blitz_elementexpirydates}} (elementId) ...Exception: SQLSTATE[42000]: Syntax error or access violation: 1280 Incorrect index name 'craft_blitz_elementexpirydates_elementId_unq_idx'
The SQL being executed was: ALTER TABLE craft_blitz_elementexpirydates ADD CONSTRAINT craft_blitz_elementexpirydates_elementId_pk PRIMARY KEY (elementId) (/var/www/html/craft/3/vendor/yiisoft/yii2/db/Schema.php:674)
#0 /var/www/html/craft/3/vendor/yiisoft/yii2/db/Command.php(1298): yii\db\Schema->convertException()
#1 /var/www/html/craft/3/vendor/yiisoft/yii2/db/Command.php(1093): yii\db\Command->internalExecute()
#2 /var/www/html/craft/3/vendor/yiisoft/yii2/db/Migration.php(437): yii\db\Command->execute()
#3 /var/www/html/craft/3/vendor/craftcms/cms/src/db/Migration.php(348): yii\db\Migration->addPrimaryKey()
#4 /var/www/html/craft/3/vendor/putyourlightson/craft-blitz/src/migrations/m200721_120000_add_primary_keys.php(29): craft\db\Migration->addPrimaryKey()
#5 /var/www/html/craft/3/vendor/craftcms/cms/src/db/Migration.php(52): putyourlightson\blitz\migrations\m200721_120000_add_primary_keys->safeUp()
#6 /var/www/html/craft/3/vendor/craftcms/cms/src/db/MigrationManager.php(233): craft\db\Migration->up()
#7 /var/www/html/craft/3/vendor/craftcms/cms/src/db/MigrationManager.php(153): craft\db\MigrationManager->migrateUp()
#8 /var/www/html/craft/3/vendor/craftcms/cms/src/services/Updates.php(233): craft\db\MigrationManager->up()
#9 /var/www/html/craft/3/vendor/craftcms/cms/src/controllers/BaseUpdaterController.php(510): craft\services\Updates->runMigrations()
#10 /var/www/html/craft/3/vendor/craftcms/cms/src/controllers/UpdaterController.php(203): craft\controllers\BaseUpdaterController->runMigrations()
#11 [internal function]: craft\controllers\UpdaterController->actionMigrate()
#12 /var/www/html/craft/3/vendor/yiisoft/yii2/base/InlineAction.php(57): call_user_func_array()
#13 /var/www/html/craft/3/vendor/yiisoft/yii2/base/Controller.php(157): yii\base\InlineAction->runWithParams()
#14 /var/www/html/craft/3/vendor/craftcms/cms/src/web/Controller.php(178): yii\base\Controller->runAction()
#15 /var/www/html/craft/3/vendor/yiisoft/yii2/base/Module.php(528): craft\web\Controller->runAction()
#16 /var/www/html/craft/3/vendor/craftcms/cms/src/web/Application.php(291): yii\base\Module->runAction()
#17 /var/www/html/craft/3/vendor/craftcms/cms/src/web/Application.php(646): craft\web\Application->runAction()
#18 /var/www/html/craft/3/vendor/craftcms/cms/src/web/Application.php(243): craft\web\Application->_processUpdateLogic()
#19 /var/www/html/craft/3/vendor/yiisoft/yii2/base/Application.php(386): craft\web\Application->handleRequest()
#20 /var/www/html/craft/3/web/index.php(21): yii\base\Application->run()
#21 {main}

To reproduce

Steps to reproduce the behaviour:

  1. Go to update blitz plugin in craft 3
  2. Click on update (just the blitz plugin)
  3. See error message "Database Exception: SQLSTATE[42000]: Syntax error or access violation: 1280 Incorrect index name 'craft_blitz_elementexpirydates_elementId_unq_idx'"

Expected behaviour

Updating to latest Blitz plugin version migrates successfully.

Screenshots

If applicable, add screenshots to help explain your problem.

Versions

michaeljoy commented 4 years ago

The only way to get this to move forward was to remove duplicate primary keys already defined that you're trying to add constraints on as well, and invalid, or incorrect duplicate indexes w/ _unq_idx. Foreign key constraints were invalid in several tables and restricted dropping the invalid or incorrectly named indexes that are duplicate of the default primary key index.

Resulting DDL (please validate that this is correct, I believe there's perhaps some cascading delete / update FK's missing here as they had to be dropped).

create or replace table craft_blitz_caches
(
    id int auto_increment
        primary key,
    siteId int not null,
    uri varchar(255) not null,
    expiryDate datetime null,
    constraint craft_blitz_caches_siteId_uri_unq_idx
        unique (siteId, uri),
    constraint craft_blitz_caches_siteId_fk
        foreign key (siteId) references craft_sites (id)
            on update cascade on delete cascade
)
charset=utf8;

create or replace index craft_blitz_caches_expiryDate_idx
    on craft_blitz_caches (expiryDate);

create or replace table craft_blitz_cachetags
(
    cacheId int not null,
    tag varchar(255) not null,
    constraint craft_blitz_cachetags_cacheId_fk
        foreign key (cacheId) references craft_blitz_caches (id)
            on update cascade on delete cascade
)
charset=utf8;

create or replace index craft_blitz_cachetags_tag_idx
    on craft_blitz_cachetags (tag);

create or replace table craft_blitz_driverdata
(
    id int auto_increment
        primary key,
    driver varchar(255) not null,
    data text null,
    dateCreated datetime not null,
    dateUpdated datetime not null,
    uid char(36) default '0' not null
)
charset=utf8;

create or replace table craft_blitz_elementcaches
(
    cacheId int not null,
    elementId int not null,
    constraint craft_blitz_elementcaches_cacheId_fk
        foreign key (cacheId) references craft_blitz_caches (id)
            on update cascade on delete cascade,
    constraint craft_blitz_elementcaches_elementId_fk
        foreign key (elementId) references craft_elements (id)
            on update cascade on delete cascade
)
charset=utf8;

create or replace table craft_blitz_elementexpirydates
(
    elementId int not null,
    expiryDate datetime null
)
charset=utf8;

create or replace index craft_blitz_elementexpirydates_expiryDate_idx
    on craft_blitz_elementexpirydates (expiryDate);

create or replace table craft_blitz_elementqueries
(
    id int auto_increment
        primary key,
    `index` bigint not null,
    type varchar(255) not null,
    params text null,
    constraint craft_blitz_elementqueries_index_unq_idx
        unique (`index`)
)
charset=utf8;

create or replace index craft_blitz_elementqueries_type_idx
    on craft_blitz_elementqueries (type);

create or replace table craft_blitz_elementquerycaches
(
    cacheId int not null,
    queryId int not null
)
charset=utf8;

create or replace index craft_blitz_elementquerycaches_queryId_fk
    on craft_blitz_elementquerycaches (queryId);

create or replace table craft_blitz_elementquerysources
(
    sourceId int null,
    queryId int not null,
    constraint craft_blitz_elementquerysources_sourceId_queryId_unq_idx
        unique (sourceId, queryId),
    constraint craft_blitz_elementquerysources_queryId_fk
        foreign key (queryId) references craft_blitz_elementqueries (id)
            on update cascade on delete cascade
)
charset=utf8;

create or replace table craft_blitz_recommendations
(
    id int auto_increment
        primary key,
    `key` varchar(255) not null,
    template varchar(255) null,
    message text null,
    info text null,
    dateCreated datetime not null,
    dateUpdated datetime not null,
    uid char(36) default '0' not null,
    constraint craft_blitz_recommendations_key_template_unq_idx
        unique (`key`, template)
)
charset=utf8;
michaeljoy commented 4 years ago

Just to be safe I purged the app and made sure the tables were gone before re-installing and re-configuring the Blitz plugin. Definitely non-optimal but works...

Resulting DDL for the tables when they were created from scratch.

create table craft_blitz_caches
(
    id int auto_increment
        primary key,
    siteId int not null,
    uri varchar(255) not null,
    expiryDate datetime null,
    constraint craft_blitz_caches_siteId_uri_unq_idx
        unique (siteId, uri),
    constraint craft_blitz_caches_siteId_fk
        foreign key (siteId) references craft_sites (id)
            on update cascade on delete cascade
)
charset=utf8;

create index craft_blitz_caches_expiryDate_idx
    on craft_blitz_caches (expiryDate);

create table craft_blitz_cachetags
(
    cacheId int not null,
    tag varchar(255) not null,
    primary key (cacheId, tag),
    constraint craft_blitz_cachetags_cacheId_fk
        foreign key (cacheId) references craft_blitz_caches (id)
            on update cascade on delete cascade
)
charset=utf8;

create index craft_blitz_cachetags_tag_idx
    on craft_blitz_cachetags (tag);

create table craft_blitz_driverdata
(
    id int auto_increment
        primary key,
    driver varchar(255) not null,
    data text null,
    dateCreated datetime not null,
    dateUpdated datetime not null,
    uid char(36) default '0' not null
)
charset=utf8;

create table craft_blitz_elementcaches
(
    cacheId int not null,
    elementId int not null,
    primary key (cacheId, elementId),
    constraint craft_blitz_elementcaches_cacheId_fk
        foreign key (cacheId) references craft_blitz_caches (id)
            on update cascade on delete cascade,
    constraint craft_blitz_elementcaches_elementId_fk
        foreign key (elementId) references craft_elements (id)
            on update cascade on delete cascade
)
charset=utf8;

create table craft_blitz_elementexpirydates
(
    elementId int not null,
    expiryDate datetime null,
    constraint craft_blitz_elementexpirydates_elementId_unq_idx
        unique (elementId),
    constraint craft_blitz_elementexpirydates_elementId_fk
        foreign key (elementId) references craft_elements (id)
            on update cascade on delete cascade
)
charset=utf8;

create index craft_blitz_elementexpirydates_expiryDate_idx
    on craft_blitz_elementexpirydates (expiryDate);

alter table craft_blitz_elementexpirydates
    add primary key (elementId);

create table craft_blitz_elementqueries
(
    id int auto_increment
        primary key,
    `index` bigint not null,
    type varchar(255) not null,
    params text null,
    constraint craft_blitz_elementqueries_index_unq_idx
        unique (`index`)
)
charset=utf8;

create index craft_blitz_elementqueries_type_idx
    on craft_blitz_elementqueries (type);

create table craft_blitz_elementquerycaches
(
    cacheId int not null,
    queryId int not null,
    constraint craft_blitz_elementquerycaches_cacheId_queryId_unq_idx
        unique (cacheId, queryId),
    constraint craft_blitz_elementquerycaches_cacheId_fk
        foreign key (cacheId) references craft_blitz_caches (id)
            on update cascade on delete cascade,
    constraint craft_blitz_elementquerycaches_queryId_fk
        foreign key (queryId) references craft_blitz_elementqueries (id)
            on update cascade on delete cascade
)
charset=utf8;

alter table craft_blitz_elementquerycaches
    add primary key (cacheId, queryId);

create table craft_blitz_elementquerysources
(
    id int auto_increment
        primary key,
    sourceId int null,
    queryId int not null,
    constraint craft_blitz_elementquerysources_sourceId_queryId_unq_idx
        unique (sourceId, queryId),
    constraint craft_blitz_elementquerysources_queryId_fk
        foreign key (queryId) references craft_blitz_elementqueries (id)
            on update cascade on delete cascade
)
charset=utf8;

create table craft_blitz_recommendations
(
    id int auto_increment
        primary key,
    `key` varchar(255) not null,
    template varchar(255) null,
    message text null,
    info text null,
    dateCreated datetime not null,
    dateUpdated datetime not null,
    uid char(36) default '0' not null,
    constraint craft_blitz_recommendations_key_template_unq_idx
        unique (`key`, template)
)
charset=utf8;
bencroker commented 4 years ago

Thanks for reporting this. It seems like an edge case as you are the only person who has reported this and I cannot replicate locally. Added a fix in https://github.com/putyourlightson/craft-blitz/commit/99486c3a82756cbb1415f0eff905bc76e9fd51a3 to help avoid this in future.

bencroker commented 4 years ago

Released in version 3.6.7.

mijewe commented 4 years ago

I'm also having this issue when updating from 3.6.5 to 3.6.7

Yii Migration Tool (based on Yii v2.0.36)

    > drop index blitz_elementcaches_cacheId_elementId_unq_idx on {{%blitz_elementcaches}} ...    > add primary key blitz_elementcaches_cacheId_elementId_pk on {{%blitz_elementcaches}} (cacheId,elementId) ... done (time: 0.457s)
    > drop foreign key blitz_elementexpirydates_elementId_fk from table {{%blitz_elementexpirydates}} ... done (time: 0.081s)
    > drop index blitz_elementexpirydates_elementId_unq_idx on {{%blitz_elementexpirydates}} ... done (time: 0.043s)
    > add primary key blitz_elementexpirydates_elementId_pk on {{%blitz_elementexpirydates}} (elementId) ... done (time: 0.033s)
    > add foreign key blitz_elementexpirydates_elementId_fk: {{%blitz_elementexpirydates}} (elementId) references {{%elements}} (id) ... done (time: 0.050s)
    > drop index blitz_elementquerycaches_cacheId_queryId_unq_idx on {{%blitz_elementquerycaches}} ...    > add primary key blitz_elementquerycaches_cacheId_queryId_pk on {{%blitz_elementquerycaches}} (cacheId,queryId) ...Exception: SQLSTATE[42000]: Syntax error or access violation: 1280 Incorrect index name 'blitz_elementquerycaches_cacheId_queryId_unq_idx'
The SQL being executed was: ALTER TABLE `blitz_elementquerycaches` ADD CONSTRAINT `blitz_elementquerycaches_cacheId_queryId_pk` PRIMARY KEY (`cacheId`, `queryId`) (/Users/xxx/craft/vendor/yiisoft/yii2/db/Schema.php:677)
#0 /Users/xxx/craft/vendor/yiisoft/yii2/db/Command.php(1298): yii\db\Schema->convertException(Object(PDOException), 'ALTER TABLE `bl...')
#1 /Users/xxx/craft/vendor/yiisoft/yii2/db/Command.php(1093): yii\db\Command->internalExecute('ALTER TABLE `bl...')
#2 /Users/xxx/craft/vendor/yiisoft/yii2/db/Migration.php(437): yii\db\Command->execute()
#3 /Users/xxx/craft/vendor/craftcms/cms/src/db/Migration.php(362): yii\db\Migration->addPrimaryKey('blitz_elementqu...', '{{%blitz_elemen...', Array)
#4 /Users/xxx/craft/vendor/putyourlightson/craft-blitz/src/migrations/m200721_120000_add_primary_keys.php(64): craft\db\Migration->addPrimaryKey('blitz_elementqu...', '{{%blitz_elemen...', Array)
#5 /Users/xxx/craft/vendor/craftcms/cms/src/db/Migration.php(52): putyourlightson\blitz\migrations\m200721_120000_add_primary_keys->safeUp()
#6 /Users/xxx/craft/vendor/craftcms/cms/src/db/MigrationManager.php(232): craft\db\Migration->up(true)
#7 /Users/xxx/craft/vendor/craftcms/cms/src/db/MigrationManager.php(148): craft\db\MigrationManager->migrateUp(Object(putyourlightson\blitz\migrations\m200721_120000_add_primary_keys))
#8 /Users/xxx/craft/vendor/craftcms/cms/src/services/Updates.php(227): craft\db\MigrationManager->up()
#9 /Users/xxx/craft/vendor/craftcms/cms/src/console/controllers/MigrateController.php(328): craft\services\Updates->runMigrations(Array)
#10 [internal function]: craft\console\controllers\MigrateController->actionAll()
#11 /Users/xxx/craft/vendor/yiisoft/yii2/base/InlineAction.php(57): call_user_func_array(Array, Array)
#12 /Users/xxx/craft/vendor/yiisoft/yii2/base/Controller.php(180): yii\base\InlineAction->runWithParams(Array)
#13 /Users/xxx/craft/vendor/yiisoft/yii2/console/Controller.php(181): yii\base\Controller->runAction('all', Array)
#14 /Users/xxx/craft/vendor/yiisoft/yii2/base/Module.php(528): yii\console\Controller->runAction('all', Array)
#15 /Users/xxx/craft/vendor/yiisoft/yii2/console/Application.php(180): yii\base\Module->runAction('migrate/all', Array)
#16 /Users/xxx/craft/vendor/craftcms/cms/src/console/Application.php(87): yii\console\Application->runAction('migrate/all', Array)
#17 /Users/xxx/craft/vendor/yiisoft/yii2/console/Application.php(147): craft\console\Application->runAction('migrate/all', Array)
#18 /Users/xxx/craft/vendor/yiisoft/yii2/base/Application.php(386): yii\console\Application->handleRequest(Object(craft\console\Request))
#19 /Users/xxx/craft/craft(22): yii\base\Application->run()
#20 {main}
bencroker commented 4 years ago

@mijewe Can you run the following query in your database to see if the blitz_elementquerycaches_cacheId_queryId_unq_idx still exists? It should be dropped as part of the update migration.

SHOW INDEX FROM blitz_elementquerycaches;
cavellblood commented 4 years ago

I was having this same issue when trying to upgrade to 3.6.6 but didn't have the time to document it. Upgrading from 3.6.5 to 3.6.7 worked correctly though. No problems.

cavellblood commented 4 years ago

I take that back. When I looked at my composer.json file I saw that I was upgrading from 3.6.6 to 3.6.7. I remember that I eventually just uninstalled the plugin all together and installed it fresh from 3.6.6 since I had just started using the plugin anyway and didn't have much to lose.

bencroker commented 4 years ago

Thanks for the feedback and sorry about this affecting people sporadically. If anyone else encounters this then please open a new issue with the log file error so we can investigate further. Currently, the most reliable fix is to uninstall and then install the plugin, but this is only really feasible if you have just started using the plugin or you store all of the settings in the config settings file.

bencroker commented 4 years ago

Released a further fix in version 3.6.8.