Andrew Roth
2007-Apr-04 19:01 UTC
joining across databases in a find statement with include (legacy db)
Hi, I have a legacy database ''old'' and a new database ''new'' which rails uses. I set up models using old with establish_connection(old), and this works well, except for include: class OldModel < ActiveRecord::Base establish_connection(old) end class NewModel < ActiveRecord::Base has_one :old_model end a = OldModel.find :first NewModel.find(:all, :include => :old_model) will give an error like Mysql::Error: Table ''new_db.old_models'' doesn''t exist: SELECT ... FROM new_models LEFT OUTER JOIN old_models ON ... WHERE ... Obviously a performance hit without the join. MySQL does support joins you specify the database first (ex old_db.old_models). I can hack it by doing the join manually but that doesn''t sound like the rails way. Any ideas? -Andrew Roth --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Suggester
2007-Apr-04 19:38 UTC
Re: joining across databases in a find statement with includ
If you must do it like this (and my must I mean you can''t run the
"new"
database on the "old" database by using new tables), I would create
faux-ActiveRecord methods in the model classes.
class OldModel < ActiveRecord::Base
establish_connection(old)
end
class NewModel < ActiveRecord::Base
def old_model
OldModel.find(:first, :conditions => ["new_model_id = ?",
self.id])
end
def old_model if self.old.nil?
OldModel.create({:new_model_id => self.id}.join(params))
else
OldModel.update(self.id, params)
end
end
end
--
Posted via http://www.ruby-forum.com/.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Ruby on Rails: Talk" group.
To post to this group, send email to
rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
To unsubscribe from this group, send email to
rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
For more options, visit this group at
http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---
John Miller
2007-Apr-04 19:48 UTC
Re: joining across databases in a find statement with includ
Andrew Roth wrote:> Hi, > > I have a legacy database ''old'' and a new database ''new'' which rails > uses. I set up models using old with establish_connection(old), and > this works well, except for include: > > class OldModel < ActiveRecord::Base > establish_connection(old) > end > > class NewModel < ActiveRecord::Base > has_one :old_model > end > > a = OldModel.find :first > NewModel.find(:all, :include => :old_model) > > will give an error like > > Mysql::Error: Table ''new_db.old_models'' doesn''t exist: SELECT ... FROM > new_models LEFT OUTER JOIN old_models ON ... WHERE ... > > Obviously a performance hit without the join. MySQL does support > joins you specify the database first (ex old_db.old_models). I can > hack it by doing the join manually but that doesn''t sound like the > rails way. Any ideas? > > -Andrew RothThis may not be as easy as it looks. Rails has no way to know that a cross data source connection can be handled in a single query. (Imagine if in ''establish_connection(old)'', old referred to a database on another server). I think there might be a way to use a :through and :source to cajole the correct query. I''m sure you can use :finder_sql in your has_many statement, but MySQL, which doesn''t always play well with compound queries, may instead execute this as 1+n queries. John Miller -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Andrew Roth
2007-Apr-05 03:16 UTC
Re: joining across databases in a find statement with includ
Good point. But at least it could try putting "database." when it detects different connections on the chance they will join. A parameter to has_many, :join_across_dbs => true could work too, but I''m not sure I''m ready to start hacking Active Record! Do people really put lots of tables in one database? Don''t tables start to get prefixed, like we have accountadmin_viewer, accountadmin_access, etc. plus form_elements, form_questions, ... and a bunch more. Isn''t it DRY - or at least good practice - to start making different databases after a few hundred of these tables? -Andrew On Apr 4, 3:48 pm, John Miller <rails-mailing-l...-ARtvInVfO7ksV2N9l4h3zg@public.gmane.org> wrote:> Andrew Roth wrote: > > Hi, > > > I have a legacy database ''old'' and a new database ''new'' which rails > > uses. I set up models using old with establish_connection(old), and > > this works well, except for include: > > > class OldModel < ActiveRecord::Base > > establish_connection(old) > > end > > > class NewModel < ActiveRecord::Base > > has_one :old_model > > end > > > a = OldModel.find :first > > NewModel.find(:all, :include => :old_model) > > > will give an error like > > > Mysql::Error: Table ''new_db.old_models'' doesn''t exist: SELECT ... FROM > > new_models LEFT OUTER JOIN old_models ON ... WHERE ... > > > Obviously a performance hit without the join. MySQL does support > > joins you specify the database first (ex old_db.old_models). I can > > hack it by doing the join manually but that doesn''t sound like the > > rails way. Any ideas? > > > -Andrew Roth > > This may not be as easy as it looks. Rails has no way to know that a > cross data source connection can be handled in a single query. (Imagine > if in ''establish_connection(old)'', old referred to a database on another > server). I think there might be a way to use a :through and :source to > cajole the correct query. I''m sure you can use :finder_sql in your > has_many statement, but MySQL, which doesn''t always play well with > compound queries, may instead execute this as 1+n queries. > > John Miller > > -- > Posted viahttp://www.ruby-forum.com/.--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Andrew Roth
2007-Apr-06 01:35 UTC
Re: joining across databases in a find statement with includ
Just wanted to follow up on this. I actually got it working by simply
pretending the table name was legacy_db.table! Easily done with
set_table_name, or if you have a bunch of models for the legacy db,
something like
class LegacyBase < ActiveRecord::Base
def self.pluralize_table_names
false # our legacy db uses singular table names
end
def self.db_name
"legacy_db"
end
def self.table_name_prefix
self.db_name + "."
end
establish_connection(self.db_name)
end
class OldModel < LegacyBase
...
end
-Andrew Roth
On Apr 4, 11:16 pm, "Andrew Roth"
<andrewr...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
wrote:> Good point. But at least it could try putting "database." when
it
> detects different connections on the chance they willjoin. A
> parameter to has_many, :join_across_dbs => true could work too, but
> I''m not sure I''m ready to start hacking Active Record!
>
> Do people really put lots of tables in one database? Don''t tables
> start to get prefixed, like we have accountadmin_viewer,
> accountadmin_access, etc. plus form_elements, form_questions, ... and
> a bunch more. Isn''t it DRY - or at least good practice - to start
> making different databases after a few hundred of these tables?
>
> -Andrew
>
> On Apr 4, 3:48 pm, John Miller
<rails-mailing-l...-ARtvInVfO7ksV2N9l4h3zg@public.gmane.org>
> wrote:
>
> > Andrew Roth wrote:
> > > Hi,
>
> > > I have alegacydatabase ''old'' and a new database
''new'' which rails
> > > uses. I set up models using old with establish_connection(old),
and
> > > this works well, except for include:
>
> > > class OldModel < ActiveRecord::Base
> > > establish_connection(old)
> > > end
>
> > > class NewModel < ActiveRecord::Base
> > > has_one :old_model
> > > end
>
> > > a = OldModel.find :first
> > > NewModel.find(:all, :include => :old_model)
>
> > > will give an error like
>
> > > Mysql::Error: Table ''new_db.old_models''
doesn''t exist: SELECT ... FROM
> > > new_models LEFT OUTERJOINold_models ON ... WHERE ...
>
> > > Obviously a performance hit without thejoin. MySQL does support
> > > joins you specify the database first (ex old_db.old_models). I
can
> > > hack it by doing thejoinmanually but that doesn''t sound
like the
> > > rails way. Any ideas?
>
> > > -Andrew Roth
>
> > This may not be as easy as it looks. Rails has no way to know that a
> > cross data source connection can be handled in a single query.
(Imagine
> > if in ''establish_connection(old)'', old referred to a
database on another
> > server). I think there might be a way to use a :through and :source
to
> > cajole the correct query. I''m sure you can use :finder_sql
in your
> > has_many statement, but MySQL, which doesn''t always play well
with
> > compound queries, may instead execute this as 1+n queries.
>
> > John Miller
>
> > --
> > Posted viahttp://www.ruby-forum.com/.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Ruby on Rails: Talk" group.
To post to this group, send email to
rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
To unsubscribe from this group, send email to
rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org
For more options, visit this group at
http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---