From bee3dea9c22c0ecd8722a020dc8dbe361a9145e8 Mon Sep 17 00:00:00 2001 From: Alexei Sorokin Date: Fri, 31 Jul 2020 16:36:40 +0300 Subject: [PATCH] [DATABASE] Add explicit indices for all foreign keys This adds a requirement for all definitions that have foreign keys to also require indices for all source (local) attributes mentioned in foreign keys. MariaDB/MySQL creates indices for source attributes automatically, so this serves as a way to get rid of those automatic indices and create clean explicit ones instead. In PostgreSQL, most of the time, indices on the source are necessary to decrease performance penalty of foreign keys (like in MariaDB), but they aren't created automatically, so this serves to remove that difference between PostgreSQL and MariaDB. --- classes/Confirm_address.php | 3 + classes/File_redirection.php | 3 + classes/Foreign_link.php | 4 + classes/Foreign_subscription.php | 2 + classes/Foreign_user.php | 3 + classes/Group_block.php | 4 + classes/Oauth_application.php | 4 + classes/Oauth_application_user.php | 3 + classes/Oauth_token_association.php | 3 + classes/Profile_block.php | 3 + classes/Related_group.php | 3 + classes/Remember_me.php | 3 + classes/User.php | 1 + lib/database/mysqlschema.php | 7 +- lib/database/schema.php | 40 +++++++- .../Activitypub_pending_follow_requests.php | 4 + plugins/Event/classes/Happening.php | 1 + plugins/Event/classes/RSVP.php | 5 +- .../GNUsocialProfileExtensionResponse.php | 1 + .../classes/Group_message_profile.php | 99 +++++++++---------- .../classes/Mention_url_profile.php | 3 + plugins/ModLog/classes/ModLog.php | 1 + 22 files changed, 142 insertions(+), 58 deletions(-) diff --git a/classes/Confirm_address.php b/classes/Confirm_address.php index 46af2b461b..2f92e0a59a 100644 --- a/classes/Confirm_address.php +++ b/classes/Confirm_address.php @@ -49,6 +49,9 @@ class Confirm_address extends Managed_DataObject 'foreign keys' => array( 'confirm_address_user_id_fkey' => array('user', array('user_id' => 'id')), ), + 'indexes' => array( + 'confirm_address_user_id_idx' => array('user_id'), + ), ); } diff --git a/classes/File_redirection.php b/classes/File_redirection.php index 4bbb3f1484..50c6df4bc7 100644 --- a/classes/File_redirection.php +++ b/classes/File_redirection.php @@ -52,6 +52,9 @@ class File_redirection extends Managed_DataObject 'foreign keys' => array( 'file_redirection_file_id_fkey' => array('file', array('file_id' => 'id')), ), + 'indexes' => array( + 'file_redirection_file_id_idx' => array('file_id'), + ), ); } diff --git a/classes/Foreign_link.php b/classes/Foreign_link.php index 3d0dd8ccbd..b4265f1820 100644 --- a/classes/Foreign_link.php +++ b/classes/Foreign_link.php @@ -63,6 +63,10 @@ class Foreign_link extends Managed_DataObject 'foreign_link_foreign_id_service_fkey' => array('foreign_user', array('foreign_id' => 'id', 'service' => 'service')), 'foreign_link_service_fkey' => array('foreign_service', array('service' => 'id')), ), + 'indexes' => array( + 'foreign_link_foreign_id_service_idx' => array('foreign_id', 'service'), + 'foreign_link_service_idx' => array('service'), + ), ); } diff --git a/classes/Foreign_subscription.php b/classes/Foreign_subscription.php index 32d9dff1e9..e1f14fc846 100644 --- a/classes/Foreign_subscription.php +++ b/classes/Foreign_subscription.php @@ -51,6 +51,8 @@ class Foreign_subscription extends Managed_DataObject 'foreign_subscription_subscribed_service_fkey' => array('foreign_user', array('subscribed' => 'id', 'service' => 'service')), ), 'indexes' => array( + 'foreign_subscription_subscriber_service_idx' => array('subscriber', 'service'), + 'foreign_subscription_subscribed_service_idx' => array('subscribed', 'service'), 'foreign_subscription_service_subscribed_idx' => array('service', 'subscribed'), ), ); diff --git a/classes/Foreign_user.php b/classes/Foreign_user.php index b4c6be7e08..dfe65b8c4f 100644 --- a/classes/Foreign_user.php +++ b/classes/Foreign_user.php @@ -54,6 +54,9 @@ class Foreign_user extends Managed_DataObject 'unique keys' => array( 'foreign_user_uri_key' => array('uri'), ), + 'indexes' => array( + 'foreign_user_service_idx' => array('service'), + ), ); } diff --git a/classes/Group_block.php b/classes/Group_block.php index a52c0822c7..03dac31e19 100644 --- a/classes/Group_block.php +++ b/classes/Group_block.php @@ -54,6 +54,10 @@ class Group_block extends Managed_DataObject 'group_block_blocked_fkey' => array('profile', array('blocked' => 'id')), 'group_block_blocker_fkey' => array('user', array('blocker' => 'id')), ), + 'indexes' => array( + 'group_block_blocked_idx' => array('blocked'), + 'group_block_blocker_idx' => array('blocker'), + ), ); } diff --git a/classes/Oauth_application.php b/classes/Oauth_application.php index 1ef424267d..ed838d0602 100644 --- a/classes/Oauth_application.php +++ b/classes/Oauth_application.php @@ -200,6 +200,10 @@ class Oauth_application extends Managed_DataObject 'oauth_application_owner_fkey' => array('profile', array('owner' => 'id')), // Are remote users allowed to create oauth application records? 'oauth_application_consumer_key_fkey' => array('consumer', array('consumer_key' => 'consumer_key')), ), + 'indexes' => array( + 'oauth_application_owner_idx' => array('owner'), + 'oauth_application_consumer_key_idx' => array('consumer_key'), + ), ); } } diff --git a/classes/Oauth_application_user.php b/classes/Oauth_application_user.php index 1ed8bc706c..2ca199683d 100644 --- a/classes/Oauth_application_user.php +++ b/classes/Oauth_application_user.php @@ -52,6 +52,9 @@ class Oauth_application_user extends Managed_DataObject 'oauth_application_user_profile_id_fkey' => array('profile', array('profile_id' => 'id')), 'oauth_application_user_application_id_fkey' => array('oauth_application', array('application_id' => 'id')), ), + 'indexes' => array( + 'oauth_application_user_application_id_idx' => array('application_id'), + ), ); } diff --git a/classes/Oauth_token_association.php b/classes/Oauth_token_association.php index 221acdcecd..02191d8c10 100644 --- a/classes/Oauth_token_association.php +++ b/classes/Oauth_token_association.php @@ -68,6 +68,9 @@ class Oauth_token_association extends Managed_DataObject 'oauth_token_association_profile_id_fkey' => array('profile', array('profile_id' => 'id')), 'oauth_token_association_application_id_fkey' => array('oauth_application', array('application_id' => 'id')), ), + 'indexes' => array( + 'oauth_token_association_application_id_idx' => array('application_id'), + ), ); } } diff --git a/classes/Profile_block.php b/classes/Profile_block.php index eb1ddf4d5e..d4e7c83cf2 100644 --- a/classes/Profile_block.php +++ b/classes/Profile_block.php @@ -49,6 +49,9 @@ class Profile_block extends Managed_DataObject 'profile_block_blocked_fkey' => array('profile', array('blocked' => 'id')), ), 'primary key' => array('blocker', 'blocked'), + 'indexes' => array( + 'profile_block_blocked_idx' => array('blocked'), + ), ); } diff --git a/classes/Related_group.php b/classes/Related_group.php index 7ed64b9c47..ff51e6cd20 100644 --- a/classes/Related_group.php +++ b/classes/Related_group.php @@ -47,6 +47,9 @@ class Related_group extends Managed_DataObject 'related_group_group_id_fkey' => array('user_group', array('group_id' => 'id')), 'related_group_related_group_id_fkey' => array('user_group', array('related_group_id' => 'id')), ), + 'indexes' => array( + 'related_group_related_group_id_idx' => array('related_group_id'), + ), ); } } diff --git a/classes/Remember_me.php b/classes/Remember_me.php index 20c3d66a5a..f7cbee5f58 100644 --- a/classes/Remember_me.php +++ b/classes/Remember_me.php @@ -45,6 +45,9 @@ class Remember_me extends Managed_DataObject 'foreign keys' => array( 'remember_me_user_id_fkey' => array('user', array('user_id' => 'id')), ), + 'indexes' => array( + 'remember_me_user_id_idx' => array('user_id'), + ), ); } } diff --git a/classes/User.php b/classes/User.php index 142f8ed695..0a36357d0e 100644 --- a/classes/User.php +++ b/classes/User.php @@ -102,6 +102,7 @@ class User extends Managed_DataObject 'user_carrier_fkey' => array('sms_carrier', array('carrier' => 'id')), ), 'indexes' => array( + 'user_carrier_idx' => array('carrier'), 'user_created_idx' => array('created'), 'user_smsemail_idx' => array('smsemail'), ), diff --git a/lib/database/mysqlschema.php b/lib/database/mysqlschema.php index 6a4a5f017f..105ef54512 100644 --- a/lib/database/mysqlschema.php +++ b/lib/database/mysqlschema.php @@ -259,12 +259,9 @@ class MysqlSchema extends Schema << $fkey_def) { + $fkey_cols = array_keys($fkey_def[1]); + + // A list of all keys/indices + $keys = array_values(array_merge( + ($def['unique keys'] ?? []), + ($def['indexes'] ?? []) + )); + if (array_key_exists('primary key', $def)) { + $keys[] = $def['primary key']; + } + + $indexed = false; + foreach ($keys as $key_cols) { + // Only the beginning of a key counts + $cols = array_slice($key_cols, 0, count($fkey_cols)); + + if ($cols == $fkey_cols) { + $indexed = true; + break; + } + } + + if (!$indexed) { + throw new ServerException( + "Invalid table definition for {$tableName}: " + . "foreign key {$fkey_name} is not indexed." + ); + } + } } return $def; diff --git a/plugins/ActivityPub/classes/Activitypub_pending_follow_requests.php b/plugins/ActivityPub/classes/Activitypub_pending_follow_requests.php index 80f3cae151..e168149534 100644 --- a/plugins/ActivityPub/classes/Activitypub_pending_follow_requests.php +++ b/plugins/ActivityPub/classes/Activitypub_pending_follow_requests.php @@ -60,6 +60,10 @@ class Activitypub_pending_follow_requests extends Managed_DataObject 'activitypub_pending_follow_requests_local_profile_id_fkey' => ['profile', ['local_profile_id' => 'id']], 'activitypub_pending_follow_requests_remote_profile_id_fkey' => ['profile', ['remote_profile_id' => 'id']], ], + 'indexes' => [ + 'activitypub_pending_follow_requests_local_profile_id_idx' => ['local_profile_id'], + 'activitypub_pending_follow_requests_remote_profile_id_idx' => ['remote_profile_id'], + ], ]; } diff --git a/plugins/Event/classes/Happening.php b/plugins/Event/classes/Happening.php index ecbd7f18b3..2a2c7df6c4 100644 --- a/plugins/Event/classes/Happening.php +++ b/plugins/Event/classes/Happening.php @@ -95,6 +95,7 @@ class Happening extends Managed_DataObject 'happening_uri_fkey' => array('notice', array('uri' => 'uri')) ), 'indexes' => array( + 'happening_profile_id_idx' => array('profile_id'), 'happening_created_idx' => array('created'), 'happening_start_time_end_time_idx' => array('start_time', 'end_time'), ), diff --git a/plugins/Event/classes/RSVP.php b/plugins/Event/classes/RSVP.php index 653c482bea..a3be71aff5 100644 --- a/plugins/Event/classes/RSVP.php +++ b/plugins/Event/classes/RSVP.php @@ -85,7 +85,10 @@ class RSVP extends Managed_DataObject 'rsvp_event_uri_fkey' => array('happening', array('event_uri' => 'uri')), 'rsvp_profile_id_fkey' => array('profile', array('profile_id' => 'id')) ), - 'indexes' => array('rsvp_created_idx' => array('created')), + 'indexes' => array( + 'rsvp_event_uri_idx' => array('event_uri'), + 'rsvp_created_idx' => array('created'), + ), ); } diff --git a/plugins/ExtendedProfile/classes/GNUsocialProfileExtensionResponse.php b/plugins/ExtendedProfile/classes/GNUsocialProfileExtensionResponse.php index 5f7ed6004e..36e8b81c6d 100644 --- a/plugins/ExtendedProfile/classes/GNUsocialProfileExtensionResponse.php +++ b/plugins/ExtendedProfile/classes/GNUsocialProfileExtensionResponse.php @@ -55,6 +55,7 @@ class GNUsocialProfileExtensionResponse extends Managed_DataObject 'gnusocialprofileextensionresponse_extension_id_fkey' => ['gnusocialprofileextensionfield', ['extension_id' => 'id']], ], 'indexes' => [ + 'gnusocialprofileextensionresponse_profile_id_idx' => ['profile_id'], 'gnusocialprofileextensionresponse_extension_id_idx' => ['extension_id'], ], ]; diff --git a/plugins/GroupPrivateMessage/classes/Group_message_profile.php b/plugins/GroupPrivateMessage/classes/Group_message_profile.php index ad465b96ea..434ad2e8a2 100644 --- a/plugins/GroupPrivateMessage/classes/Group_message_profile.php +++ b/plugins/GroupPrivateMessage/classes/Group_message_profile.php @@ -1,48 +1,42 @@ . + /** * Who received a group message * - * PHP version 5 - * - * @category Data - * @package StatusNet - * @author Evan Prodromou - * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 - * @link http://status.net/ - * - * StatusNet - the distributed open-source microblogging tool - * Copyright (C) 2011, StatusNet, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . + * @category Data + * @package GNUsocial + * @author Evan Prodromou + * @copyright 2011 StatusNet, Inc. + * @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later */ -if (!defined('STATUSNET')) { - exit(1); -} +defined('GNUSOCIAL') || die(); require_once INSTALLDIR . '/classes/Memcached_DataObject.php'; /** * Data class for group direct messages for users * - * @category GroupPrivateMessage - * @package StatusNet - * @author Evan Prodromou - * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 - * @link http://status.net/ + * @category GroupPrivateMessage + * @package GNUsocial + * @author Evan Prodromou + * @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later * - * @see DB_DataObject + * @see DB_DataObject */ class Group_message_profile extends Managed_DataObject { @@ -66,10 +60,13 @@ class Group_message_profile extends Managed_DataObject 'group_message_profile_to_profile_fkey' => array('profile', array('to_profile' => 'id')), 'group_message_profile_group_message_id_fkey' => array('group_message', array('group_message_id' => 'id')), ), + 'indexes' => array( + 'group_message_profile_group_message_id_idx' => array('group_message_id'), + ), ); } - function send($gm, $profile) + public function send($gm, $profile) { $gmp = new Group_message_profile(); @@ -87,13 +84,13 @@ class Group_message_profile extends Managed_DataObject return $gmp; } - function notify() + public function notify() { // XXX: add more here $this->notifyByMail(); } - function notifyByMail() + public function notifyByMail() { $to = User::getKV('id', $this->to_profile); @@ -117,21 +114,23 @@ class Group_message_profile extends Managed_DataObject // TRANS: %1$s is the sending user's long name, %2$s is the sending user's nickname, // TRANS: %3$s is the message content, %4$s a URL to the message, // TRANS: %5$s is the StatusNet sitename. - $body = sprintf(_m("%1\$s (%2\$s) sent a private message to group %3\$s:\n\n". - "------------------------------------------------------\n". - "%4\$s\n". - "------------------------------------------------------\n\n". - "You can reply to their message here:\n\n". - "%5\$s\n\n". - "Do not reply to this email; it will not get to them.\n\n". - "With kind regards,\n". - "%6\$s"), - $from_profile->getBestName(), - $from_profile->nickname, - $group->nickname, - $gm->content, - common_local_url('newmessage', array('to' => $from_profile->id)), - common_config('site', 'name')) . "\n"; + $body = sprintf( + _m("%1\$s (%2\$s) sent a private message to group %3\$s:\n\n" + . "------------------------------------------------------\n" + . "%4\$s\n" + . "------------------------------------------------------\n\n" + . "You can reply to their message here:\n\n" + . "%5\$s\n\n" + . "Do not reply to this email; it will not get to them.\n\n" + . "With kind regards,\n" + . "%6\$s"), + $from_profile->getBestName(), + $from_profile->nickname, + $group->nickname, + $gm->content, + common_local_url('newmessage', ['to' => $from_profile->id]), + common_config('site', 'name') + ) . "\n"; $headers = _mail_prepare_headers('message', $to->nickname, $from_profile->nickname); diff --git a/plugins/MentionURL/classes/Mention_url_profile.php b/plugins/MentionURL/classes/Mention_url_profile.php index 44c36a0362..b04d24ce42 100644 --- a/plugins/MentionURL/classes/Mention_url_profile.php +++ b/plugins/MentionURL/classes/Mention_url_profile.php @@ -37,6 +37,9 @@ class Mention_url_profile extends Managed_DataObject 'foreign keys' => array( 'mention_url_profile_profile_id_fkey' => array('profile', array('profile_id' => 'id')), ), + 'indexes' => array( + 'mention_url_profile_profile_id_idx' => array('profile_id'), + ), ); } diff --git a/plugins/ModLog/classes/ModLog.php b/plugins/ModLog/classes/ModLog.php index 0c61f488d3..c8ce036c7f 100644 --- a/plugins/ModLog/classes/ModLog.php +++ b/plugins/ModLog/classes/ModLog.php @@ -90,6 +90,7 @@ class ModLog extends Managed_DataObject ], 'indexes' => [ 'modlog_profile_id_created_idx' => ['profile_id', 'created'], + 'modlog_moderator_id_idx' => ['moderator_id'], ], ]; }