このコミットが含まれているのは:
2026-09-22 15:13:14 +09:00
コミット 068355720d
4個のファイルの変更288行の追加0行の削除
+54
ファイルの表示
@@ -0,0 +1,54 @@
class CreateExternalTags < ActiveRecord::Migration[8.0]
def up
create_table :external_tags do |t|
t.string :platform, limit: 16, null: false
t.string :name, limit: 255, null: false
t.integer :post_count, null: false, default: 0
t.datetime :created_at, null: false
t.index [:platform, :name], unique: true
end
execute <<~SQL
INSERT INTO
external_tags(id, platform, name, post_count, created_at)
SELECT
t.id
, 'nico' AS platform
, SUBSTR(tn.name, 6) AS name
, t.post_count
, t.created_at
FROM
tags t
INNER JOIN
tag_names tn
ON
tn.id = t.tag_name_id
AND t.category = 'nico'
SQL
execute <<~SQL
INSERT INTO
external_tags(id, platform, name, post_count, created_at)
SELECT
ntv.tag_id
, 'nico' AS platform
, SUBSTR(ntv.name, 6) AS name
, 0 AS post_count
, ntv.created_at
FROM
nico_tag_versions ntv
LEFT JOIN
external_tags et
ON
et.id = ntv.tag_id
WHERE
ntv.version_no = 1
AND et.id IS NULL
SQL
end
def down
drop_table :external_tags
end
end
+29
ファイルの表示
@@ -0,0 +1,29 @@
class CreatePostExternalTags < ActiveRecord::Migration[8.0]
def up
create_table :post_external_tags, primary_key: [:post_id, :external_tag_id] do |t|
t.references :post, null: false, index: false, foreign_key: true
t.references :external_tag, null: false, foreign_key: true
t.datetime :created_at, null: false
end
execute <<~SQL
INSERT INTO
post_external_tags(post_id, external_tag_id, created_at)
SELECT
pt.post_id
, pt.tag_id AS external_tag_id
, pt.created_at
FROM
post_tags pt
INNER JOIN
tags t
ON
pt.tag_id = t.id
AND t.category = 'nico'
SQL
end
def down
drop_table :post_external_tags
end
end
+6
ファイルの表示
@@ -0,0 +1,6 @@
class ChangeForeignKeyOnNicoTagRelations < ActiveRecord::Migration[8.0]
def change
remove_foreign_key :nico_tag_relations, :tags, column: :nico_tag_id
add_foreign_key :nico_tag_relations, :external_tags, column: :nico_tag_id
end
end
+199
ファイルの表示
@@ -0,0 +1,199 @@
class MigrateExternalTags < ActiveRecord::Migration[8.0]
class MigrationPostVersion < ActiveRecord::Base
self.table_name = 'post_versions'
end
def up
x = connection.select_value(<<~SQL)
SELECT
COUNT(0)
FROM
post_tag_sections pts
INNER JOIN
tags t
ON
t.id = pts.tag_id
WHERE
t.category = 'nico'
SQL
if x > 0
raise "post_tag_sections に #{ x } 件のチンカスがあります!"
end
x = connection.select_value(<<~SQL)
SELECT
COUNT(0)
FROM
materials m
INNER JOIN
tags t
ON
t.id = m.tag_id
WHERE
t.category = 'nico'
SQL
if x > 0
raise "materials に #{ x } 件のチンカスがあります!"
end
x = connection.select_value(<<~SQL)
SELECT
COUNT(0)
FROM
tag_implications ti
INNER JOIN
tags t
ON
t.id = ti.tag_id
OR t.id = ti.parent_tag_id
WHERE
t.category = 'nico'
SQL
if x > 0
raise "tag_implications に #{ x } 件のチンカスがあります!"
end
execute <<~SQL
DELETE
ts
FROM
tag_similarities ts
INNER JOIN
tags t
ON
t.category = 'nico'
AND (t.id = ts.tag_id
OR t.id = ts.target_tag_id)
SQL
execute <<~SQL
DELETE
tset
FROM
theatre_skip_event_tags tset
INNER JOIN
tags t
ON
t.category = 'nico'
AND t.id = tset.tag_id
SQL
remove_check_constraint :post_versions, name: 'chk_post_versions_tags_json_schema'
say_with_time 'Migrate post_versions.tags_json' do
count = 0
MigrationPostVersion.find_each(batch_size: 500) do |version|
tags = version.tags_json.map do |tag|
if tag.fetch('category') == 'nico'
{ 'external_tag_id' => tag.fetch('id') }
else
{ 'tag_id' => tag.fetch('id'),
'version_no' => tag.fetch('version_no'),
'name' => tag.fetch('name'),
'category' => tag.fetch('category'),
'sections' => tag.fetch('sections') }
end
end
version.update_columns(tags_json: tags)
count += 1
end
count
end
add_tags_json_constraint!
tag_name_ids = connection.select_values(<<~SQL)
SELECT
tag_name_id
FROM
tags
WHERE
category = 'nico'
SQL
connection.transaction do
execute <<~SQL
DELETE
pt
FROM
post_tags pt
INNER JOIN
tags t
ON
t.category = 'nico'
AND t.id = pt.tag_id
SQL
execute <<~SQL
DELETE
FROM
tags
WHERE
category = 'nico'
SQL
unless tag_name_ids.empty?
execute <<~SQL
DELETE
FROM
tag_names
WHERE
id IN (#{ tag_name_ids.join(', ') })
SQL
end
end
end
def down
raise ActiveRecord::IrreversibleMigration, '戻せません.'
end
private
def add_tags_json_constraint!
schema = { type: 'array',
items: { oneOf: [internal_tag_schema, external_tag_schema] } }
quoted_schema = connection.quote(JSON.generate(schema))
add_check_constraint :post_versions,
"JSON_SCHEMA_VALID(#{ quoted_schema }, tags_json)",
name: 'chk_post_versions_tags_json_schema'
end
def internal_tag_schema
{ type: 'object',
properties: { tag_id: { type: 'integer', minimum: 1 },
version_no: { type: 'integer', minimum: 1 },
name: { type: 'string', minLength: 1 },
category: { type: 'string',
enum: ['deerjikist',
'meme',
'character',
'general',
'material',
'meta'] },
sections: sections_schema },
required: ['tag_id', 'version_no', 'sections'],
additionalProperties: false }
end
def external_tag_schema
{ type: 'object',
properties: { external_tag_id: { type: 'integer', minimum: 1 } },
required: ['external_tag_id'],
additionalProperties: false }
end
def sections_schema
{ type: 'array',
items: { type: 'object',
properties: { begin_ms: { type: 'integer', minimum: 0 },
end_ms: { type: ['integer', 'null'], minimum: 0 } },
required: ['begin_ms', 'end_ms'],
additionalProperties: false } }
end
end