fixed select, pluck

This commit is contained in:
Dylan Knutson
2025-02-04 20:17:27 +00:00
parent b62f7094f4
commit 2a9302ced9
6 changed files with 114 additions and 28 deletions

View File

@@ -230,10 +230,12 @@ class Domain::MigrateToDomain
old_post_fa_ids = old_user.fav_posts.pluck(:fa_id)
new_post_ids = Domain::Post::FaPost.where(fa_id: old_post_fa_ids).pluck(:id)
Domain::UserPostFav.upsert_all(
new_post_ids.map { |post_id| { user_id: user.id, post_id: } },
unique_by: %i[user_id post_id],
)
new_post_ids.each_slice(10_000) do |post_ids|
Domain::UserPostFav.upsert_all(
post_ids.map { |post_id| { user_id: user.id, post_id: } },
unique_by: %i[user_id post_id],
)
end
if user.faved_posts.count != old_user.fav_posts.count
logger.error(
@@ -261,10 +263,12 @@ class Domain::MigrateToDomain
new_user_ids =
Domain::User::FaUser.where(url_name: followed_user_url_names).pluck(:id)
Domain::UserUserFollow.upsert_all(
new_user_ids.map { |user_id| { from_id: user.id, to_id: user_id } },
unique_by: %i[from_id to_id],
)
new_user_ids.each_slice(10_000) do |user_ids|
Domain::UserUserFollow.upsert_all(
user_ids.map { |user_id| { from_id: user.id, to_id: user_id } },
unique_by: %i[from_id to_id],
)
end
if user.following_users.count != old_user.follows.count
logger.error(

View File

@@ -42,6 +42,35 @@ class Arel::Visitors::ToSql
)
end
require "active_record/relation/query_methods"
module ActiveRecord::QueryMethods
extend T::Sig
prepend(
Module.new do
extend T::Sig
sig { params(field: T.untyped).returns(T.untyped) }
def arel_column(field)
klass = T.cast(T.unsafe(self).klass, T.class_of(ActiveRecord::Base))
if attribute_def =
AttrJsonRecordAliases::ImplHelper.get_json_attr_def(klass, field)
attr_type_cast =
T.unsafe(klass).json_attribute_type_cast(attribute_def.type.type)
adapter_class = T.unsafe(self).adapter_class
column =
"#{adapter_class.quote_column_name("json_attributes")}->>'#{field}'"
Arel::Nodes::SqlLiteral.new(
"(#{adapter_class.quote_table_name(klass.table_name)}.#{column})#{attr_type_cast} " +
"AS #{adapter_class.quote_column_name(field)}",
)
else
super
end
end
end,
)
end
module AttrJsonRecordAliases
extend T::Sig
extend T::Helpers
@@ -68,14 +97,8 @@ module AttrJsonRecordAliases
sig { params(name: T.untyped, value: T.untyped).returns(T.untyped) }
def write_attribute(name, value)
klass = self.class
ret = super(name, value)
registry =
T.cast(
T.unsafe(klass).attr_json_registry,
AttrJson::AttributeDefinition::Registry,
)
if attribute_def = registry[name.to_sym]
if attribute_def = ImplHelper.get_json_attr_def(self.class, name)
public_send(attribute_def.container_attribute)[
attribute_def.store_key
] = read_attribute(name)
@@ -83,6 +106,28 @@ module AttrJsonRecordAliases
ret
end
module ImplHelper
extend T::Sig
sig do
params(klass: T.class_of(ActiveRecord::Base), field: T.untyped).returns(
T.nilable(AttrJson::AttributeDefinition),
)
end
def self.get_json_attr_def(klass, field)
if klass < AttrJsonRecordAliases
registry =
T.cast(
T.unsafe(klass).attr_json_registry,
AttrJson::AttributeDefinition::Registry,
)
registry[field.to_sym]
else
nil
end
end
end
module ClassMethods
extend T::Sig
extend T::Helpers

View File

@@ -1,13 +1,27 @@
# typed: strict
#
class CreateDomainPosts < ActiveRecord::Migration[7.2]
class CreateUnifiedDomainTables < ActiveRecord::Migration[7.2]
extend T::Sig
POST_TYPES = %w[
Domain::Post::FaPost
Domain::Post::E621Post
Domain::Post::InkbunnyPost
Domain::Post::SofurryPost
]
USER_TYPES = %w[
Domain::User::FaUser
Domain::User::E621User
Domain::User::InkbunnyUser
Domain::User::SofurryUser
]
sig { void }
def change
reversible do |dir|
dir.up do
execute "CREATE TYPE domain_post_type AS ENUM ('Domain::Post::FaPost', 'Domain::Post::E621Post')"
execute "CREATE TYPE domain_post_type AS ENUM (#{POST_TYPES.map { |t| "'#{t}'" }.join(", ")})"
end
dir.down { execute "DROP TYPE domain_post_type" }
@@ -23,7 +37,7 @@ class CreateDomainPosts < ActiveRecord::Migration[7.2]
reversible do |dir|
dir.up do
execute "CREATE TYPE domain_user_type AS ENUM ('Domain::User::FaUser', 'Domain::User::E621User')"
execute "CREATE TYPE domain_user_type AS ENUM (#{USER_TYPES.map { |t| "'#{t}'" }.join(", ")})"
end
dir.down { execute "DROP TYPE domain_user_type" }

View File

@@ -99,7 +99,9 @@ COMMENT ON EXTENSION vector IS 'vector data type and ivfflat access method';
CREATE TYPE public.domain_post_type AS ENUM (
'Domain::Post::FaPost',
'Domain::Post::E621Post'
'Domain::Post::E621Post',
'Domain::Post::InkbunnyPost',
'Domain::Post::SofurryPost'
);
@@ -109,7 +111,9 @@ CREATE TYPE public.domain_post_type AS ENUM (
CREATE TYPE public.domain_user_type AS ENUM (
'Domain::User::FaUser',
'Domain::User::E621User'
'Domain::User::E621User',
'Domain::User::InkbunnyUser',
'Domain::User::SofurryUser'
);

View File

@@ -83,15 +83,20 @@ namespace :e621 do
# puts Domain::Post::E621Post.where(e621_id: 5_350_363).explain.inspect
# puts Domain::Post::FaPost.where(fa_id: 52_801_830).explain.inspect
# puts Domain::Fa::Post.where(fa_id: 52_801_830).explain.inspect
puts Domain::Fa::Post
.joins(
"
LEFT JOIN domain_posts ON domain_fa_posts.fa_id =
(domain_posts.json_attributes->>'fa_id')::integer
",
)
.where(domain_posts: { id: nil, type: "Domain::Post::FaPost" })
puts Domain::Post::FaPost
.select(:fa_id)
.where(fa_id: 52_801_830)
.explain
.inspect
# puts Domain::Fa::Post
# .joins(
# "
# LEFT JOIN domain_posts ON domain_fa_posts.fa_id =
# (domain_posts.json_attributes->>'fa_id')::integer
# ",
# )
# .where(domain_posts: { id: nil, type: "Domain::Post::FaPost" })
# .explain
# .inspect
end
end

View File

@@ -101,6 +101,20 @@ RSpec.describe Domain::Post::FaPost do
new_post = described_class.new
expect(new_post.keywords).to eq([])
end
it "can be selected by an attribute" do
post = create(:domain_post_fa_post)
query = described_class.where(fa_id: post.fa_id)
expect(query.count).to eq(1)
query =
described_class.select(:fa_id, :json_attributes).where(
fa_id: post.fa_id,
)
expect(query.map(&:fa_id)).to eq([post.fa_id])
query = described_class.pluck(:id, :fa_id)
expect(query).to eq([[post.id, post.fa_id]])
end
end
describe "factory" do