Skip to content

Commit

Permalink
chore: tried to optimise some queries and failed
Browse files Browse the repository at this point in the history
  • Loading branch information
bethesque committed Dec 1, 2020
1 parent 551507d commit 8a0faac
Show file tree
Hide file tree
Showing 4 changed files with 163 additions and 0 deletions.
18 changes: 18 additions & 0 deletions lib/pact_broker/domain/tag.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,24 @@ def latest_tags
.join(latest_tags, latest_tags_versions_join, { table_alias: :latest_tags })
end

# Ron's fancy join
# performs every so slightly better
def latest_tags_2
tag_versions = PactBroker::Domain::Tag
.select_all_qualified
.select_append(Sequel[:versions][:pacticipant_id])
.select_append(Sequel[:versions][:order])
.join(:versions,
{ Sequel[:tags][:version_id] => Sequel[:versions][:id] }
)

tag_versions
.left_join(tag_versions, { Sequel[:tags][:name] => Sequel[:tags_2][:name], Sequel[:versions][:pacticipant_id] => Sequel[:tags_2][:pacticipant_id] }, { table_alias: :tags_2 }) do | table, joined_table, js |
Sequel.qualify(table, :order) > Sequel.qualify(joined_table, :order)
end
.where(Sequel[:tags_2][:name] => nil)
end

# Does NOT care about whether or not there is a pact publication
# for the version
def latest_tags_for_pacticipant_ids(pacticipant_ids)
Expand Down
87 changes: 87 additions & 0 deletions lib/pact_broker/domain/verification.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
require 'pact_broker/repositories/helpers'
require 'pact_broker/tags/tag_with_latest_flag'
require 'pact_broker/pacts/content'
require 'sequel/extensions/symbol_aref_refinement'


module PactBroker
module Domain
class Verification < Sequel::Model
using Sequel::SymbolAref

set_primary_key :id
associate(:many_to_one, :pact_version, class: "PactBroker::Pacts::PactVersion", key: :pact_version_id, primary_key: :id)
Expand All @@ -25,6 +27,82 @@ def before_create
dataset_module do
include PactBroker::Repositories::Helpers

def latest_verification_ids_for_all_consumer_version_tags
verif_pact_join = { Sequel[:verifications][:pact_version_id] => Sequel[:lpp][:pact_version_id] }
tag_join = { Sequel[:lpp][:consumer_version_id] => Sequel[:cvt][:version_id] }
verisons_join = { Sequel[:v][:provider_version_id] => Sequel[:pv][:id] }

db[:verifications]
.select_group(
Sequel[:pv][:pacticipant_id].as(:provider_id),
Sequel[:lpp][:consumer_id],
Sequel[:cvt][:name].as(:consumer_version_tag_name)
)
.select_append{ max(verifications[id]).as(latest_verification_id) }
.join(:latest_pact_publication_ids_for_consumer_versions, verif_pact_join, { table_alias: :lpp } )
.join(:tags, tag_join, { table_alias: :cvt })
.join(:versions, verisons_join, { table_alias: :pv })
end

# Do not use this query. It performs worse than the view.
# Keeping for posterity
def latest_verifications_for_all_consumer_version_tags
verif_pact_join = { Sequel[:v][:pact_version_id] => Sequel[:lpp][:pact_version_id] }
tag_join = { Sequel[:lpp][:consumer_version_id] => Sequel[:cvt][:version_id] }
verisons_join = { Sequel[:v][:provider_version_id] => Sequel[:pv][:id] }

base_query = db[Sequel.as(:latest_verification_id_for_pact_version_and_provider_version, :v)]
.select(:v[:verification_id], :pv[:pacticipant_id].as(:provider_id), :lpp[:consumer_id], :cvt[:name].as(:consumer_version_tag_name))
.join(:latest_pact_publication_ids_for_consumer_versions, verif_pact_join, { table_alias: :lpp } )
.join(:tags, tag_join, { table_alias: :cvt })
.join(:versions, verisons_join, { table_alias: :pv })


base_join = {
:pv[:pacticipant_id] => :v2[:provider_id],
:lpp[:consumer_id] => :v2[:consumer_id],
:cvt[:name] => :v2[:consumer_version_tag_name]
}

thing = base_query
.left_join(base_query, base_join, { table_alias: :v2 }) do | table, joined_table, something |
:v2[:verification_id] > :v[:verification_id]
end.where(:v2[:verification_id] => nil)

where(id: thing.from_self.select(:verification_id))
end

def latest_verification_ids_for_consumer_version_tags(consumer_ids, consumer_version_tag_names)
pact_join = { :verifications[:pact_version_id] => :lpp[:pact_version_id], :lpp[:consumer_id] => consumer_ids }
tag_join = { :lpp[:consumer_version_id] => :cvt[:version_id], :cvt[:name] => consumer_version_tag_names }
provider_versions_join = { :verifications[:provider_version_id] => :pv[:id] }

db[Sequel.as(:latest_verification_id_for_pact_version_and_provider_version, :verifications)]
.select_group(
:pv[:pacticipant_id].as(:provider_id),
:lpp[:consumer_id],
:cvt[:name].as(:consumer_version_tag_name)
)
.select_append{ max(verifications[verification_id]).as(latest_verification_id) }
.join(:latest_pact_publication_ids_for_consumer_versions, pact_join, { table_alias: :lpp } )
.join(:tags, tag_join, { table_alias: :cvt })
.join(:versions, provider_versions_join, { table_alias: :pv })
.where(:verifications[:consumer_id] => consumer_ids)
end

# Do not use this query. It performs worse than the view.
# Keeping for posterity
def latest_verifications_for_consumer_version_tags(consumer_ids, consumer_version_tag_names)
latest_ids_for_cv_tags = latest_verification_ids_for_consumer_version_tags(consumer_ids, consumer_version_tag_names)
join_cols = {
Sequel[:verifications][:id] => Sequel[:t2][:latest_verification_id]
}
select_all_qualified
.select_append(Sequel[:t2][:consumer_version_tag_name])
.where(Sequel[:verifications][:consumer_id] => consumer_ids)
.join(latest_ids_for_cv_tags, join_cols, { table_alias: :t2 })
end

# Expects to be joined with AllPactPublications or subclass
# Beware that when columns with the same name exist in both datasets
# you may get the wrong column back in your model.
Expand Down Expand Up @@ -102,6 +180,15 @@ def all_interactions_missing_test_results?
def pact_content_with_test_results
@pact_content_with_test_results = PactBroker::Pacts::Content.from_json(pact_version.content).with_test_results(test_results)
end

# So consumer_version_tag_name can be accessed by method name
def method_missing(m, *args, &block)
if values.key?(m) && args.size == 0
values[m]
else
super
end
end
end

Verification.plugin :timestamps
Expand Down
9 changes: 9 additions & 0 deletions lib/pact_broker/test/test_data_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,15 @@ def create_pact_with_verification consumer_name = "Consumer", consumer_version =
self
end

def create_pact_with_verification_and_tags consumer_name = "Consumer", consumer_version = "1.0.#{model_counter}", consumer_version_tags = [], provider_name = "Provider", provider_version = "1.0.#{model_counter}", provider_version_tags = []
create_pact_with_hierarchy(consumer_name, consumer_version, provider_name)
consumer_version_tags.each do | tag |
create_consumer_version_tag(tag)
end
create_verification(number: model_counter, provider_version: provider_version, tag_names: provider_version_tags)
self
end

def create_version_with_hierarchy pacticipant_name, pacticipant_version
pacticipant = pacticipant_service.create(:name => pacticipant_name)
version = PactBroker::Domain::Version.create(:number => pacticipant_version, :pacticipant => pacticipant)
Expand Down
49 changes: 49 additions & 0 deletions spec/lib/pact_broker/domain/verification_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,55 @@ module PactBroker

module Domain
describe Verification do
describe "latest_verifications_for_all_consumer_version_tags" do
before do
td.create_pact_with_verification_and_tags("Foo", "1", ["fmain"], "Bar", "2")
.create_pact_with_verification_and_tags("Foo", "3", ["fmain"], "Bar", "4")
.create_pact_with_verification_and_tags("Foo", "5", ["fmain"], "Bar", "5")
.create_pact_with_verification_and_tags("Foo", "6", ["other"], "Bar", "5")
.create_pact_with_verification_and_tags("Foo2", "6", ["fprod"], "Bar", "7")
.create_pact_with_verification_and_tags("Ignored", "6", ["fmain"], "Bar", "8")
end

subject { Verification.latest_verifications_for_all_consumer_version_tags.all }

it "returns the same number of rows as the view" do
expect(subject.size).to eq Verification.db[:latest_verifications_for_consumer_version_tags].count
end

it "allows eager" do
expect(Verification.latest_verifications_for_all_consumer_version_tags.eager(:provider_version).all.first.provider_version.number).to_not be nil
end
end

describe "latest_verifications_for_consumer_version_tags" do
before do
td.create_pact_with_verification_and_tags("Foo", "1", ["fmain"], "Bar", "2")
.create_pact_with_verification_and_tags("Foo", "3", ["fmain"], "Bar", "4")
.create_pact_with_verification_and_tags("Foo", "5", ["fmain"], "Bar", "5")
.create_pact_with_verification_and_tags("Foo", "6", ["other"], "Bar", "5")
.create_pact_with_verification_and_tags("Foo2", "6", ["fprod"], "Bar", "7")
.create_pact_with_verification_and_tags("Ignored", "6", ["fmain"], "Bar", "8")
end

let(:consumer_ids) { PactBroker::Domain::Pacticipant.where(name: ["Foo", "Foo2"]).all.collect(&:id) }

subject { Verification.latest_verifications_for_consumer_version_tags(consumer_ids, ["fmain", "fprod"]).order(:id) }

it "returns the latest verifications for the given consumer ids and consumer version tag names" do
expect(subject.first.provider_version_number).to eq "5"
expect(subject.first.consumer_name).to eq "Foo"
expect(subject.first.consumer_version_tag_name).to eq "fmain"
expect(subject.last.provider_version_number).to eq "7"
expect(subject.last.consumer_name).to eq "Foo2"
expect(subject.last.consumer_version_tag_name).to eq "fprod"
end

it "allows eager" do
expect(subject.eager(:provider_version).all.first.provider_version.number).to eq "5"
end
end

describe "delete" do
before do
td.create_pact_with_hierarchy("Foo", "1", "Bar")
Expand Down

0 comments on commit 8a0faac

Please sign in to comment.