Merge tag 'v3.4.0' into hometown-dev
This commit is contained in:
@ -1,4 +1,4 @@
|
||||
class AddUrlToStatuses < ActiveRecord::Migration[4.2]
|
||||
class AddURLToStatuses < ActiveRecord::Migration[4.2]
|
||||
def change
|
||||
add_column :statuses, :url, :string, null: true, default: nil
|
||||
end
|
||||
|
@ -1,4 +1,4 @@
|
||||
class AddUrlToAccounts < ActiveRecord::Migration[4.2]
|
||||
class AddURLToAccounts < ActiveRecord::Migration[4.2]
|
||||
def change
|
||||
add_column :accounts, :url, :string, null: true, default: nil
|
||||
end
|
||||
|
@ -1,4 +1,4 @@
|
||||
class AddAvatarRemoteUrlToAccounts < ActiveRecord::Migration[4.2]
|
||||
class AddAvatarRemoteURLToAccounts < ActiveRecord::Migration[4.2]
|
||||
def change
|
||||
add_column :accounts, :avatar_remote_url, :string, null: true, default: nil
|
||||
end
|
||||
|
@ -7,12 +7,12 @@ end
|
||||
class RailsSettingsMigration < MIGRATION_BASE_CLASS
|
||||
def self.up
|
||||
create_table :settings do |t|
|
||||
t.string :var, :null => false
|
||||
t.string :var, null: false
|
||||
t.text :value
|
||||
t.references :target, :null => false, :polymorphic => true
|
||||
t.timestamps :null => true
|
||||
t.references :target, null: false, polymorphic: true, index: { name: 'index_settings_on_target_type_and_target_id' }
|
||||
t.timestamps null: true
|
||||
end
|
||||
add_index :settings, [ :target_type, :target_id, :var ], :unique => true
|
||||
add_index :settings, [ :target_type, :target_id, :var ], unique: true
|
||||
end
|
||||
|
||||
def self.down
|
||||
|
@ -1,4 +1,4 @@
|
||||
class AddHeaderRemoteUrlToAccounts < ActiveRecord::Migration[5.0]
|
||||
class AddHeaderRemoteURLToAccounts < ActiveRecord::Migration[5.0]
|
||||
def change
|
||||
add_column :accounts, :header_remote_url, :string, null: false, default: ''
|
||||
end
|
||||
|
@ -1,7 +1,7 @@
|
||||
class StatusIdsToTimestampIds < ActiveRecord::Migration[5.1]
|
||||
def up
|
||||
# Prepare the function we will use to generate IDs.
|
||||
Rake::Task['db:define_timestamp_id'].execute
|
||||
Mastodon::Snowflake.define_timestamp_id
|
||||
|
||||
# Set up the statuses.id column to use our timestamp-based IDs.
|
||||
ActiveRecord::Base.connection.execute(<<~SQL)
|
||||
@ -11,7 +11,7 @@ class StatusIdsToTimestampIds < ActiveRecord::Migration[5.1]
|
||||
SQL
|
||||
|
||||
# Make sure we have a sequence to use.
|
||||
Rake::Task['db:ensure_id_sequences_exist'].execute
|
||||
Mastodon::Snowflake.ensure_id_sequences_exist
|
||||
end
|
||||
|
||||
def down
|
||||
|
@ -3,7 +3,7 @@ class CreateAdminActionLogs < ActiveRecord::Migration[5.1]
|
||||
create_table :admin_action_logs do |t|
|
||||
t.belongs_to :account, foreign_key: { on_delete: :cascade }
|
||||
t.string :action, null: false, default: ''
|
||||
t.references :target, polymorphic: true
|
||||
t.references :target, polymorphic: true, index: { name: 'index_admin_action_logs_on_target_type_and_target_id' }
|
||||
t.text :recorded_changes, null: false, default: ''
|
||||
|
||||
t.timestamps
|
||||
|
@ -1,6 +1,6 @@
|
||||
require Rails.root.join('lib', 'mastodon', 'migration_helpers')
|
||||
|
||||
class AddEmbedUrlToPreviewCards < ActiveRecord::Migration[5.1]
|
||||
class AddEmbedURLToPreviewCards < ActiveRecord::Migration[5.1]
|
||||
include Mastodon::MigrationHelpers
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
@ -1,4 +1,4 @@
|
||||
class AddFeaturedCollectionUrlToAccounts < ActiveRecord::Migration[5.1]
|
||||
class AddFeaturedCollectionURLToAccounts < ActiveRecord::Migration[5.1]
|
||||
def change
|
||||
add_column :accounts, :featured_collection_url, :string
|
||||
end
|
||||
|
@ -37,7 +37,7 @@ class FixAccountsUniqueIndex < ActiveRecord::Migration[5.2]
|
||||
end
|
||||
end
|
||||
|
||||
duplicates = Account.connection.select_all('SELECT string_agg(id::text, \',\') AS ids FROM accounts GROUP BY lower(username), lower(domain) HAVING count(*) > 1').to_hash
|
||||
duplicates = Account.connection.select_all('SELECT string_agg(id::text, \',\') AS ids FROM accounts GROUP BY lower(username), lower(domain) HAVING count(*) > 1').to_ary
|
||||
|
||||
duplicates.each do |row|
|
||||
deduplicate_account!(row['ids'].split(','))
|
||||
|
@ -17,8 +17,8 @@ class MigrateAccountConversations < ActiveRecord::Migration[5.2]
|
||||
belongs_to :account, optional: true
|
||||
belongs_to :activity, polymorphic: true, optional: true
|
||||
|
||||
belongs_to :status, foreign_type: 'Status', foreign_key: 'activity_id', optional: true
|
||||
belongs_to :mention, foreign_type: 'Mention', foreign_key: 'activity_id', optional: true
|
||||
belongs_to :status, foreign_key: 'activity_id', optional: true
|
||||
belongs_to :mention, foreign_key: 'activity_id', optional: true
|
||||
|
||||
def target_status
|
||||
mention&.status
|
||||
|
@ -2,7 +2,7 @@ class DowncaseCustomEmojiDomains < ActiveRecord::Migration[5.2]
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
duplicates = CustomEmoji.connection.select_all('SELECT string_agg(id::text, \',\') AS ids FROM custom_emojis GROUP BY shortcode, lower(domain) HAVING count(*) > 1').to_hash
|
||||
duplicates = CustomEmoji.connection.select_all('SELECT string_agg(id::text, \',\') AS ids FROM custom_emojis GROUP BY shortcode, lower(domain) HAVING count(*) > 1').to_ary
|
||||
|
||||
duplicates.each do |row|
|
||||
CustomEmoji.where(id: row['ids'].split(',')[0...-1]).destroy_all
|
||||
|
@ -2,7 +2,7 @@ class AddCaseInsensitiveIndexToTags < ActiveRecord::Migration[5.2]
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
Tag.connection.select_all('SELECT string_agg(id::text, \',\') AS ids FROM tags GROUP BY lower(name) HAVING count(*) > 1').to_hash.each do |row|
|
||||
Tag.connection.select_all('SELECT string_agg(id::text, \',\') AS ids FROM tags GROUP BY lower(name) HAVING count(*) > 1').to_ary.each do |row|
|
||||
canonical_tag_id = row['ids'].split(',').first
|
||||
redundant_tag_ids = row['ids'].split(',')[1..-1]
|
||||
|
||||
|
@ -5,7 +5,7 @@ class ResetUniqueJobsLocks < ActiveRecord::Migration[5.2]
|
||||
# We do this to clean up unique job digests that were not properly
|
||||
# disposed of prior to https://github.com/tootsuite/mastodon/pull/13361
|
||||
|
||||
SidekiqUniqueJobs::Digests.delete_by_pattern('*', count: SidekiqUniqueJobs::Digests.count)
|
||||
until SidekiqUniqueJobs::Digests.new.delete_by_pattern('*').nil?; end
|
||||
end
|
||||
|
||||
def down; end
|
||||
|
@ -1,4 +1,4 @@
|
||||
class AddDevicesUrlToAccounts < ActiveRecord::Migration[5.2]
|
||||
class AddDevicesURLToAccounts < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
add_column :accounts, :devices_url, :string
|
||||
end
|
||||
|
11
db/migrate/20210221045109_create_rules.rb
Normal file
11
db/migrate/20210221045109_create_rules.rb
Normal file
@ -0,0 +1,11 @@
|
||||
class CreateRules < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
create_table :rules do |t|
|
||||
t.integer :priority, null: false, default: 0
|
||||
t.datetime :deleted_at
|
||||
t.text :text, null: false, default: ''
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
17
db/migrate/20210306164523_account_ids_to_timestamp_ids.rb
Normal file
17
db/migrate/20210306164523_account_ids_to_timestamp_ids.rb
Normal file
@ -0,0 +1,17 @@
|
||||
class AccountIdsToTimestampIds < ActiveRecord::Migration[5.1]
|
||||
def up
|
||||
# Set up the accounts.id column to use our timestamp-based IDs.
|
||||
safety_assured do
|
||||
execute("ALTER TABLE accounts ALTER COLUMN id SET DEFAULT timestamp_id('accounts')")
|
||||
end
|
||||
|
||||
# Make sure we have a sequence to use.
|
||||
Mastodon::Snowflake.ensure_id_sequences_exist
|
||||
end
|
||||
|
||||
def down
|
||||
execute("LOCK accounts")
|
||||
execute("SELECT setval('accounts_id_seq', (SELECT MAX(id) FROM accounts))")
|
||||
execute("ALTER TABLE accounts ALTER COLUMN id SET DEFAULT nextval('accounts_id_seq')")
|
||||
end
|
||||
end
|
9
db/migrate/20210322164601_create_account_summaries.rb
Normal file
9
db/migrate/20210322164601_create_account_summaries.rb
Normal file
@ -0,0 +1,9 @@
|
||||
class CreateAccountSummaries < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
create_view :account_summaries, materialized: { no_data: true }
|
||||
|
||||
# To be able to refresh the view concurrently,
|
||||
# at least one unique index is required
|
||||
safety_assured { add_index :account_summaries, :account_id, unique: true }
|
||||
end
|
||||
end
|
@ -0,0 +1,5 @@
|
||||
class CreateFollowRecommendations < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
create_view :follow_recommendations
|
||||
end
|
||||
end
|
@ -0,0 +1,9 @@
|
||||
class CreateFollowRecommendationSuppressions < ActiveRecord::Migration[6.1]
|
||||
def change
|
||||
create_table :follow_recommendation_suppressions do |t|
|
||||
t.references :account, null: false, foreign_key: { on_delete: :cascade }, index: { unique: true }
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
10
db/migrate/20210416200740_create_canonical_email_blocks.rb
Normal file
10
db/migrate/20210416200740_create_canonical_email_blocks.rb
Normal file
@ -0,0 +1,10 @@
|
||||
class CreateCanonicalEmailBlocks < ActiveRecord::Migration[6.1]
|
||||
def change
|
||||
create_table :canonical_email_blocks do |t|
|
||||
t.string :canonical_email_hash, null: false, default: '', index: { unique: true }
|
||||
t.belongs_to :reference_account, null: false, foreign_key: { on_cascade: :delete, to_table: 'accounts' }
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
@ -0,0 +1,13 @@
|
||||
class AddCaseInsensitiveBtreeIndexToTags < ActiveRecord::Migration[5.2]
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
safety_assured { execute 'CREATE UNIQUE INDEX CONCURRENTLY index_tags_on_name_lower_btree ON tags (lower(name) text_pattern_ops)' }
|
||||
remove_index :tags, name: 'index_tags_on_name_lower'
|
||||
end
|
||||
|
||||
def down
|
||||
safety_assured { execute 'CREATE UNIQUE INDEX CONCURRENTLY index_tags_on_name_lower ON tags (lower(name))' }
|
||||
remove_index :tags, name: 'index_tags_on_name_lower_btree'
|
||||
end
|
||||
end
|
@ -0,0 +1,13 @@
|
||||
class AddIndexOnMediaAttachmentsAccountIdStatusId < ActiveRecord::Migration[5.2]
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
add_index :media_attachments, [:account_id, :status_id], order: { status_id: :desc }, algorithm: :concurrently
|
||||
remove_index :media_attachments, :account_id, algorithm: :concurrently
|
||||
end
|
||||
|
||||
def down
|
||||
add_index :media_attachments, :account_id, algorithm: :concurrently
|
||||
remove_index :media_attachments, [:account_id, :status_id], order: { status_id: :desc }, algorithm: :concurrently
|
||||
end
|
||||
end
|
@ -0,0 +1,18 @@
|
||||
class UpdateFollowRecommendationsToVersion2 < ActiveRecord::Migration[6.1]
|
||||
# We're switching from a normal to a materialized view so we need
|
||||
# custom `up` and `down` paths.
|
||||
|
||||
def up
|
||||
drop_view :follow_recommendations
|
||||
create_view :follow_recommendations, version: 2, materialized: { no_data: true }
|
||||
|
||||
# To be able to refresh the view concurrently,
|
||||
# at least one unique index is required
|
||||
safety_assured { add_index :follow_recommendations, :account_id, unique: true }
|
||||
end
|
||||
|
||||
def down
|
||||
drop_view :follow_recommendations, materialized: true
|
||||
create_view :follow_recommendations, version: 1
|
||||
end
|
||||
end
|
@ -0,0 +1,7 @@
|
||||
class RemoveSubscriptionExpiresAtFromAccounts < ActiveRecord::Migration[5.0]
|
||||
def change
|
||||
safety_assured do
|
||||
remove_column :accounts, :subscription_expires_at, :datetime, null: true, default: nil
|
||||
end
|
||||
end
|
||||
end
|
13
db/post_migrate/20210502233513_drop_account_tag_stats.rb
Normal file
13
db/post_migrate/20210502233513_drop_account_tag_stats.rb
Normal file
@ -0,0 +1,13 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class DropAccountTagStats < ActiveRecord::Migration[5.2]
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
drop_table :account_tag_stats
|
||||
end
|
||||
|
||||
def down
|
||||
raise ActiveRecord::IrreversibleMigration
|
||||
end
|
||||
end
|
@ -0,0 +1,12 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class RemoveHubURLFromAccounts < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
safety_assured do
|
||||
remove_column :accounts, :secret, :string, null: false, default: ''
|
||||
remove_column :accounts, :remote_url, :string, null: false, default: ''
|
||||
remove_column :accounts, :salmon_url, :string, null: false, default: ''
|
||||
remove_column :accounts, :hub_url, :string, null: false, default: ''
|
||||
end
|
||||
end
|
||||
end
|
106
db/schema.rb
106
db/schema.rb
@ -2,15 +2,15 @@
|
||||
# of editing this file, please use the migrations feature of Active Record to
|
||||
# incrementally modify your database, and then regenerate this schema definition.
|
||||
#
|
||||
# Note that this schema.rb definition is the authoritative source for your
|
||||
# database schema. If you need to create the application database on another
|
||||
# system, you should be using db:schema:load, not running all the migrations
|
||||
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
|
||||
# you'll amass, the slower it'll run and the greater likelihood for issues).
|
||||
# This file is the source Rails uses to define your schema when running `bin/rails
|
||||
# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
|
||||
# be faster and is potentially less error prone than running all of your
|
||||
# migrations from scratch. Old migrations may fail to apply correctly if those
|
||||
# migrations use external dependencies or application code.
|
||||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 2020_12_18_054746) do
|
||||
ActiveRecord::Schema.define(version: 2021_05_07_001928) do
|
||||
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
@ -115,15 +115,6 @@ ActiveRecord::Schema.define(version: 2020_12_18_054746) do
|
||||
t.index ["account_id"], name: "index_account_stats_on_account_id", unique: true
|
||||
end
|
||||
|
||||
create_table "account_tag_stats", force: :cascade do |t|
|
||||
t.bigint "tag_id", null: false
|
||||
t.bigint "accounts_count", default: 0, null: false
|
||||
t.boolean "hidden", default: false, null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.index ["tag_id"], name: "index_account_tag_stats_on_tag_id", unique: true
|
||||
end
|
||||
|
||||
create_table "account_warning_presets", force: :cascade do |t|
|
||||
t.text "text", default: "", null: false
|
||||
t.datetime "created_at", null: false
|
||||
@ -142,15 +133,11 @@ ActiveRecord::Schema.define(version: 2020_12_18_054746) do
|
||||
t.index ["target_account_id"], name: "index_account_warnings_on_target_account_id"
|
||||
end
|
||||
|
||||
create_table "accounts", force: :cascade do |t|
|
||||
create_table "accounts", id: :bigint, default: -> { "timestamp_id('accounts'::text)" }, force: :cascade do |t|
|
||||
t.string "username", default: "", null: false
|
||||
t.string "domain"
|
||||
t.string "secret", default: "", null: false
|
||||
t.text "private_key"
|
||||
t.text "public_key", default: "", null: false
|
||||
t.string "remote_url", default: "", null: false
|
||||
t.string "salmon_url", default: "", null: false
|
||||
t.string "hub_url", default: "", null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.text "note", default: "", null: false
|
||||
@ -166,7 +153,6 @@ ActiveRecord::Schema.define(version: 2020_12_18_054746) do
|
||||
t.integer "header_file_size"
|
||||
t.datetime "header_updated_at"
|
||||
t.string "avatar_remote_url"
|
||||
t.datetime "subscription_expires_at"
|
||||
t.boolean "locked", default: false, null: false
|
||||
t.string "header_remote_url", default: "", null: false
|
||||
t.datetime "last_webfingered_at"
|
||||
@ -281,6 +267,15 @@ ActiveRecord::Schema.define(version: 2020_12_18_054746) do
|
||||
t.index ["status_id"], name: "index_bookmarks_on_status_id"
|
||||
end
|
||||
|
||||
create_table "canonical_email_blocks", force: :cascade do |t|
|
||||
t.string "canonical_email_hash", default: "", null: false
|
||||
t.bigint "reference_account_id", null: false
|
||||
t.datetime "created_at", precision: 6, null: false
|
||||
t.datetime "updated_at", precision: 6, null: false
|
||||
t.index ["canonical_email_hash"], name: "index_canonical_email_blocks_on_canonical_email_hash", unique: true
|
||||
t.index ["reference_account_id"], name: "index_canonical_email_blocks_on_reference_account_id"
|
||||
end
|
||||
|
||||
create_table "conversation_mutes", force: :cascade do |t|
|
||||
t.bigint "conversation_id", null: false
|
||||
t.bigint "account_id", null: false
|
||||
@ -407,6 +402,13 @@ ActiveRecord::Schema.define(version: 2020_12_18_054746) do
|
||||
t.index ["tag_id"], name: "index_featured_tags_on_tag_id"
|
||||
end
|
||||
|
||||
create_table "follow_recommendation_suppressions", force: :cascade do |t|
|
||||
t.bigint "account_id", null: false
|
||||
t.datetime "created_at", precision: 6, null: false
|
||||
t.datetime "updated_at", precision: 6, null: false
|
||||
t.index ["account_id"], name: "index_follow_recommendation_suppressions_on_account_id", unique: true
|
||||
end
|
||||
|
||||
create_table "follow_requests", force: :cascade do |t|
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
@ -527,7 +529,7 @@ ActiveRecord::Schema.define(version: 2020_12_18_054746) do
|
||||
t.integer "thumbnail_file_size"
|
||||
t.datetime "thumbnail_updated_at"
|
||||
t.string "thumbnail_remote_url"
|
||||
t.index ["account_id"], name: "index_media_attachments_on_account_id"
|
||||
t.index ["account_id", "status_id"], name: "index_media_attachments_on_account_id_and_status_id", order: { status_id: :desc }
|
||||
t.index ["scheduled_status_id"], name: "index_media_attachments_on_scheduled_status_id"
|
||||
t.index ["shortcode"], name: "index_media_attachments_on_shortcode", unique: true
|
||||
t.index ["status_id"], name: "index_media_attachments_on_status_id"
|
||||
@ -724,6 +726,14 @@ ActiveRecord::Schema.define(version: 2020_12_18_054746) do
|
||||
t.index ["target_account_id"], name: "index_reports_on_target_account_id"
|
||||
end
|
||||
|
||||
create_table "rules", force: :cascade do |t|
|
||||
t.integer "priority", default: 0, null: false
|
||||
t.datetime "deleted_at"
|
||||
t.text "text", default: "", null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
create_table "scheduled_statuses", force: :cascade do |t|
|
||||
t.bigint "account_id"
|
||||
t.datetime "scheduled_at"
|
||||
@ -842,7 +852,7 @@ ActiveRecord::Schema.define(version: 2020_12_18_054746) do
|
||||
t.datetime "last_status_at"
|
||||
t.float "max_score"
|
||||
t.datetime "max_score_at"
|
||||
t.index "lower((name)::text)", name: "index_tags_on_name_lower", unique: true
|
||||
t.index "lower((name)::text) text_pattern_ops", name: "index_tags_on_name_lower_btree", unique: true
|
||||
end
|
||||
|
||||
create_table "tombstones", force: :cascade do |t|
|
||||
@ -965,7 +975,6 @@ ActiveRecord::Schema.define(version: 2020_12_18_054746) do
|
||||
add_foreign_key "account_pins", "accounts", column: "target_account_id", on_delete: :cascade
|
||||
add_foreign_key "account_pins", "accounts", on_delete: :cascade
|
||||
add_foreign_key "account_stats", "accounts", on_delete: :cascade
|
||||
add_foreign_key "account_tag_stats", "tags", on_delete: :cascade
|
||||
add_foreign_key "account_warnings", "accounts", column: "target_account_id", on_delete: :cascade
|
||||
add_foreign_key "account_warnings", "accounts", on_delete: :nullify
|
||||
add_foreign_key "accounts", "accounts", column: "moved_to_account_id", on_delete: :nullify
|
||||
@ -980,6 +989,7 @@ ActiveRecord::Schema.define(version: 2020_12_18_054746) do
|
||||
add_foreign_key "blocks", "accounts", name: "fk_4269e03e65", on_delete: :cascade
|
||||
add_foreign_key "bookmarks", "accounts", on_delete: :cascade
|
||||
add_foreign_key "bookmarks", "statuses", on_delete: :cascade
|
||||
add_foreign_key "canonical_email_blocks", "accounts", column: "reference_account_id"
|
||||
add_foreign_key "conversation_mutes", "accounts", name: "fk_225b4212bb", on_delete: :cascade
|
||||
add_foreign_key "conversation_mutes", "conversations", on_delete: :cascade
|
||||
add_foreign_key "custom_filters", "accounts", on_delete: :cascade
|
||||
@ -992,6 +1002,7 @@ ActiveRecord::Schema.define(version: 2020_12_18_054746) do
|
||||
add_foreign_key "favourites", "statuses", name: "fk_b0e856845e", on_delete: :cascade
|
||||
add_foreign_key "featured_tags", "accounts", on_delete: :cascade
|
||||
add_foreign_key "featured_tags", "tags", on_delete: :cascade
|
||||
add_foreign_key "follow_recommendation_suppressions", "accounts", on_delete: :cascade
|
||||
add_foreign_key "follow_requests", "accounts", column: "target_account_id", name: "fk_9291ec025d", on_delete: :cascade
|
||||
add_foreign_key "follow_requests", "accounts", name: "fk_76d644b0e7", on_delete: :cascade
|
||||
add_foreign_key "follows", "accounts", column: "target_account_id", name: "fk_745ca29eac", on_delete: :cascade
|
||||
@ -1075,4 +1086,51 @@ ActiveRecord::Schema.define(version: 2020_12_18_054746) do
|
||||
SQL
|
||||
add_index "instances", ["domain"], name: "index_instances_on_domain", unique: true
|
||||
|
||||
create_view "account_summaries", materialized: true, sql_definition: <<-SQL
|
||||
SELECT accounts.id AS account_id,
|
||||
mode() WITHIN GROUP (ORDER BY t0.language) AS language,
|
||||
mode() WITHIN GROUP (ORDER BY t0.sensitive) AS sensitive
|
||||
FROM (accounts
|
||||
CROSS JOIN LATERAL ( SELECT statuses.account_id,
|
||||
statuses.language,
|
||||
statuses.sensitive
|
||||
FROM statuses
|
||||
WHERE ((statuses.account_id = accounts.id) AND (statuses.deleted_at IS NULL))
|
||||
ORDER BY statuses.id DESC
|
||||
LIMIT 20) t0)
|
||||
WHERE ((accounts.suspended_at IS NULL) AND (accounts.silenced_at IS NULL) AND (accounts.moved_to_account_id IS NULL) AND (accounts.discoverable = true) AND (accounts.locked = false))
|
||||
GROUP BY accounts.id;
|
||||
SQL
|
||||
add_index "account_summaries", ["account_id"], name: "index_account_summaries_on_account_id", unique: true
|
||||
|
||||
create_view "follow_recommendations", materialized: true, sql_definition: <<-SQL
|
||||
SELECT t0.account_id,
|
||||
sum(t0.rank) AS rank,
|
||||
array_agg(t0.reason) AS reason
|
||||
FROM ( SELECT account_summaries.account_id,
|
||||
((count(follows.id))::numeric / (1.0 + (count(follows.id))::numeric)) AS rank,
|
||||
'most_followed'::text AS reason
|
||||
FROM (((follows
|
||||
JOIN account_summaries ON ((account_summaries.account_id = follows.target_account_id)))
|
||||
JOIN users ON ((users.account_id = follows.account_id)))
|
||||
LEFT JOIN follow_recommendation_suppressions ON ((follow_recommendation_suppressions.account_id = follows.target_account_id)))
|
||||
WHERE ((users.current_sign_in_at >= (now() - 'P30D'::interval)) AND (account_summaries.sensitive = false) AND (follow_recommendation_suppressions.id IS NULL))
|
||||
GROUP BY account_summaries.account_id
|
||||
HAVING (count(follows.id) >= 5)
|
||||
UNION ALL
|
||||
SELECT account_summaries.account_id,
|
||||
(sum((status_stats.reblogs_count + status_stats.favourites_count)) / (1.0 + sum((status_stats.reblogs_count + status_stats.favourites_count)))) AS rank,
|
||||
'most_interactions'::text AS reason
|
||||
FROM (((status_stats
|
||||
JOIN statuses ON ((statuses.id = status_stats.status_id)))
|
||||
JOIN account_summaries ON ((account_summaries.account_id = statuses.account_id)))
|
||||
LEFT JOIN follow_recommendation_suppressions ON ((follow_recommendation_suppressions.account_id = statuses.account_id)))
|
||||
WHERE ((statuses.id >= (((date_part('epoch'::text, (now() - 'P30D'::interval)) * (1000)::double precision))::bigint << 16)) AND (account_summaries.sensitive = false) AND (follow_recommendation_suppressions.id IS NULL))
|
||||
GROUP BY account_summaries.account_id
|
||||
HAVING (sum((status_stats.reblogs_count + status_stats.favourites_count)) >= (5)::numeric)) t0
|
||||
GROUP BY t0.account_id
|
||||
ORDER BY (sum(t0.rank)) DESC;
|
||||
SQL
|
||||
add_index "follow_recommendations", ["account_id"], name: "index_follow_recommendations_on_account_id", unique: true
|
||||
|
||||
end
|
||||
|
22
db/views/account_summaries_v01.sql
Normal file
22
db/views/account_summaries_v01.sql
Normal file
@ -0,0 +1,22 @@
|
||||
SELECT
|
||||
accounts.id AS account_id,
|
||||
mode() WITHIN GROUP (ORDER BY language ASC) AS language,
|
||||
mode() WITHIN GROUP (ORDER BY sensitive ASC) AS sensitive
|
||||
FROM accounts
|
||||
CROSS JOIN LATERAL (
|
||||
SELECT
|
||||
statuses.account_id,
|
||||
statuses.language,
|
||||
statuses.sensitive
|
||||
FROM statuses
|
||||
WHERE statuses.account_id = accounts.id
|
||||
AND statuses.deleted_at IS NULL
|
||||
ORDER BY statuses.id DESC
|
||||
LIMIT 20
|
||||
) t0
|
||||
WHERE accounts.suspended_at IS NULL
|
||||
AND accounts.silenced_at IS NULL
|
||||
AND accounts.moved_to_account_id IS NULL
|
||||
AND accounts.discoverable = 't'
|
||||
AND accounts.locked = 'f'
|
||||
GROUP BY accounts.id
|
38
db/views/follow_recommendations_v01.sql
Normal file
38
db/views/follow_recommendations_v01.sql
Normal file
@ -0,0 +1,38 @@
|
||||
SELECT
|
||||
account_id,
|
||||
sum(rank) AS rank,
|
||||
array_agg(reason) AS reason
|
||||
FROM (
|
||||
SELECT
|
||||
accounts.id AS account_id,
|
||||
count(follows.id) / (1.0 + count(follows.id)) AS rank,
|
||||
'most_followed' AS reason
|
||||
FROM follows
|
||||
INNER JOIN accounts ON accounts.id = follows.target_account_id
|
||||
INNER JOIN users ON users.account_id = follows.account_id
|
||||
WHERE users.current_sign_in_at >= (now() - interval '30 days')
|
||||
AND accounts.suspended_at IS NULL
|
||||
AND accounts.moved_to_account_id IS NULL
|
||||
AND accounts.silenced_at IS NULL
|
||||
AND accounts.locked = 'f'
|
||||
AND accounts.discoverable = 't'
|
||||
GROUP BY accounts.id
|
||||
HAVING count(follows.id) >= 5
|
||||
UNION ALL
|
||||
SELECT accounts.id AS account_id,
|
||||
sum(reblogs_count + favourites_count) / (1.0 + sum(reblogs_count + favourites_count)) AS rank,
|
||||
'most_interactions' AS reason
|
||||
FROM status_stats
|
||||
INNER JOIN statuses ON statuses.id = status_stats.status_id
|
||||
INNER JOIN accounts ON accounts.id = statuses.account_id
|
||||
WHERE statuses.id >= ((date_part('epoch', now() - interval '30 days') * 1000)::bigint << 16)
|
||||
AND accounts.suspended_at IS NULL
|
||||
AND accounts.moved_to_account_id IS NULL
|
||||
AND accounts.silenced_at IS NULL
|
||||
AND accounts.locked = 'f'
|
||||
AND accounts.discoverable = 't'
|
||||
GROUP BY accounts.id
|
||||
HAVING sum(reblogs_count + favourites_count) >= 5
|
||||
) t0
|
||||
GROUP BY account_id
|
||||
ORDER BY rank DESC
|
34
db/views/follow_recommendations_v02.sql
Normal file
34
db/views/follow_recommendations_v02.sql
Normal file
@ -0,0 +1,34 @@
|
||||
SELECT
|
||||
account_id,
|
||||
sum(rank) AS rank,
|
||||
array_agg(reason) AS reason
|
||||
FROM (
|
||||
SELECT
|
||||
account_summaries.account_id AS account_id,
|
||||
count(follows.id) / (1.0 + count(follows.id)) AS rank,
|
||||
'most_followed' AS reason
|
||||
FROM follows
|
||||
INNER JOIN account_summaries ON account_summaries.account_id = follows.target_account_id
|
||||
INNER JOIN users ON users.account_id = follows.account_id
|
||||
LEFT OUTER JOIN follow_recommendation_suppressions ON follow_recommendation_suppressions.account_id = follows.target_account_id
|
||||
WHERE users.current_sign_in_at >= (now() - interval '30 days')
|
||||
AND account_summaries.sensitive = 'f'
|
||||
AND follow_recommendation_suppressions.id IS NULL
|
||||
GROUP BY account_summaries.account_id
|
||||
HAVING count(follows.id) >= 5
|
||||
UNION ALL
|
||||
SELECT account_summaries.account_id AS account_id,
|
||||
sum(reblogs_count + favourites_count) / (1.0 + sum(reblogs_count + favourites_count)) AS rank,
|
||||
'most_interactions' AS reason
|
||||
FROM status_stats
|
||||
INNER JOIN statuses ON statuses.id = status_stats.status_id
|
||||
INNER JOIN account_summaries ON account_summaries.account_id = statuses.account_id
|
||||
LEFT OUTER JOIN follow_recommendation_suppressions ON follow_recommendation_suppressions.account_id = statuses.account_id
|
||||
WHERE statuses.id >= ((date_part('epoch', now() - interval '30 days') * 1000)::bigint << 16)
|
||||
AND account_summaries.sensitive = 'f'
|
||||
AND follow_recommendation_suppressions.id IS NULL
|
||||
GROUP BY account_summaries.account_id
|
||||
HAVING sum(reblogs_count + favourites_count) >= 5
|
||||
) t0
|
||||
GROUP BY account_id
|
||||
ORDER BY rank DESC
|
Reference in New Issue
Block a user