Browse Source

Fix foreign keys in MySQL

microsub
J. King 4 years ago
parent
commit
737dd9f6b8
  1. 6
      CHANGELOG
  2. 10
      UPGRADING
  3. 6
      lib/Database.php
  4. 49
      sql/MySQL/5.sql
  5. 7
      sql/PostgreSQL/5.sql
  6. 7
      sql/SQLite3/5.sql
  7. 4
      tests/lib/DatabaseDrivers/MySQL.php

6
CHANGELOG

@ -1,3 +1,9 @@
Version 0.8.2 (????-??-??)
==========================
Bug fixes:
- Enforce foreign key constraints in MySQL
Version 0.8.1 (2019-10-28) Version 0.8.1 (2019-10-28)
========================== ==========================

10
UPGRADING

@ -10,6 +10,15 @@ usually prudent:
- If installing from source, update dependencies with: - If installing from source, update dependencies with:
`composer install -o --no-dev` `composer install -o --no-dev`
Upgrading from 0.8.1 to 0.8.2
=============================
- The database schema has changed from rev5 to rev6; if upgrading the database
manually, apply the 5.sql file. MySQL databases may need manual
intervention to ensure foreign key constraints are not violated
Upgrading from 0.7.1 to 0.8.0 Upgrading from 0.7.1 to 0.8.0
============================= =============================
@ -22,6 +31,7 @@ Upgrading from 0.7.1 to 0.8.0
- zendframework/zend-diactoros (version 2.x) - zendframework/zend-diactoros (version 2.x)
- zendframework/zend-httphandlerrunner - zendframework/zend-httphandlerrunner
Upgrading from 0.5.1 to 0.6.0 Upgrading from 0.5.1 to 0.6.0
============================= =============================

6
lib/Database.php

@ -39,7 +39,7 @@ use JKingWeb\Arsse\Misc\URL;
*/ */
class Database { class Database {
/** The version number of the latest schema the interface is aware of */ /** The version number of the latest schema the interface is aware of */
const SCHEMA_VERSION = 5; const SCHEMA_VERSION = 6;
/** The size of a set of values beyond which the set will be embedded into the query text */ /** The size of a set of values beyond which the set will be embedded into the query text */
const LIMIT_SET_SIZE = 25; const LIMIT_SET_SIZE = 25;
/** The length of a string in an embedded set beyond which a parameter placeholder will be used for the string */ /** The length of a string in an embedded set beyond which a parameter placeholder will be used for the string */
@ -50,7 +50,7 @@ class Database {
const ASSOC_ADD = 1; const ASSOC_ADD = 1;
/** Makes tag/label association change operations replace members */ /** Makes tag/label association change operations replace members */
const ASSOC_REPLACE = 2; const ASSOC_REPLACE = 2;
/** A map database driver short-names and their associated class names */ /** A map of database driver short-names and their associated class names */
const DRIVER_NAMES = [ const DRIVER_NAMES = [
'sqlite3' => \JKingWeb\Arsse\Db\SQLite3\Driver::class, 'sqlite3' => \JKingWeb\Arsse\Db\SQLite3\Driver::class,
'postgresql' => \JKingWeb\Arsse\Db\PostgreSQL\Driver::class, 'postgresql' => \JKingWeb\Arsse\Db\PostgreSQL\Driver::class,
@ -520,7 +520,7 @@ class Database {
if (!ValueInfo::id($id)) { if (!ValueInfo::id($id)) {
throw new Db\ExceptionInput("typeViolation", ["action" => __FUNCTION__, "field" => "folder", 'type' => "int > 0"]); throw new Db\ExceptionInput("typeViolation", ["action" => __FUNCTION__, "field" => "folder", 'type' => "int > 0"]);
} }
$changes = $this->db->prepare("WITH RECURSIVE folders(folder) as (SELECT ? union select id from arsse_folders join folders on parent = folder) DELETE FROM arsse_folders where owner = ? and id in (select folder from folders)", "int", "str")->run($id, $user)->changes(); $changes = $this->db->prepare("DELETE FROM arsse_folders where owner = ? and id = ?", "str", "int")->run($user, $id)->changes();
if (!$changes) { if (!$changes) {
throw new Db\ExceptionInput("subjectMissing", ["action" => __FUNCTION__, "field" => "folder", 'id' => $id]); throw new Db\ExceptionInput("subjectMissing", ["action" => __FUNCTION__, "field" => "folder", 'id' => $id]);
} }

49
sql/MySQL/5.sql

@ -0,0 +1,49 @@
-- SPDX-License-Identifier: MIT
-- Copyright 2017 J. King, Dustin Wilson et al.
-- See LICENSE and AUTHORS files for details
-- Please consult the SQLite 3 schemata for commented version
-- Correct character set and collation of sessions table
alter table arsse_sessions default character set utf8mb4 collate utf8mb4_unicode_ci;
alter table arsse_sessions convert to character set utf8mb4 collate utf8mb4_unicode_ci;
-- Make integer foreign key referrers unsigned to match serial-type keys
alter table arsse_folders modify parent bigint unsigned;
alter table arsse_subscriptions modify feed bigint unsigned not null;
alter table arsse_subscriptions modify folder bigint unsigned;
alter table arsse_articles modify feed bigint unsigned not null;
alter table arsse_enclosures modify article bigint unsigned not null;
alter table arsse_marks modify article bigint unsigned not null;
alter table arsse_marks modify subscription bigint unsigned not null;
alter table arsse_editions modify article bigint unsigned not null;
alter table arsse_categories modify article bigint unsigned not null;
alter table arsse_label_members modify label bigint unsigned not null;
alter table arsse_label_members modify article bigint unsigned not null;
alter table arsse_label_members modify subscription bigint unsigned not null;
alter table arsse_tag_members modify tag bigint unsigned not null;
alter table arsse_tag_members modify subscription bigint unsigned not null;
-- Fix foreign key constraints
alter table arsse_folders add foreign key(owner) references arsse_users(id) on delete cascade on update cascade;
alter table arsse_folders add foreign key(parent) references arsse_folders(id) on delete cascade;
alter table arsse_subscriptions add foreign key(owner) references arsse_users(id) on delete cascade on update cascade;
alter table arsse_subscriptions add foreign key(feed) references arsse_feeds(id) on delete cascade;
alter table arsse_subscriptions add foreign key(folder) references arsse_folders(id) on delete cascade;
alter table arsse_articles add foreign key(feed) references arsse_feeds(id) on delete cascade;
alter table arsse_enclosures add foreign key(article) references arsse_articles(id) on delete cascade;
alter table arsse_marks add foreign key(article) references arsse_articles(id) on delete cascade;
alter table arsse_marks add foreign key(subscription) references arsse_subscriptions(id) on delete cascade;
alter table arsse_editions add foreign key(article) references arsse_articles(id) on delete cascade;
alter table arsse_categories add foreign key(article) references arsse_articles(id) on delete cascade;
alter table arsse_sessions add foreign key("user") references arsse_users(id) on delete cascade on update cascade;
alter table arsse_labels add foreign key(owner) references arsse_users(id) on delete cascade on update cascade;
alter table arsse_label_members add foreign key(label) references arsse_labels(id) on delete cascade;
alter table arsse_label_members add foreign key(article) references arsse_articles(id) on delete cascade;
alter table arsse_label_members add foreign key(subscription) references arsse_subscriptions(id) on delete cascade;
alter table arsse_tags add foreign key(owner) references arsse_users(id) on delete cascade on update cascade;
alter table arsse_tag_members add foreign key(tag) references arsse_tags(id) on delete cascade;
alter table arsse_tag_members add foreign key(subscription) references arsse_subscriptions(id) on delete cascade;
alter table arsse_tokens add foreign key("user") references arsse_users(id) on delete cascade on update cascade;
update arsse_meta set value = '6' where "key" = 'schema_version';

7
sql/PostgreSQL/5.sql

@ -0,0 +1,7 @@
-- SPDX-License-Identifier: MIT
-- Copyright 2017 J. King, Dustin Wilson et al.
-- See LICENSE and AUTHORS files for details
-- Please consult the SQLite 3 schemata for commented version
update arsse_meta set value = '6' where "key" = 'schema_version';

7
sql/SQLite3/5.sql

@ -0,0 +1,7 @@
-- SPDX-License-Identifier: MIT
-- Copyright 2017 J. King, Dustin Wilson et al.
-- See LICENSE and AUTHORS files for details
-- set version marker
pragma user_version = 6;
update arsse_meta set value = '6' where "key" = 'schema_version';

4
tests/lib/DatabaseDrivers/MySQL.php

@ -48,6 +48,7 @@ trait MySQL {
$db->query("UNLOCK TABLES; ROLLBACK"); $db->query("UNLOCK TABLES; ROLLBACK");
} catch (\Throwable $e) { } catch (\Throwable $e) {
} }
$db->query("SET FOREIGN_KEY_CHECKS=0");
foreach (self::dbTableList($db) as $table) { foreach (self::dbTableList($db) as $table) {
if ($table === "arsse_meta") { if ($table === "arsse_meta") {
$db->query("DELETE FROM $table where `key` <> 'schema_version'"); $db->query("DELETE FROM $table where `key` <> 'schema_version'");
@ -56,6 +57,7 @@ trait MySQL {
} }
$db->query("ALTER TABLE $table auto_increment = 1"); $db->query("ALTER TABLE $table auto_increment = 1");
} }
$db->query("SET FOREIGN_KEY_CHECKS=1");
foreach ($afterStatements as $st) { foreach ($afterStatements as $st) {
$db->query($st); $db->query($st);
} }
@ -67,9 +69,11 @@ trait MySQL {
$db->query("UNLOCK TABLES; ROLLBACK"); $db->query("UNLOCK TABLES; ROLLBACK");
} catch (\Throwable $e) { } catch (\Throwable $e) {
} }
$db->query("SET FOREIGN_KEY_CHECKS=0");
foreach (self::dbTableList($db) as $table) { foreach (self::dbTableList($db) as $table) {
$db->query("DROP TABLE IF EXISTS $table"); $db->query("DROP TABLE IF EXISTS $table");
} }
$db->query("SET FOREIGN_KEY_CHECKS=1");
foreach ($afterStatements as $st) { foreach ($afterStatements as $st) {
$db->query($st); $db->query($st);
} }

Loading…
Cancel
Save