Skip to content

Commit

Permalink
Fix anykeyh#19 issue with joins
Browse files Browse the repository at this point in the history
  • Loading branch information
Yacine Petitprez committed Jun 28, 2018
1 parent 127d0f8 commit 0982b06
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 13 deletions.
36 changes: 34 additions & 2 deletions spec/model/model_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ module ModelSpec

belongs_to user : User, key_type: Int32?

self.table = "models_posts"
self.table = "model_posts"
end

class UserInfo
Expand Down Expand Up @@ -69,7 +69,7 @@ module ModelSpec
t.timestamps
end

create_table "models_posts" do |t|
create_table "model_posts" do |t|
t.string "title", index: true
t.references to: "model_users", name: "user_id", on_delete: "cascade"
end
Expand Down Expand Up @@ -329,6 +329,38 @@ module ModelSpec
end
end

context "with join" do
it "resolves by default ambiguous columns in joins" do
temporary do
reinit

u = User.create!({first_name: "Join User"})
p = Post.create!({title: "A Post", user_id: u.id})

Post.query.join("model_users") { model_posts.user_id == model_users.id }.to_sql
.should eq "SELECT model_posts.* FROM model_posts INNER JOIN model_users " +
"ON ((model_posts.user_id = model_users.id))"
end
end

it "resolve ambiguous columns in with_* methods" do
temporary do
reinit
u = User.create!({first_name: "Join User"})
p = Post.create!({title: "A Post", user_id: u.id})

user_with_a_post_minimum = User.query.distinct.join("model_posts") { model_posts.user_id == model_users.id }

user_with_a_post_minimum.to_sql.should eq \
"SELECT DISTINCT model_users.* FROM model_users INNER JOIN " +
"model_posts ON ((model_posts.user_id = model_users.id))"

user_with_a_post_minimum.with_posts.each do |u|
end
end
end
end

context "with pagination" do
it "can pull the next 5 users from page 2" do
temporary do
Expand Down
8 changes: 8 additions & 0 deletions src/clear/model/collection.cr
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,14 @@ module Clear::Model
last(fetch_columns).not_nil!
end

protected def join_impl(name, type, clear_expr)
if @columns.empty?
self.select("#{T.table}.*")
end

super(name, type, clear_expr)
end

# Get the last row from the collection query.
# if not found, return `nil`
def last(fetch_columns = false) : T?
Expand Down
8 changes: 4 additions & 4 deletions src/clear/model/modules/has_relations.cr
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ module Clear::Model::HasRelations
%foreign_key = {{foreign_key}} || ( {{@type}}.table.to_s.singularize + "_id" )

#SELECT * FROM foreign WHERE foreign_key IN ( SELECT primary_key FROM users )
sub_query = self.dup.clear_select.select("#{%primary_key}")
sub_query = self.dup.clear_select.select("#{{{@type}}.table}.#{%primary_key}")

@cache.active "{{method_name}}"

Expand Down Expand Up @@ -113,7 +113,7 @@ module Clear::Model::HasRelations

@cache.active "{{method_name}}"

sub_query = self.dup.clear_select.select(self_type.pkey)
sub_query = self.dup.clear_select.select("#{{{@type}}.table}.#{self_type.pkey}")

qry = {{relation_type}}.query.join(%through_table){
var("#{%through_table}.#{%through_key}") == var("#{%final_table}.#{%final_pkey}")
Expand Down Expand Up @@ -190,7 +190,7 @@ module Clear::Model::HasRelations
%foreign_key = {{foreign_key}} || ( {{@type}}.table.to_s.singularize + "_id" )

#SELECT * FROM foreign WHERE foreign_key IN ( SELECT primary_key FROM users )
sub_query = self.dup.clear_select.select("#{%primary_key}")
sub_query = self.dup.clear_select.select("#{{{@type}}.table}.#{%primary_key}")

qry = {{relation_type}}.query.where{ raw(%foreign_key).in?(sub_query) }
block.call(qry)
Expand Down Expand Up @@ -286,7 +286,7 @@ module Clear::Model::HasRelations
class Collection
def with_{{method_name}}(fetch_columns = false, &block : {{relation_type}}::Collection -> ) : self
before_query do
sub_query = self.dup.clear_select.select({{foreign_key.id.stringify}})
sub_query = self.dup.clear_select.select("#{{{@type}}.table}.{{foreign_key.id}}")

cached_qry = {{relation_type}}.query.where{ raw({{relation_type}}.pkey).in?(sub_query) }

Expand Down
16 changes: 9 additions & 7 deletions src/clear/sql/query/join.cr
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,26 @@ module Clear::SQL::Query::Join
getter joins : Array(SQL::Join)
end

def join(name : Symbolic, type = :inner, &block)
joins << Clear::SQL::Join.new(name, Clear::Expression.ensure_node!(with Clear::Expression.new yield), type)
protected def join_impl(name : Symbolic, type, clear_expr)
joins << Clear::SQL::Join.new(name, clear_expr, type)
change!
end

def join(name : Symbolic, type = :inner, &block)
join_impl(name, type, Clear::Expression.ensure_node!(with Clear::Expression.new yield))
end

def join(name : Symbolic, type = :inner)
joins << Clear::SQL::Join.new(name, nil, type)
change!
join_impl(name, type, nil)
end

def cross_join(name : Symbolic)
join(name, type: :cross)
join(name, :cross)
end

{% for j in ["left", "right", "full_outer"] %}
def {{j.id}}_join(name : Symbolic, &block)
joins << Clear::SQL::Join.new(name, Clear::Expression.ensure_node!(with Clear::Expression.new yield), :{{j.id}})
change!
join_impl(name, :{{j.id}}, Clear::Expression.ensure_node!(with Clear::Expression.new yield))
end
{% end %}

Expand Down

0 comments on commit 0982b06

Please sign in to comment.