Fix direct query execution issues in PG by using select_values/select_rows instead of execute.

This commit is contained in:
Raphael Sofaer 2011-06-22 14:47:59 -07:00
parent 02739259b6
commit e8552fc417
7 changed files with 23 additions and 38 deletions

View file

@ -56,19 +56,14 @@ class ConversationsController < ApplicationController
end
def new
all_contacts_and_ids = Contact.connection.execute(current_user.contacts.joins(:person => :profile
).select("contacts.id, profiles.first_name, profiles.last_name, people.diaspora_handle").to_sql).map do |r|
person_json_from_row r
end
all_contacts_and_ids = Contact.connection.select_rows(
current_user.contacts.joins(:person => :profile).
select("contacts.id, profiles.first_name, profiles.last_name, people.diaspora_handle").to_sql
).map{|r| {:value => r[0], :name => Person.name_from_attrs(r[1], r[2], r[3]).gsub(/(")/, "'")} }
@contacts_json = all_contacts_and_ids.to_json.gsub!(/(")/, '\\"')
@contact = current_user.contacts.find(params[:contact_id]) if params[:contact_id]
render :layout => false
end
def person_json_from_row r
r = [r["id"], r["first_name"], r["last_name"], r["diaspora_handle"]] if defined?(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter) && ActiveRecord::Base.connection.is_a?(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter)
{:value => r[0],
:name => Person.name_from_attrs(r[1], r[2], r[3]).gsub(/(")/, "'")}
end
end

View file

@ -23,9 +23,9 @@ class ActivityStreams::Photo < Post
def socket_to_user(user_or_id, opts={}) #adds aspect_ids to opts if they are not there
unless opts[:aspect_ids]
user_id = user_or_id.instance_of?(Fixnum) ? user_or_id : user_or_id.id
aspect_ids = AspectMembership.connection.execute(
aspect_ids = AspectMembership.connection.select_values(
AspectMembership.joins(:contact).where(:contacts => {:user_id => user_id, :person_id => self.author_id}).select('aspect_memberships.aspect_id').to_sql
).map{|r| r.first}
)
opts.merge!(:aspect_ids => aspect_ids)
end
super(user_or_id, opts)

View file

@ -80,7 +80,7 @@ class Person < ActiveRecord::Base
# @return [Array<String>] postgreSQL and mysql deal with null values in orders differently, it seems.
def self.search_order
@search_order ||= Proc.new {
order = if defined?(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter) && ActiveRecord::Base.connection.is_a?(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter)
order = if postgres?
"ASC"
else
"DESC"

View file

@ -132,9 +132,9 @@ class StatusMessage < Post
def socket_to_user(user_or_id, opts={})
unless opts[:aspect_ids]
user_id = user_or_id.instance_of?(Fixnum) ? user_or_id : user_or_id.id
aspect_ids = AspectMembership.connection.execute(
aspect_ids = AspectMembership.connection.select_values(
AspectMembership.joins(:contact).where(:contacts => {:user_id => user_id, :person_id => self.author_id}).select('aspect_memberships.aspect_id').to_sql
).map{|r| r.first}
)
opts.merge!(:aspect_ids => aspect_ids)
end
super(user_or_id, opts)

View file

@ -36,3 +36,8 @@ module Devise
end
end
end
# check what database you have
def postgres?
@using_postgres ||= defined?(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter) && ActiveRecord::Base.connection.is_a?(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter)
end

View file

@ -48,26 +48,11 @@ module Diaspora
all_posts = "#{posts_from_others.to_sql} UNION ALL #{posts_from_self.to_sql} ORDER BY #{opts[:order]} LIMIT #{opts[:limit]}"
end
post_ids = Post.connection.execute(all_posts).map {|post| id_for(post) }
post_ids = Post.connection.select_values(all_posts)
Post.where(:id => post_ids).select('DISTINCT posts.*').limit(opts[:limit]).order(order_with_table)
end
# Determine, cache, and execute the method call needed to extract the id from a raw result row.
# Returns row["id"] for PostgreSQL
# Returns row.first for everything else (MYSQL)
#
# @param row The row to get the id from.
# @return The id of the database row passed in.
def id_for row
@@id_method_for_row ||= if defined?(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter) && ActiveRecord::Base.connection.is_a?(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter)
[:[], "id"]
else
:first
end
row.send(*@@id_method_for_row)
end
def visible_photos(opts = {})
visible_posts(opts.merge(:type => 'Photo'))
end
@ -117,9 +102,13 @@ module Diaspora
p = Post.arel_table
post_ids = []
if contact = self.contact_for(person)
post_ids = Post.connection.execute(contact.post_visibilities.where(:hidden => false).select('post_visibilities.post_id').to_sql).map{|r| r.first}
post_ids = Post.connection.select_values(
contact.post_visibilities.where(:hidden => false).select('post_visibilities.post_id').to_sql
)
end
post_ids += Post.connection.execute(person.posts.where(:public => true).select('posts.id').to_sql).map{|r| r.first}
post_ids += Post.connection.select_values(
person.posts.where(:public => true).select('posts.id').to_sql
)
Post.where(:id => post_ids, :pending => false).select('DISTINCT posts.*').order("posts.created_at DESC")
end

View file

@ -81,9 +81,5 @@ def remote_raphael
end
def photo_fixture_name
@photo_fixture_name = File.join(File.dirname(__FILE__), 'fixtures', 'button.png')
end
def postgres?
defined?(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter) && ActiveRecord::Base.connection.is_a?(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter)
@photo_fixture_name = File.join(File.dirname(__FILE__), 'fixtures', 'button.png')
end