From 80b184425e1e255cec8ff34ef77f277516dd8296 Mon Sep 17 00:00:00 2001 From: Samuel Giddins Date: Sun, 21 Jul 2024 16:12:46 -0700 Subject: [PATCH] Use Sequel builder methods for complex compact index queries --- lib/gemstash/compact_index_builder.rb | 50 +++++++++++++++------------ lib/gemstash/db/rubygem.rb | 2 ++ lib/gemstash/db/version.rb | 1 + 3 files changed, 30 insertions(+), 23 deletions(-) diff --git a/lib/gemstash/compact_index_builder.rb b/lib/gemstash/compact_index_builder.rb index b535d73e..ba05ee0a 100644 --- a/lib/gemstash/compact_index_builder.rb +++ b/lib/gemstash/compact_index_builder.rb @@ -183,21 +183,30 @@ def build_result private def requirements_and_dependencies - group_by_columns = "number, platform, sha256, info_checksum, required_ruby_version, required_rubygems_version, versions.created_at" - - dep_req_agg = "string_agg(dependencies.requirements, '@' ORDER BY dependencies.rubygem_name, dependencies.id) as dep_req_agg" - - dep_name_agg = "string_agg(dependencies.rubygem_name, ',' ORDER BY dependencies.rubygem_name) AS dep_name_agg" - - DB::Rubygem.db[<<~SQL.squish, @name]. - SELECT #{group_by_columns}, #{dep_req_agg}, #{dep_name_agg} - FROM rubygems - LEFT JOIN versions ON versions.rubygem_id = rubygems.id - LEFT JOIN dependencies ON dependencies.version_id = versions.id - WHERE rubygems.name = ? AND versions.indexed = true - GROUP BY #{group_by_columns} - ORDER BY versions.created_at, number, platform, dep_name_agg - SQL + # group_by_columns = "number, platform, sha256, info_checksum, required_ruby_version, required_rubygems_version, versions.created_at" + + # dep_req_agg = Sequel::SQL::StringAgg.new("dependencies.requirements", "@"). + # order("dependencies.rubygem_name", :id). + # as(:dep_req_agg) + + # dep_name_agg = Sequel::SQL::StringAgg.new("dependencies.rubygem_name", ","). + # order("dependencies.rubygem_name"). + # as(:dep_name_agg) + + group_by_columns = %i[number platform sha256 info_checksum required_ruby_version required_rubygems_version created_at]. + map {|c| DB::Version[c] } + + DB::Rubygem.association_left_join(versions: :dependencies). + where(name: @name). + where { versions[:indexed] }. + order { [versions[:created_at], versions[:number], versions[:platform], dep_name_agg] }. + select_group do + [versions[:number], versions[:platform], versions[:sha256], versions[:info_checksum], versions[:required_ruby_version], versions[:required_rubygems_version], versions[:created_at]] + end. # rubocop:disable Style/MultilineBlockChain + select_more do + [string_agg(dependencies[:requirements], "@").order(dependencies[:rubygem_name], dependencies[:id]).as(:dep_req_agg), + string_agg(dependencies[:rubygem_name], ",").order(dependencies[:rubygem_name]).as(:dep_name_agg)] + end. # rubocop:disable Style/MultilineBlockChain map do |row| reqs = row[:dep_req_agg]&.split("@") dep_names = row[:dep_name_agg]&.split(",") @@ -235,14 +244,9 @@ def fetch_resource end def build_result - names = DB::Rubygem.db[<<~SQL.squish].map {|row| row[:name] } - SELECT name - FROM rubygems - INNER JOIN versions ON versions.rubygem_id = rubygems.id - WHERE versions.indexed = true - GROUP BY name - ORDER BY name - SQL + names = DB::Rubygem.association_join(:versions). + where { versions[:indexed] }. + order(:name).group(:name).select_map(:name) @result = CompactIndex.names(names).encode("UTF-8") end diff --git a/lib/gemstash/db/rubygem.rb b/lib/gemstash/db/rubygem.rb index 7083d416..a2112195 100644 --- a/lib/gemstash/db/rubygem.rb +++ b/lib/gemstash/db/rubygem.rb @@ -6,6 +6,8 @@ module Gemstash module DB # Sequel model for rubygems table. class Rubygem < Sequel::Model + one_to_many :versions + def self.find_or_insert(spec) record = self[name: spec.name] return record.id if record diff --git a/lib/gemstash/db/version.rb b/lib/gemstash/db/version.rb index 032c03fa..d8925762 100644 --- a/lib/gemstash/db/version.rb +++ b/lib/gemstash/db/version.rb @@ -7,6 +7,7 @@ module DB # Sequel model for versions table. class Version < Sequel::Model many_to_one :rubygem + one_to_many :dependencies def deindex info = Gemstash::CompactIndexBuilder::Info.new(nil, rubygem.name).tap(&:build_result).result