rails / arel Goto Github PK
View Code? Open in Web Editor NEWThis project forked from brynary/arel
A Relational Algebra
This project forked from brynary/arel
A Relational Algebra
#union
always returns a Arel::Nodes::Union
, and you can't chain more operations off of it.
arel_a = arel_table_a.project(Arel.star)
arel_b = arel_table_b.project(Arel.star)
union = arel_a.union(arel_b)
union.class #=> Arel::Nodes::Union
union.order("x, y DESC") # Doesn't work
You either have to wrap the whole thing in a redundant Arel::SelectManager, which I haven't quite figured out yet, since the AS
is required by postgres. I think I have to make it generate SQL like this, but that seems like a waste:
SELECT * FROM (
SELECT * FROM table_a UNION SELECT * FROM table_b
) AS table ORDER BY x, y DESC
Or do something like:
union.to_sql + " ORDER BY x, y DESC"
...except there's a comment on Nodes::Binary#to_sql that says it shouldn't be used.
Here's a sample UPDATE statement with FOR UPDATE subquery in PostgreSQL 9.2:
UPDATE tickets
SET purchased = TRUE
WHERE ID in (
SELECT id
FROM tickets
WHERE NOT purchased
LIMIT 10
FOR UPDATE
)
I would expect to have this UPDATE statement from the following rails statement:
Ticket.where(:purchased => false).limit(10).lock(true).update_all(:purchased => true)
but FOR UPDATE clause is not added because UpdateManager doesn't have a way to add FOR UPDATE (pessimistic lock) in update subquery. File: update_manager.rb.
This is a screenshot from rails source where UpdateManager.lock should probably be called: http://bit.ly/RPsQ31
Is this something you think about adding in later versions or it was omitted with a purpose? I know such a FOR UPDATE lock was not supported in PostgreSQL before 9.0.
When you build a query with a GROUP BY in Oracle, any use of .first() or .limit() doesn't produce a subquery like it should. There's a comment in Visitors::Oracle about this, but there's no check in the code.
For example an arel query like this:
things = Thing.arel_table
Thing.group(things[:id]).having(things[:thing_type].count.gt(2)).select(things[:id]).first
Generates SQL like this (which returns no rows):
select id
from things
where rownum <= 1
group by id
having count(thing_type) > 2
It should wrap everything in a subquery for limiting the results:
select * from (
select id
from things
group by id
having count(thing_type) > 2
) where rownum <= 1
I'm not super familiar with the internals of arel, but I'll try to demonstrate this in a test case and submit a fix.
Setting alias for table:
a = Foo.arel_table
a1 = a.alias("#{a.name}_1")
a2 = a.alias("#{a.name}_2")
inner_where = a1[:attr1].eq(a2[:attr1])
just working on joins:
a.join(a2).on(a1[:attr1].eq(a2[:attr1])).to_sql
returns:
"SELECT FROM \"foos\"
INNER JOIN \"foos\" \"foos_2\"
ON \"foos\".\"attr1\" = \"foos_2\".\"attr1\""
Same approach for nested where, no way:
a.where( a.where(inner_where).exists).to_sql
Don't express Alias for From clauses
"SELECT FROM \"foos\"
WHERE EXISTS (SELECT FROM \"foos\"
WHERE \"foos_1\".\"attr1\" = \"foos_2\".\"attr1\")"
Self subqueries needs some like:
"SELECT FROM \"foos\" \"foos_1\"
WHERE EXISTS (SELECT FROM \"foos\" \"foos_2\"
WHERE \"foos_1\".\"attr1\" = \"foos_2\".\"attr1\")"
when chaining custom selects in rails like
Model.select(table[:name].as('foo')).select(table[:name].as('foo'))
It produces duplicate select_values. Thats because the select_values array can't be made uniq in
ActiveRecord::QueryMethods#build_arel
Unlike
table[:name] == table[:name]
=> true
table[:name].as('foo') == table[:name].as('foo')
=> false
Wouldn't it make sense to implement equality for Arel::Nodes ?
Or to be more specific to have a proper implementation of the hash function for Arel::Nodes ?
Just playing around with the idea of a ToSqlPretty visitor, would you consider pulling it in or should it belong in a separate gem?
I'm thinking indentation, colors. Maybe this should go in the awesome_print gem.
Thoughts?
Hi guys,
The following example given in the documentation generates invalid SQL.
GROUP BY is called group:
users.group(users[:name]) # => SELECT * FROM users GROUP BY name
MySQL will execute this, by PostgreSQL will complain that:
ERROR: column "users.id" must appear in the GROUP BY clause or be used in an aggregate function
LINE 1: SELECT * FROM users GROUP BY name
Cheers,
Dan
I wasn't sure if there was a reason for not having this method, or if maybe no one thought about it, so I'd like to put in a request, and if you think it's cool, I'd be ok with forking and adding it in.
User.not(:last_name => 'Smith').to_sql #=> SELECT `users`.* FROM `users` WHERE (last_name <> 'Smith')
User.where(:first_name => 'Billy').not(:last_name => 'Smith').to_sql #=> SELECT `users`.* FROM `users` WHERE `users`.`first_name` = 'Billy' AND (last_name <> 'Smith')
It would basically be a "helper" method, but add in a more "ruby" like way of writing the SQL instead of having to do a where() with a SQL string inside it.
Thanks,
~Jeremy
Using Arel 3.0.2 with Rails 3.2, but I believe the bug has always been present. A joined query like Comment.joins("inner join posts on post.id = comments.post_id").where("posts.published = 1")
results in the invalid sql statement select * from comments where posts.published = 1
.
It's a one-line patch to visit_Arel_Nodes_SelectCore
in lib/arel/visitors/informix.rb:
- ("FROM #{visit o.froms}" if o.froms),
+ ("FROM #{visit o.source}" if o.source),
I plan to fork and submit a pull request soon, unless someone can point out a problem with that solution.
For reference, I am using Rails 3.1.0rc4 with arel 2.1.1, and pg 0.11.0
My tests seemed to have exposed this bug. Take the following model:
class Location < ActiveRecord::Base
belongs_to :user
scope :distinct_by_user, select('DISTINCT ON(user_id) *')
scope :from_sorted_locations, from('(SELECT locations.* FROM "locations" ORDER BY locations.id DESC) AS sorted_locations')
scope :recent_user_locations, distinct_by_user.from_sorted_locations
end
The SQL Query that's generated is below the ruby code:
Location.recent_user_locations
# SELECT DISTINCT ON(user_id) * FROM (SELECT locations.* FROM "locations" ORDER BY locations.id DESC) AS sorted_locations
Location.recent_user_locations.size
# SELECT COUNT(*) FROM (SELECT locations.* FROM "locations" ORDER BY locations.id DESC) AS sorted_locations
Basically, calling "size" / "count" will go against my own "from" query, but disregard my select query. Once the query is executed, #size / #count return the correct record count.
Thank you!
This commit - 7941132 - changed the expectation of what is passed to ToSql#new, and the call to ToSql#new in SelectManager#where_clauses was not changed appropriately. Looks like Compatibility::Wheres#each probably has the same problem. SelectManager#where_clauses is deprecated, but should still work properly, unless it is going to be removed entirely.
An addition or subtraction results in a Nodes::Grouping instance, and that class does not have the mixins to support chaining additional methods. I can't even specify a column name using #as (e.g. (foo_table[:value] + 1).as(foo_plus_one). Attempting to do so results in...
NoMethodError: undefined method `as' for #Arel::Nodes::Grouping:0x00000102e9b968
Likewise, I can't chain an addition to an addition, etc. The same problem does not exist for multiplication and division, because those return instances of Nodes::Binary subclasses rather than Nodes::Grouping.
It seems to me that the addition and subtraction operators should return instances of something like a MathGrouping class that includes the same mixins that Nodes::Binary and Attributes::Attribute do (and maybe there should be another module that encapsulates that combination of inclusions).
Hi,
I've had this issue with Oracle database and opened a issue rsim/oracle-enhanced#185.
Since that I have no way to find workaround/fix this issue, this error message has Arel::Nodes::Ascending:
. I decided to open a new issue here.
Tested with Rails master branch, Unit tests for Oracle got an ActiveRecord::StatementInvalid: OCIError: ORA-00911 at test_find_on_has_many_association_collection_with_include_and_conditions.
$ ARCONN=oracle ruby -Itest test/cases/associations/has_many_through_associations_test.rb -n test_find_on_has_many_association_collection_with_include_and_conditions
Using oracle
Run options: -n test_find_on_has_many_association_collection_with_include_and_conditions --seed 56475
# Running tests:
E
Finished tests in 2.174052s, 0.4600 tests/s, 0.0000 assertions/s.
1) Error:
test_find_on_has_many_association_collection_with_include_and_conditions(HasManyThroughAssociationsTest):
ActiveRecord::StatementInvalid: OCIError: ORA-00911: invalid character: SELECT * FROM (SELECT DISTINCT "POSTS".id, FIRST_VALUE(#<Arel::Nodes::Ascending:0x000000027777a0>) OVER (PARTITION BY "POSTS".id ORDER BY #<Arel::Nodes::Ascending:0x000000027777a0>) AS alias_0__ FROM "POSTS" LEFT OUTER JOIN "COMMENTS" ON "COMMENTS"."POST_ID" = "POSTS"."ID" INNER JOIN "READERS" ON "POSTS"."ID" = "READERS"."POST_ID" WHERE "READERS"."PERSON_ID" = :a1 AND (comments.id is null) ORDER BY alias_0__) WHERE ROWNUM <= 1
stmt.c:253:in oci8lib_191.so
/home/yahonda/.rvm/gems/ruby-1.9.3-p194@v32stable/gems/ruby-oci8-2.1.2/lib/oci8/oci8.rb:474:in `exec'
/home/yahonda/git/oracle-enhanced/lib/active_record/connection_adapters/oracle_enhanced_oci_connection.rb:143:in `exec'
/home/yahonda/git/oracle-enhanced/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb:639:in `block in exec_query'
/home/yahonda/git/rails/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb:288:in `block in log'
/home/yahonda/git/rails/activesupport/lib/active_support/notifications/instrumenter.rb:18:in `instrument'
/home/yahonda/git/rails/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb:283:in `log'
/home/yahonda/git/oracle-enhanced/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb:1322:in `log'
/home/yahonda/git/oracle-enhanced/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb:619:in `exec_query'
/home/yahonda/git/oracle-enhanced/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb:1276:in `select'
/home/yahonda/git/rails/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb:19:in `select_all'
/home/yahonda/git/rails/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb:63:in `select_all'
/home/yahonda/git/rails/activerecord/lib/active_record/querying.rb:40:in `block in find_by_sql'
/home/yahonda/git/rails/activerecord/lib/active_record/explain.rb:37:in `logging_query_plan'
/home/yahonda/git/rails/activerecord/lib/active_record/querying.rb:39:in `find_by_sql'
/home/yahonda/git/rails/activerecord/lib/active_record/relation.rb:174:in `exec_queries'
/home/yahonda/git/rails/activerecord/lib/active_record/relation.rb:164:in `block in to_a'
/home/yahonda/git/rails/activerecord/lib/active_record/explain.rb:37:in `logging_query_plan'
/home/yahonda/git/rails/activerecord/lib/active_record/relation.rb:163:in `to_a'
/home/yahonda/git/rails/activerecord/lib/active_record/relation/delegation.rb:6:in `collect'
/home/yahonda/git/rails/activerecord/lib/active_record/relation/finder_methods.rb:244:in `construct_limited_ids_condition'
/home/yahonda/git/rails/activerecord/lib/active_record/relation/finder_methods.rb:229:in `apply_join_dependency'
/home/yahonda/git/rails/activerecord/lib/active_record/relation/finder_methods.rb:218:in `construct_relation_for_association_find'
/home/yahonda/git/rails/activerecord/lib/active_record/relation/finder_methods.rb:197:in `find_with_associations'
/home/yahonda/git/rails/activerecord/lib/active_record/relation.rb:174:in `exec_queries'
/home/yahonda/git/rails/activerecord/lib/active_record/relation.rb:164:in `block in to_a'
/home/yahonda/git/rails/activerecord/lib/active_record/explain.rb:37:in `logging_query_plan'
/home/yahonda/git/rails/activerecord/lib/active_record/relation.rb:163:in `to_a'
/home/yahonda/git/rails/activerecord/lib/active_record/relation/finder_methods.rb:326:in `find_first'
/home/yahonda/git/rails/activerecord/lib/active_record/relation/finder_methods.rb:93:in `first'
/home/yahonda/.rvm/gems/ruby-1.9.3-p194@v32stable/bundler/gems/active_record_deprecated_finders-c5418c5119b3/lib/active_record_deprecated_finders/relation.rb:130:in `first'
/home/yahonda/git/rails/activerecord/lib/active_record/associations/collection_association.rb:581:in `first_or_last'
/home/yahonda/git/rails/activerecord/lib/active_record/associations/collection_association.rb:102:in `first'
/home/yahonda/git/rails/activerecord/lib/active_record/associations/collection_proxy.rb:871:in `first'
test/cases/associations/has_many_through_associations_test.rb:595:in `test_find_on_has_many_association_collection_with_include_and_conditions'
/home/yahonda/.rvm/gems/ruby-1.9.3-p194@v32stable/gems/mocha-0.11.4/lib/mocha/integration/mini_test/version_230_to_262.rb:28:in `run'
/home/yahonda/git/rails/activesupport/lib/active_support/testing/setup_and_teardown.rb:37:in `block in run'
/home/yahonda/git/rails/activesupport/lib/active_support/callbacks.rb:347:in `_run__775593665989726039__setup__callbacks'
/home/yahonda/git/rails/activesupport/lib/active_support/callbacks.rb:75:in `run_callbacks'
/home/yahonda/git/rails/activesupport/lib/active_support/testing/setup_and_teardown.rb:36:in `run'
1 tests, 0 assertions, 0 failures, 1 errors, 0 skips
When this test successfully finished with Oracle enhanced adapter with Rails 3-2 stable branch,
order_by
is an Arrayorder_by.blank?
returns trueOn the other hand, when it get an error with rails master branch,
order_by
is an Array same as 3.2order_by.blank?
returns falsep order_by
shows following values.[#<Arel::Nodes::Ascending:0x0000000262e268 @expr=#<struct Arel::Attributes::Attribute relation=#<Arel::Table:0x000000030c3840 @name="posts", @engine=Post(id: integer, author_id: integer, title: string, body: string, type: string, comments_count: integer, taggings_count: integer, taggings_with_delete_all_count: integer, taggings_with_destroy_count: integer, tags_count: integer, tags_with_destroy_count: integer, tags_with_nullify_count: integer), @columns=nil, @aliases=[], @table_alias=nil, @primary_key=nil>, name="id">>]
I'm still trying to address this error. If anyone has any advice, it would be really appreciated.
The Source Code, Documentation, Wiki and Bug Tracker links are out of date in https://rubygems.org/gems/arel
A weird issue happens when your query is ordered, and then paginated to include limit and offset. It returns last couple of rows(this is weird, because there is no strict number the database will return) for all pages, and after few pages it just freezes the query and returns the same rows for any offset and limit.
This is all tested on oracle 11gR2x64, I also ran the query in SQLDeveloper and got the same results. So it's a database problem. I found a workaround that works, and i will make a pull request that solves this issue, at least for me, it should probably be tested by someone else.
Hello guys.. I'm understand that not Areal#matches intention to match with a regexp(#61), but would be interesting if areal offer that with other method(I don't know, something like Areal#regex_match).
Have some situations where we need search with a regexp, e.g. search for some file content_type.
The column: ['image/png', 'image/jpeg', 'image/gif', 'application/pdf', 'application/x-shockwave-flash']
And I want to select only images and flashs file. Would be interesting use:
table[column].regex_match('.(image|flash).').
Thank's
Pretend I have a OutlandishClaim model, and each claim can have many sources.
class OutlandishClaim < ActiveRecord::Base
has_many :sources, :as => :sourceable
scope: sourced, joins(:sources).group("sourceable_id")
end
I'd like to get a list of all the OutlandishClaims that have been sourced. BUT, I can't do the following
OutlandishClaim.sourced.count
because it returns an ordered hash. It seems the count method is reading the group on the scope and thinking that I'd actually called
OutlandishClaim.sourced.count(:group => "sourceable_id")
This behaviour requires anyone using this scope to know to call count again on the hash to get the actual count. A la
OutlandishClaim.sourced.count.count
Unfortunately this is lame and also instantiates each record and then counts them. How it should work is that count ignores any chained group on the scope and only groups if you explicitly pass the option to count. This would allow for consistent counting behaviour, and in cases where I wanted it grouped, I could simply do as the Rails documentation states and pass the option to the count method.
Hello guys,
I'm doing a log analyser where I need to parse SQLs. I did it all with regexp, and I understand that is not the best way to do it.
I would like to add an AST strategy to my code, and I would like to know if Arel supports converting raw SQLs to it's ast.
I'm reading Arel's source, but I couldn't find anything on my own yet.
Thank you
Hello,
The API lacks a way to read projections from a SelectManager, so I'm using this monkey patch:
class Arel::SelectManager
def projections
@ctx.projections
end
end
In contrast, the API currently allows us to append (#project) and set (#projections=) projections.
Thanks for your consideration.
receiving the following error with arel 2.1.5 and rails 3.1 rc4 and rc5. downgrading to arel 2.1.4 resolves the error.
NoMethodError: undefined method `visitor' for #<ActiveRecord::ConnectionAdapters::Mysql2Adapter:0x000001048b4c50>
from /Users/cipater/.rvm/gems/ruby-1.9.2-p180@rails/gems/arel-2.1.5/lib/arel/tree_manager.rb:19:in `visitor'
from /Users/cipater/.rvm/gems/ruby-1.9.2-p180@rails/gems/arel-2.1.5/lib/arel/tree_manager.rb:23:in `to_sql'
from /Users/cipater/.rvm/gems/ruby-1.9.2-p180@rails/gems/activerecord-3.1.0.rc5/lib/active_record/relation.rb:111:in `to_a'
from /Users/cipater/.rvm/gems/ruby-1.9.2-p180@rails/gems/activerecord-3.1.0.rc5/lib/active_record/relation/finder_methods.rb:370:in `find_first'
from /Users/cipater/.rvm/gems/ruby-1.9.2-p180@rails/gems/activerecord-3.1.0.rc5/lib/active_record/relation/finder_methods.rb:122:in `first'
from /Users/cipater/.rvm/gems/ruby-1.9.2-p180@rails/gems/activerecord-3.1.0.rc5/lib/active_record/base.rb:437:in `first'
from (irb):2
from /Users/cipater/.rvm/gems/ruby-1.9.2-p180@rails/gems/railties-3.1.0.rc5/lib/rails/commands/console.rb:45:in `start'
from /Users/cipater/.rvm/gems/ruby-1.9.2-p180@rails/gems/railties-3.1.0.rc5/lib/rails/commands/console.rb:8:in `start'
from /Users/cipater/.rvm/gems/ruby-1.9.2-p180@rails/gems/railties-3.1.0.rc5/lib/rails/commands.rb:40:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>'
I have a Rails app (currently on 3.0.12, but have also tested this on 3.0.13) with a custom rake task:
namespace :db do
task :bootstrap => ["db:drop", "db:create", "db:migrate", "db:seed"]
end
When I run it I get an error "undefined method 'name' for nil:NilClass". It is triggered from a line that calls save
on an object, but the actual error seems to be coming from arel-2.0.10/lib/arel/visitors/to_sql.rb:56
.
When I run all these tasks in tandem in the command line I do not get the error:
rake db:drop && rake db:create && rake db:migrate && rake db:seed
I'm not familiar enough with the internals of rake tasks to understand what the environmental differences might be that would lead to this error in the former case but not the latter, and thus if it is an error in Arel that could be addressed or an error in Rake. Any feedback would be helpful.
Full trace follows:
undefined method `name' for nil:NilClass
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/activesupport-3.0.13/lib/active_support/whiny_nil.rb:48:in `method_missing'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/arel-2.0.10/lib/arel/visitors/to_sql.rb:56:in `block in visit_Arel_Nodes_InsertStatement'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/arel-2.0.10/lib/arel/visitors/to_sql.rb:55:in `map'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/arel-2.0.10/lib/arel/visitors/to_sql.rb:55:in `visit_Arel_Nodes_InsertStatement'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/arel-2.0.10/lib/arel/visitors/visitor.rb:15:in `visit'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/arel-2.0.10/lib/arel/visitors/visitor.rb:5:in `accept'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/arel-2.0.10/lib/arel/visitors/to_sql.rb:18:in `block in accept'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/activerecord-3.0.13/lib/active_record/connection_adapters/abstract/connection_pool.rb:111:in `with_connection'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/arel-2.0.10/lib/arel/visitors/to_sql.rb:16:in `accept'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/arel-2.0.10/lib/arel/tree_manager.rb:20:in `to_sql'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/arel-2.0.10/lib/arel/select_manager.rb:217:in `insert'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/activerecord-3.0.13/lib/active_record/relation.rb:14:in `insert'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/activerecord-3.0.13/lib/active_record/persistence.rb:281:in `create'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/activerecord-3.0.13/lib/active_record/timestamp.rb:47:in `create'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/activerecord-3.0.13/lib/active_record/callbacks.rb:277:in `block in create'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/activesupport-3.0.13/lib/active_support/callbacks.rb:414:in `_run_create_callbacks'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/activerecord-3.0.13/lib/active_record/callbacks.rb:277:in `create'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/activerecord-3.0.13/lib/active_record/persistence.rb:257:in `create_or_update'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/activerecord-3.0.13/lib/active_record/callbacks.rb:273:in `block in create_or_update'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/activesupport-3.0.13/lib/active_support/callbacks.rb:434:in `_run_save_callbacks'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/activerecord-3.0.13/lib/active_record/callbacks.rb:273:in `create_or_update'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/activerecord-3.0.13/lib/active_record/persistence.rb:60:in `save!'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/activerecord-3.0.13/lib/active_record/validations.rb:49:in `save!'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/activerecord-3.0.13/lib/active_record/attribute_methods/dirty.rb:30:in `save!'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/activerecord-3.0.13/lib/active_record/transactions.rb:245:in `block in save!'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/activerecord-3.0.13/lib/active_record/transactions.rb:292:in `block in with_transaction_returning_status'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/activerecord-3.0.13/lib/active_record/connection_adapters/abstract/database_statements.rb:139:in `transaction'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/activerecord-3.0.13/lib/active_record/transactions.rb:207:in `transaction'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/newrelic_rpm-3.1.2/lib/new_relic/agent/method_tracer.rb:491:in `block in transaction_with_trace_ActiveRecord_self_name_transaction'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/newrelic_rpm-3.1.2/lib/new_relic/agent/method_tracer.rb:242:in `trace_execution_scoped'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/newrelic_rpm-3.1.2/lib/new_relic/agent/method_tracer.rb:486:in `transaction_with_trace_ActiveRecord_self_name_transaction'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/activerecord-3.0.13/lib/active_record/transactions.rb:290:in `with_transaction_returning_status'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/activerecord-3.0.13/lib/active_record/transactions.rb:245:in `save!'
db/seeds/development/brands.seeds.rb:49:in `block (2 levels) in <top (required)>'
db/seeds/development/brands.seeds.rb:12:in `times'
db/seeds/development/brands.seeds.rb:12:in `block in <top (required)>'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/activerecord-3.0.13/lib/active_record/connection_adapters/abstract/database_statements.rb:139:in `transaction'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/activerecord-3.0.13/lib/active_record/transactions.rb:207:in `transaction'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/newrelic_rpm-3.1.2/lib/new_relic/agent/method_tracer.rb:491:in `block in transaction_with_trace_ActiveRecord_self_name_transaction'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/newrelic_rpm-3.1.2/lib/new_relic/agent/method_tracer.rb:242:in `trace_execution_scoped'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/newrelic_rpm-3.1.2/lib/new_relic/agent/method_tracer.rb:486:in `transaction_with_trace_ActiveRecord_self_name_transaction'
db/seeds/development/brands.seeds.rb:11:in `<top (required)>'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/activesupport-3.0.13/lib/active_support/dependencies.rb:236:in `load'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/activesupport-3.0.13/lib/active_support/dependencies.rb:236:in `block in load'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/activesupport-3.0.13/lib/active_support/dependencies.rb:225:in `block in load_dependency'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/activesupport-3.0.13/lib/active_support/dependencies.rb:597:in `new_constants_in'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/activesupport-3.0.13/lib/active_support/dependencies.rb:225:in `load_dependency'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/activesupport-3.0.13/lib/active_support/dependencies.rb:236:in `load'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/seedbank-0.0.9/lib/seedbank/dsl.rb:19:in `block in define_seed_task'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/rake-0.9.2.2/lib/rake/task.rb:205:in `call'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/rake-0.9.2.2/lib/rake/task.rb:205:in `block in execute'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/rake-0.9.2.2/lib/rake/task.rb:200:in `each'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/rake-0.9.2.2/lib/rake/task.rb:200:in `execute'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/rake-0.9.2.2/lib/rake/task.rb:158:in `block in invoke_with_call_chain'
/Users/chrisbloom7/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/monitor.rb:201:in `mon_synchronize'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/rake-0.9.2.2/lib/rake/task.rb:151:in `invoke_with_call_chain'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/rake-0.9.2.2/lib/rake/task.rb:176:in `block in invoke_prerequisites'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/rake-0.9.2.2/lib/rake/task.rb:174:in `each'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/rake-0.9.2.2/lib/rake/task.rb:174:in `invoke_prerequisites'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/rake-0.9.2.2/lib/rake/task.rb:157:in `block in invoke_with_call_chain'
/Users/chrisbloom7/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/monitor.rb:201:in `mon_synchronize'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/rake-0.9.2.2/lib/rake/task.rb:151:in `invoke_with_call_chain'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/rake-0.9.2.2/lib/rake/task.rb:176:in `block in invoke_prerequisites'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/rake-0.9.2.2/lib/rake/task.rb:174:in `each'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/rake-0.9.2.2/lib/rake/task.rb:174:in `invoke_prerequisites'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/rake-0.9.2.2/lib/rake/task.rb:157:in `block in invoke_with_call_chain'
/Users/chrisbloom7/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/monitor.rb:201:in `mon_synchronize'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/rake-0.9.2.2/lib/rake/task.rb:151:in `invoke_with_call_chain'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/rake-0.9.2.2/lib/rake/task.rb:176:in `block in invoke_prerequisites'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/rake-0.9.2.2/lib/rake/task.rb:174:in `each'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/rake-0.9.2.2/lib/rake/task.rb:174:in `invoke_prerequisites'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/rake-0.9.2.2/lib/rake/task.rb:157:in `block in invoke_with_call_chain'
/Users/chrisbloom7/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/monitor.rb:201:in `mon_synchronize'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/rake-0.9.2.2/lib/rake/task.rb:151:in `invoke_with_call_chain'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/rake-0.9.2.2/lib/rake/task.rb:144:in `invoke'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/rake-0.9.2.2/lib/rake/application.rb:116:in `invoke_task'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/rake-0.9.2.2/lib/rake/application.rb:94:in `block (2 levels) in top_level'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/rake-0.9.2.2/lib/rake/application.rb:94:in `each'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/rake-0.9.2.2/lib/rake/application.rb:94:in `block in top_level'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/rake-0.9.2.2/lib/rake/application.rb:133:in `standard_exception_handling'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/rake-0.9.2.2/lib/rake/application.rb:88:in `top_level'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/rake-0.9.2.2/lib/rake/application.rb:66:in `block in run'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/rake-0.9.2.2/lib/rake/application.rb:133:in `standard_exception_handling'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/rake-0.9.2.2/lib/rake/application.rb:63:in `run'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/gems/rake-0.9.2.2/bin/rake:33:in `<top (required)>'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/bin/rake:19:in `load'
/Users/chrisbloom7/.rvm/gems/ruby-1.9.2-p180@mms/bin/rake:19:in `<main>'
Tasks: TOP => db:bootstrap => db:seed => db:seed:development => db:seed:development:brands
Just upgraded to Rails RC5 with bundle update and all my tests fail with messages line this:
NoMethodError: undefined method `visitor' for #<ActiveRecord::ConnectionAdapters::MysqlAdapter:0x104d4b818>
arel (2.1.5) lib/arel/tree_manager.rb:19:in `visitor'
arel (2.1.5) lib/arel/tree_manager.rb:23:in `to_sql'
activerecord (3.1.0.rc5) lib/active_record/relation.rb:111:in `to_a'
activerecord (3.1.0.rc5) lib/active_record/relation/finder_methods.rb:155:in `all'
activerecord (3.1.0.rc5) lib/active_record/base.rb:437:in `__send__'
activerecord (3.1.0.rc5) lib/active_record/base.rb:437:in `all'
app/models/listener_image.rb:35:in `random_image'
app/controllers/application_controller.rb:77:in `setup'
MySQL Gem is a 2.8.1, Arel at 2.1.5. Forcing it back to 2.1.4 in Gemfile and all tests pass.
I've been writing some new ARel visitors and ran into a confusing problem where if I run certain custom visitors, some of their visit_*
methods won't be called when expected.
Turns out the issue has to do with the global DISPATCH
cache in Arel::Visitors::Visitor
- since the default visit
method is inherited into subclasses, all visitors share the same cache!
This means if I have a visitor that implements only visit_Arel_Nodes_Join
(but not visit_Arel_Nodes_OuterJoin
and visit_Arel_Nodes_InnerJoin
), the method would never be called if another visitor (e.g. ToSql
) has been run before. This is because the cache would indicate that a Arel::Nodes::OuterJoin
should always be visited via visit_Arel_Nodes_OuterJoin
, regardless of what is implemented in that particular visitor.
One solution I found is to replace the constant with a per-class-object cache:
def self.dispatch_cache
@dispatch_cache ||= Hash.new do |hash, klass|
hash[klass] = "visit_#{(klass.name || '').gsub('::', '_')}"
end
end
def visit object
send self.class.dispatch_cache[object.class], object
rescue NoMethodError => e
raise e if respond_to?(self.class.dispatch_cache[object.class], true)
superklass = object.class.ancestors.find { |klass|
respond_to?(self.class.dispatch_cache[klass], true)
}
raise(TypeError, "Cannot visit #{object.class}") unless superklass
self.class.dispatch_cache[object.class] = self.class.dispatch_cache[superklass]
retry
end
Hopefully this could make it into the next release of ARel.
I'm trying to generate two UPDATE
queries that are functionally equivalent, but one is for MySQL and the other for PostgreSQL:
MySQL:
UPDATE a, (SELECT ...) b
SET a.foo = b.bar
WHERE a.id = b.id
PostgreSQL:
UPDATE a
SET a.foo = b.bar
FROM (SELECT ...) b
WHERE a.id = b.id
I'd like to generate these queries with Arel, because the conditions and updated columns are nontrivial. The MySQL version seems to be possible with some SqlLiteral
hacking. I cannot figure out how to generate the PostgreSQL query, though, since there is no support for FROM
in UPDATE
statements.
If I wrote a patch to support FROM
in UPDATE
statements, would it be included in Arel? If not, is there a (supported) alternative way to use Arel to build non standard SQL queries like these? I'm trying to avoid having to do a lot of string manipulation. Thanks!
Code says it all:
# (Rails console)
Post.count # => 300
Post.group('user_id').count #=> TypeError: Cannot visit Sequel::SQL::AliasedExpression
Note that this code is made simple to illustrate the problem. In reality, I'm also select
ing more fields and joins
ing on another table. Here's my actual code:
scope = Source.joins(:source_channel).select("
sources.*,
MIN(source_channels.oldest_article_at) AS oldest_article_at,
MAX(source_channels.newest_article_at) AS newest_article_at
").group("sources.id")
Version: 3.0.2 and master
[EDIT: master
is also affected.]
2.1.1 of the arel gem won't install on jruby 1.6.1 (untested for other versions).
No idea of the cause of the error but 2.1.0 works fine.
$ gem install arel
System.java:-2:in `arraycopy': java.lang.ArrayIndexOutOfBoundsException
from DefaultResolver.java:111:in `makeTime'
from DefaultResolver.java:277:in `create'
from DefaultResolver.java:317:in `handleScalar'
from DefaultResolver.java:435:in `orgHandler'
from DefaultResolver.java:455:in `node_import'
from DefaultResolver$s$1$0$node_import.gen:65535:in `call'
from CachingCallSite.java:137:in `call'
from RubyLoadHandler.java:40:in `handle'
from Parser.java:300:in `addNode'
from DefaultYAMLParser.java:676:in `yyparse'
from Parser.java:290:in `yechtparse'
from Parser.java:284:in `parse'
from YParser.java:152:in `load'
from YParser$s$0$1$load.gen:65535:in `call'
from JavaMethod.java:630:in `call'
from DynamicMethod.java:205:in `call'
from CachingCallSite.java:282:in `cacheAndCall'
from CachingCallSite.java:139:in `call'
from CallOneArgNode.java:57:in `interpret'
from LocalAsgnNode.java:123:in `interpret'
from NewlineNode.java:103:in `interpret'
from ASTInterpreter.java:74:in `INTERPRET_METHOD'
from InterpretedMethod.java:190:in `call'
from DefaultMethod.java:179:in `call'
from CachingCallSite.java:282:in `cacheAndCall'
from CachingCallSite.java:139:in `call'
from CallOneArgNode.java:57:in `interpret'
from LocalAsgnNode.java:123:in `interpret'
from NewlineNode.java:103:in `interpret'
from BlockNode.java:71:in `interpret'
from ASTInterpreter.java:74:in `INTERPRET_METHOD'
from InterpretedMethod.java:190:in `call'
from DefaultMethod.java:179:in `call'
from CachingCallSite.java:282:in `cacheAndCall'
from CachingCallSite.java:139:in `call'
from CallOneArgNode.java:57:in `interpret'
from NewlineNode.java:103:in `interpret'
from RescueNode.java:216:in `executeBody'
from RescueNode.java:120:in `interpretWithJavaExceptions'
from RescueNode.java:110:in `interpret'
from ASTInterpreter.java:74:in `INTERPRET_METHOD'
from InterpretedMethod.java:190:in `call'
from DefaultMethod.java:179:in `call'
from CachingCallSite.java:282:in `cacheAndCall'
from CachingCallSite.java:139:in `call'
from FCallOneArgNode.java:36:in `interpret'
from InstAsgnNode.java:95:in `interpret'
from NewlineNode.java:103:in `interpret'
from BlockNode.java:71:in `interpret'
from EnsureNode.java:96:in `interpret'
from BeginNode.java:83:in `interpret'
from NewlineNode.java:103:in `interpret'
from WhenOneArgNode.java:36:in `whenSlowTest'
from WhenOneArgNode.java:46:in `when'
from CaseNode.java:133:in `interpret'
from NewlineNode.java:103:in `interpret'
from ASTInterpreter.java:111:in `INTERPRET_BLOCK'
from InterpretedBlock.java:374:in `evalBlockBody'
from InterpretedBlock.java:347:in `yield'
from InterpretedBlock.java:304:in `yield'
from Block.java:130:in `yield'
from YieldNode.java:112:in `interpret'
from NewlineNode.java:103:in `interpret'
from BlockNode.java:71:in `interpret'
from ASTInterpreter.java:111:in `INTERPRET_BLOCK'
from InterpretedBlock.java:374:in `evalBlockBody'
from InterpretedBlock.java:295:in `yield'
from InterpretedBlock.java:229:in `yieldSpecific'
from Block.java:99:in `yieldSpecific'
from RubyKernel.java:1418:in `loop'
from RubyKernel$s$0$0$loop.gen:65535:in `call'
from CachingCallSite.java:272:in `cacheAndCall'
from CachingCallSite.java:114:in `callBlock'
from CachingCallSite.java:123:in `callIter'
from FCallNoArgBlockNode.java:32:in `interpret'
from NewlineNode.java:103:in `interpret'
from ASTInterpreter.java:74:in `INTERPRET_METHOD'
from InterpretedMethod.java:169:in `call'
from DefaultMethod.java:171:in `call'
from CachingCallSite.java:272:in `cacheAndCall'
from CachingCallSite.java:114:in `callBlock'
from CachingCallSite.java:123:in `callIter'
from CallNoArgBlockNode.java:64:in `interpret'
from NewlineNode.java:103:in `interpret'
from BlockNode.java:71:in `interpret'
from ASTInterpreter.java:74:in `INTERPRET_METHOD'
from InterpretedMethod.java:255:in `call'
from DefaultMethod.java:203:in `call'
from CachingCallSite.java:312:in `cacheAndCall'
from CachingCallSite.java:182:in `callBlock'
from CachingCallSite.java:186:in `call'
from RubyClass.java:806:in `newInstance'
from RubyClass$i$newInstance.gen:65535:in `call'
from JavaMethod.java:283:in `call'
from WrapperMethod.java:62:in `call'
from CachingCallSite.java:302:in `cacheAndCall'
from CachingCallSite.java:173:in `call'
from FCallTwoArgNode.java:38:in `interpret'
from LocalAsgnNode.java:123:in `interpret'
from NewlineNode.java:103:in `interpret'
from BlockNode.java:71:in `interpret'
from EnsureNode.java:96:in `interpret'
from ASTInterpreter.java:74:in `INTERPRET_METHOD'
from InterpretedMethod.java:255:in `call'
from DefaultMethod.java:203:in `call'
from CachingCallSite.java:312:in `cacheAndCall'
from CachingCallSite.java:182:in `callBlock'
from CachingCallSite.java:186:in `call'
from CallTwoArgBlockPassNode.java:62:in `interpret'
from NewlineNode.java:103:in `interpret'
from BlockNode.java:71:in `interpret'
from ASTInterpreter.java:74:in `INTERPRET_METHOD'
from InterpretedMethod.java:298:in `call'
from DefaultMethod.java:219:in `call'
from CachingCallSite.java:332:in `cacheAndCall'
from CachingCallSite.java:216:in `callBlock'
from CachingCallSite.java:225:in `callIter'
from CallThreeArgBlockNode.java:64:in `interpret'
from NewlineNode.java:103:in `interpret'
from BlockNode.java:71:in `interpret'
from ASTInterpreter.java:74:in `INTERPRET_METHOD'
from InterpretedMethod.java:276:in `call'
from DefaultMethod.java:211:in `call'
from CachingCallSite.java:322:in `cacheAndCall'
from CachingCallSite.java:207:in `call'
from FCallThreeArgNode.java:40:in `interpret'
from NewlineNode.java:103:in `interpret'
from ASTInterpreter.java:111:in `INTERPRET_BLOCK'
from InterpretedBlock.java:374:in `evalBlockBody'
from InterpretedBlock.java:347:in `yield'
from InterpretedBlock.java:304:in `yield'
from Block.java:130:in `yield'
from RubyIO.java:1121:in `open'
from RubyKernel.java:298:in `open'
from RubyKernel$s$0$2$open.gen:65535:in `call'
from DynamicMethod.java:217:in `call'
from CachingCallSite.java:312:in `cacheAndCall'
from CachingCallSite.java:182:in `callBlock'
from CachingCallSite.java:191:in `callIter'
from FCallTwoArgBlockNode.java:34:in `interpret'
from NewlineNode.java:103:in `interpret'
from RescueNode.java:216:in `executeBody'
from RescueNode.java:120:in `interpretWithJavaExceptions'
from RescueNode.java:110:in `interpret'
from BeginNode.java:83:in `interpret'
from NewlineNode.java:103:in `interpret'
from IfNode.java:119:in `interpret'
from IfNode.java:119:in `interpret'
from NewlineNode.java:103:in `interpret'
from BlockNode.java:71:in `interpret'
from ASTInterpreter.java:74:in `INTERPRET_METHOD'
from InterpretedMethod.java:233:in `call'
from DefaultMethod.java:195:in `call'
from CachingCallSite.java:302:in `cacheAndCall'
from CachingCallSite.java:173:in `call'
from CallTwoArgNode.java:59:in `interpret'
from InstAsgnNode.java:95:in `interpret'
from NewlineNode.java:103:in `interpret'
from RescueNode.java:216:in `executeBody'
from RescueNode.java:120:in `interpretWithJavaExceptions'
from RescueNode.java:110:in `interpret'
from BeginNode.java:83:in `interpret'
from NewlineNode.java:103:in `interpret'
from ASTInterpreter.java:74:in `INTERPRET_METHOD'
from InterpretedMethod.java:147:in `call'
from DefaultMethod.java:163:in `call'
from CachingCallSite.java:262:in `cacheAndCall'
from CachingCallSite.java:105:in `call'
from VCallNode.java:85:in `interpret'
from NewlineNode.java:103:in `interpret'
from BlockNode.java:71:in `interpret'
from ASTInterpreter.java:74:in `INTERPRET_METHOD'
from InterpretedMethod.java:255:in `call'
from DefaultMethod.java:203:in `call'
from CachingCallSite.java:312:in `cacheAndCall'
from CachingCallSite.java:182:in `callBlock'
from CachingCallSite.java:186:in `call'
from RubyClass.java:806:in `newInstance'
from RubyClass$i$newInstance.gen:65535:in `call'
from JavaMethod.java:283:in `call'
from CachingCallSite.java:302:in `cacheAndCall'
from CachingCallSite.java:173:in `call'
from CallTwoArgNode.java:59:in `interpret'
from DAsgnNode.java:110:in `interpret'
from NewlineNode.java:103:in `interpret'
from BlockNode.java:71:in `interpret'
from ASTInterpreter.java:111:in `INTERPRET_BLOCK'
from InterpretedBlock.java:374:in `evalBlockBody'
from InterpretedBlock.java:347:in `yield'
from InterpretedBlock.java:304:in `yield'
from Block.java:130:in `yield'
from RubyArray.java:1595:in `eachCommon'
from RubyArray.java:1602:in `each'
from RubyArray$i$0$0$each.gen:65535:in `call'
from CachingCallSite.java:272:in `cacheAndCall'
from CachingCallSite.java:114:in `callBlock'
from CachingCallSite.java:123:in `callIter'
from CallNoArgBlockNode.java:64:in `interpret'
from NewlineNode.java:103:in `interpret'
from BlockNode.java:71:in `interpret'
from ASTInterpreter.java:74:in `INTERPRET_METHOD'
from InterpretedMethod.java:233:in `call'
from DefaultMethod.java:195:in `call'
from CachingCallSite.java:302:in `cacheAndCall'
from CachingCallSite.java:173:in `call'
from CallTwoArgNode.java:59:in `interpret'
from NewlineNode.java:103:in `interpret'
from BlockNode.java:71:in `interpret'
from RescueNode.java:216:in `executeBody'
from RescueNode.java:120:in `interpretWithJavaExceptions'
from RescueNode.java:110:in `interpret'
from BeginNode.java:83:in `interpret'
from NewlineNode.java:103:in `interpret'
from ASTInterpreter.java:111:in `INTERPRET_BLOCK'
from InterpretedBlock.java:374:in `evalBlockBody'
from InterpretedBlock.java:347:in `yield'
from InterpretedBlock.java:304:in `yield'
from Block.java:130:in `yield'
from RubyArray.java:1595:in `eachCommon'
from RubyArray.java:1602:in `each'
from RubyArray$i$0$0$each.gen:65535:in `call'
from CachingCallSite.java:272:in `cacheAndCall'
from CachingCallSite.java:114:in `callBlock'
from CachingCallSite.java:123:in `callIter'
from CallNoArgBlockNode.java:64:in `interpret'
from NewlineNode.java:103:in `interpret'
from BlockNode.java:71:in `interpret'
from ASTInterpreter.java:74:in `INTERPRET_METHOD'
from InterpretedMethod.java:147:in `call'
from DefaultMethod.java:163:in `call'
from CachingCallSite.java:262:in `cacheAndCall'
from CachingCallSite.java:105:in `call'
from VCallNode.java:85:in `interpret'
from NewlineNode.java:103:in `interpret'
from IfNode.java:119:in `interpret'
from IfNode.java:119:in `interpret'
from NewlineNode.java:103:in `interpret'
from BlockNode.java:71:in `interpret'
from ASTInterpreter.java:74:in `INTERPRET_METHOD'
from InterpretedMethod.java:190:in `call'
from DefaultMethod.java:179:in `call'
from CachingCallSite.java:282:in `cacheAndCall'
from CachingCallSite.java:139:in `call'
from CallSpecialArgNode.java:67:in `interpret'
from NewlineNode.java:103:in `interpret'
from BlockNode.java:71:in `interpret'
from CaseNode.java:138:in `interpret'
from NewlineNode.java:103:in `interpret'
from BlockNode.java:71:in `interpret'
from ASTInterpreter.java:74:in `INTERPRET_METHOD'
from InterpretedMethod.java:190:in `call'
from DefaultMethod.java:179:in `call'
from CachingCallSite.java:282:in `cacheAndCall'
from CachingCallSite.java:139:in `call'
from FCallOneArgNode.java:36:in `interpret'
from NewlineNode.java:103:in `interpret'
from RescueNode.java:216:in `executeBody'
from RescueNode.java:120:in `interpretWithJavaExceptions'
from RescueNode.java:110:in `interpret'
from ASTInterpreter.java:74:in `INTERPRET_METHOD'
from InterpretedMethod.java:190:in `call'
from DefaultMethod.java:179:in `call'
from CachingCallSite.java:282:in `cacheAndCall'
from CachingCallSite.java:139:in `call'
from CallOneArgNode.java:57:in `interpret'
from NewlineNode.java:103:in `interpret'
from BlockNode.java:71:in `interpret'
from ASTInterpreter.java:74:in `INTERPRET_METHOD'
from InterpretedMethod.java:190:in `call'
from DefaultMethod.java:179:in `call'
from CachingCallSite.java:282:in `cacheAndCall'
from CachingCallSite.java:139:in `call'
from /usr/local/rvm/rubies/jruby-1.6.1/bin/gem:25:in `chained_0_rescue_1$RUBY$SYNTHETIC__file__'
from /usr/local/rvm/rubies/jruby-1.6.1/bin/gem:24:in `__file__'
from /usr/local/rvm/rubies/jruby-1.6.1/bin/gem:-1:in `load'
from Ruby.java:671:in `runScript'
from Ruby.java:575:in `runNormally'
from Ruby.java:424:in `runFromMain'
from Main.java:278:in `doRunFromMain'
from Main.java:198:in `internalRun'
from Main.java:164:in `run'
from Main.java:148:in `run'
from Main.java:128:in `main'
I have a simple model
class User
has_many :logs
class Logs
related in the usual way through the foreign key logs.user_id. I'm trying to do the following using Arel and according to the Arel doc it should work.
u_t = User.arel_table
l_t = Log.arel_table
counts = l_t.
group(l_t[:user_id]).
project(
l_t[:user_id].as("user_id"),
l_t[:user_id].count.as("count_all")
).as "counts"
users = u_t.
join(counts).
on(u_t[:id].
eq(counts[:user_id])).
project("*")
puts users.to_sql
When I do that I get an error. The SQL I would expect to be generated would be something like this
select * from users
join ( select logs.user_id as user_id, count(logs.user_id) as count_all group by logs.user_id ) counts
on users.id = counts.user_id
The original fork of Arel suggest queries like this are possible but perhaps Arel has been re-factored
and now this is not possible.
With the refactoring to use Arel::Nodes::JoinSource
to model joins in ARel 2.1, it seems that we can no longer express joins where the right hand side of the join is another join. In particular, Arel::Visitors::ToSql
currently assumes that a JoinSource
is always the source of a Arel::Nodes::SelectCore
and thus puts in the "FROM" keyword at all times.
To allow JoinSource
to be usable as the RHS of a join, I worked around this by changing ToSql#visit_Arel_Nodes_SelectCore
to:
def visit_Arel_Nodes_SelectCore o
[
"SELECT",
(visit(o.top) if o.top),
(visit(o.set_quantifier) if o.set_quantifier),
("#{o.projections.map { |x| visit x }.join ', '}" unless o.projections.empty?),
("FROM #{visit(o.source)}" if (o.source && (!o.is_a?(Arel::Nodes::JoinSource) || (!o.source.left && o.source.right.empty?)))),
("WHERE #{o.wheres.map { |x| visit x }.join ' AND ' }" unless o.wheres.empty?),
("GROUP BY #{o.groups.map { |x| visit x }.join ', ' }" unless o.groups.empty?),
(visit(o.having) if o.having),
].compact.join ' '
end
...and ToSql#visit_Arel_Nodes_JoinSource
to:
def visit_Arel_Nodes_JoinSource o
return unless o.left || !o.right.empty?
[
(visit(o.left) if o.left),
o.right.map { |j| visit j }.join(' ')
].compact.join ' '
end
At the same time, MySQL requires that a join appearing on the RHS of another join to be parenthesized even though it is unambiguous. So I had to change Arel::Visitors::MySQL
to account for this:
def visit_Arel_Nodes_OuterJoin o
left_result = case o.left
when Arel::Nodes::JoinSource
"(#{visit o.left})"
else
visit o.left
end
"LEFT OUTER JOIN #{left_result} #{visit o.right}"
end
def visit_Arel_Nodes_InnerJoin o
left_result = case o.left
when Arel::Nodes::JoinSource
"(#{visit o.left})"
else
visit o.left
end
"INNER JOIN #{left_result} #{visit o.right if o.right}"
end
We're using the mysql2 gem and we noticed this error when we arel updated to 2.1.5. We went back to 2.1.4 and everything went back to normal.
undefined method `visitor' for #ActiveRecord::ConnectionAdapters::Mysql2Adapter:0x00000103dea3d8
Hello,
In Arel 3.0.2, some aggregations ignore the #distinct=
setting when converted into SQL:
Loading development environment (Rails 3.2.8)
## ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-linux]
>> ActiveRecord::Base.connection.adapter_name
"SQLite"
>> Arel::VERSION
"3.0.2"
>> a=Arel.star.count; a.distinct=true; p a; a.to_sql
#<Arel::Nodes::Count:0x00000003de3728 @expressions=["*"], @alias=nil, @distinct=true>
"COUNT(DISTINCT *)"
>> a=Arel.star.sum; a.distinct=true; p a; a.to_sql
#<Arel::Nodes::Sum:0x000000040da738 @expressions=["*"], @alias="sum_id", @distinct=true>
"SUM(*) AS sum_id"
>> a=Arel.star.average; a.distinct=true; p a; a.to_sql
#<Arel::Nodes::Avg:0x00000003e3ccb0 @expressions=["*"], @alias="avg_id", @distinct=true>
"AVG(*) AS avg_id"
>> a=Arel.star.minimum; a.distinct=true; p a; a.to_sql
#<Arel::Nodes::Min:0x00000003e43b78 @expressions=["*"], @alias="min_id", @distinct=true>
"MIN(*) AS min_id"
>> a=Arel.star.maximum; a.distinct=true; p a; a.to_sql
#<Arel::Nodes::Max:0x00000003e4a4f0 @expressions=["*"], @alias="max_id", @distinct=true>
"MAX(*) AS max_id"
I expect them all to emit (DISTINCT *)
for their function call parameter list in SQL.
Thanks for your consideration.
Hi,
as I have also reported to the rails tracker [1], due to gemification of the Ruby standard library [2], I think you should include bigdecimal gem in gemspec of arel - if new version of bigdecimal is released, you will need to add it there anyway, so that bundler doesn't pick up the bigdecimal that is bundled in the standard Ruby installation.
Thank you!
[1] rails/rails#5355
[2] https://bugs.ruby-lang.org/issues/5481
On History.txt, I see:
Arel::Table#columns is deprecated and will be removed in 3.0.0 with no replacement.
But look this behavior:
ruby-1.9.2-p180 :009 > User
=> User(id: integer, name: string, email: string, encrypted_password: string, created_at: datetime, updated_at: datetime, reset_password_token: string, reset_password_sent_at: datetime, profile_id: integer)
ruby-1.9.2-p180 :012 > User.arel_table.columns.detect{|column| column.name == :id}
((irb):12:in `irb_binding') Arel::Table#columns is deprecated and will be removed in
Arel 3.0.0 with no replacement. PEW PEW PEW!!!
=> #<struct Arel::Attributes::Integer relation=#<Arel::Table:0x00000102c66e40 @name="users", @engine=ActiveRecord::Base, @columns=[#<struct Arel::Attributes::Integer:...>, #<struct Arel::Attributes::String relation=#<Arel::Table:0x00000102c66e40 ...>, name=:name>, #<struct Arel::Attributes::String relation=#<Arel::Table:0x00000102c66e40 ...>, name=:email>, #<struct Arel::Attributes::String relation=#<Arel::Table:0x00000102c66e40 ...>, name=:encrypted_password>, #<struct Arel::Attributes::Time relation=#<Arel::Table:0x00000102c66e40 ...>, name=:created_at>, #<struct Arel::Attributes::Time relation=#<Arel::Table:0x00000102c66e40 ...>, name=:updated_at>, #<struct Arel::Attributes::String relation=#<Arel::Table:0x00000102c66e40 ...>, name=:reset_password_token>, #<struct Arel::Attributes::Time relation=#<Arel::Table:0x00000102c66e40 ...>, name=:reset_password_sent_at>, #<struct Arel::Attributes::Integer relation=#<Arel::Table:0x00000102c66e40 ...>, name=:profile_id>], @aliases=[], @table_alias=nil, @primary_key=nil>, name=:id>
ruby-1.9.2-p180 :013 > User.arel_table[:id]
=> #<struct Arel::Attributes::Attribute relation=#<Arel::Table:0x00000102c66e40 @name="users", @engine=ActiveRecord::Base, @columns=[#<struct Arel::Attributes::Integer relation=#<Arel::Table:0x00000102c66e40 ...>, name=:id>, #<struct Arel::Attributes::String relation=#<Arel::Table:0x00000102c66e40 ...>, name=:name>, #<struct Arel::Attributes::String relation=#<Arel::Table:0x00000102c66e40 ...>, name=:email>, #<struct Arel::Attributes::String relation=#<Arel::Table:0x00000102c66e40 ...>, name=:encrypted_password>, #<struct Arel::Attributes::Time relation=#<Arel::Table:0x00000102c66e40 ...>, name=:created_at>, #<struct Arel::Attributes::Time relation=#<Arel::Table:0x00000102c66e40 ...>, name=:updated_at>, #<struct Arel::Attributes::String relation=#<Arel::Table:0x00000102c66e40 ...>, name=:reset_password_token>, #<struct Arel::Attributes::Time relation=#<Arel::Table:0x00000102c66e40 ...>, name=:reset_password_sent_at>, #<struct Arel::Attributes::Integer relation=#<Arel::Table:0x00000102c66e40 ...>, name=:profile_id>], @aliases=[], @table_alias=nil, @primary_key=nil>, name=:id>
When I get column from Arel::Table#columns
, I know the column is an integer ( Arel::Attributes::Integer
), but on second I don't (Arel::Attributes::Attribute
).
In this case, I don't know if I should use eq
or matches
on PostgreSQL database.
This is the expected behavior? How can I detect the column type with Arel::Attributes::Attribute
?
Would a patch to support VARIANCE()
be welcomed? MySQL and Postgres, likely among others, support this aggregation function to calculate variance (related to standard deviation).
This would allow in Rails:
Person.calculate(:variance, :age)
Notably, it's not supported in sqlite so I'm asking before I go to the effort of making the patch.
As far as I can tell, it's currently not possible to apply conditions to models that are eager loaded using the includes
method. For instance, given the following models:
class Shift < ActiveRecord::Base
has_many :schedules
end
class Schedule < ActiveRecord::Base
belongs_to :shift
end
And a desire to select all shifts, eager loading any schedules that occur on a given date, one would think to do something like:
Shift.includes(:schedules).where(:schedules => { :occurs_on => Date.today })
Unfortunately, this will cause all shifts without schedules for the given day to be removed from the results as the filtering occurs in the where
clause.
Shouldn't there be a way to apply conditions on the associated objects to be eager loaded? The best I've been able to come up with is:
Shift.includes(:schedules).where("schedules.occurs_on is null OR schedules.occurs_on = '#{Date.today}'")
This is ugly and non obvious. Ideally, I'd be able to say:
Shift.includes(:schedules => {:occurs_on => Date.today}}
But when doing this, ActiveRecord errors saying that :occurs_on is not a relation. This syntax is already used for nesting includes.
Any ideas on how to proceed?
Hello,
I'm having issues trying to save my rails object.
The exception is:
Encoding::CompatibilityError: incompatible character encodings: UTF-8 and ASCII-8BIT
My backtrace says:
[GEM_ROOT]/gems/arel-2.0.10/lib/arel/visitors/to_sql.rb:69:in join' [GEM_ROOT]/gems/arel-2.0.10/lib/arel/visitors/to_sql.rb:69:in
visit_Arel_Nodes_Values'
[GEM_ROOT]/gems/arel-2.0.10/lib/arel/visitors/visitor.rb:15:in visit' [GEM_ROOT]/gems/arel-2.0.10/lib/arel/visitors/to_sql.rb:59:in
visit_Arel_Nodes_InsertStatement'
[GEM_ROOT]/gems/arel-2.0.10/lib/arel/visitors/visitor.rb:15:in visit' [GEM_ROOT]/gems/arel-2.0.10/lib/arel/visitors/visitor.rb:5:in
accept'
[GEM_ROOT]/gems/arel-2.0.10/lib/arel/visitors/to_sql.rb:18:in block in accept' [GEM_ROOT]/gems/activerecord-3.0.9/lib/active_record/connection_adapters/abstract/connection_pool.rb:111:in
with_connection'
[GEM_ROOT]/gems/arel-2.0.10/lib/arel/visitors/to_sql.rb:16:in accept' [GEM_ROOT]/gems/arel-2.0.10/lib/arel/tree_manager.rb:20:in
to_sql'
[GEM_ROOT]/gems/arel-2.0.10/lib/arel/select_manager.rb:217:in insert' [GEM_ROOT]/gems/activerecord-3.0.9/lib/active_record/relation.rb:14:in
insert'
[GEM_ROOT]/gems/activerecord-3.0.9/lib/active_record/persistence.rb:274:in create' [GEM_ROOT]/gems/activerecord-3.0.9/lib/active_record/timestamp.rb:47:in
create'
[GEM_ROOT]/gems/activerecord-3.0.9/lib/active_record/callbacks.rb:277:in block in create' [GEM_ROOT]/gems/activesupport-3.0.9/lib/active_support/callbacks.rb:414:in
_run_create_callbacks'
[GEM_ROOT]/gems/activerecord-3.0.9/lib/active_record/callbacks.rb:277:in create' [GEM_ROOT]/gems/activerecord-3.0.9/lib/active_record/persistence.rb:250:in
create_or_update'
[GEM_ROOT]/gems/activerecord-3.0.9/lib/active_record/callbacks.rb:273:in block in create_or_update' [GEM_ROOT]/gems/activesupport-3.0.9/lib/active_support/callbacks.rb:444:in
_run_save_callbacks'
[GEM_ROOT]/gems/activerecord-3.0.9/lib/active_record/callbacks.rb:273:in create_or_update' [GEM_ROOT]/gems/activerecord-3.0.9/lib/active_record/persistence.rb:40:in
save'
[GEM_ROOT]/gems/activerecord-3.0.9/lib/active_record/validations.rb:43:in save' [GEM_ROOT]/gems/activerecord-3.0.9/lib/active_record/attribute_methods/dirty.rb:21:in
save'
[GEM_ROOT]/gems/activerecord-3.0.9/lib/active_record/transactions.rb:240:in block (2 levels) in save' [GEM_ROOT]/gems/activerecord-3.0.9/lib/active_record/transactions.rb:292:in
block in with_transaction_returning_status'
[GEM_ROOT]/gems/activerecord-3.0.9/lib/active_record/connection_adapters/abstract/database_statements.rb:139:in transaction' [GEM_ROOT]/gems/activerecord-3.0.9/lib/active_record/transactions.rb:207:in
transaction'
[GEM_ROOT]/gems/activerecord-3.0.9/lib/active_record/transactions.rb:290:in with_transaction_returning_status' [GEM_ROOT]/gems/activerecord-3.0.9/lib/active_record/transactions.rb:240:in
block in save'
[GEM_ROOT]/gems/activerecord-3.0.9/lib/active_record/transactions.rb:251:in rollback_active_record_state!' [GEM_ROOT]/gems/activerecord-3.0.9/lib/active_record/transactions.rb:239:in
save'
app/controllers/lambs_controller.rb:245:in block in create' [GEM_ROOT]/gems/activerecord-3.0.9/lib/active_record/connection_adapters/abstract/database_statements.rb:139:in
transaction'
[GEM_ROOT]/gems/activerecord-3.0.9/lib/active_record/transactions.rb:207:in transaction' app/controllers/my_controller.rb:229:in
create'
i'm using ruby 1.9.2p180 (2011-02-18 revision 30909) [i686-linux] and adjusted the encoding as utf-8 either on database.yml and my_controller.rb with (#encoding:utf-8)
How to solve this issue?
thank you.
This is a duplicate of the email I had sent to you, just wanted to get an open log going. Basically I found out that rails calculations.rb #perform_calculation method which greps the AST like so:
unless arel.ast.grep(Arel::Nodes::OuterJoin).empty?
distinct = true
end
Will cause my Ascending/Descending ordering objects from there on afterward to blow up. A simple test I wrote illustrates the problem.
diff --git a/test/test_select_manager.rb b/test/test_select_manager.rb
index e948aec..119ad3e 100644
--- a/test/test_select_manager.rb
+++ b/test/test_select_manager.rb
@@ -412,6 +412,15 @@ module Arel
ast = mgr.ast
mgr.visitor.accept(ast).must_equal mgr.to_sql
end
+ it 'should allow orders to work when the ast is grepped' do
+ table = Table.new :users
+ mgr = table.from table
+ mgr.project Arel.sql '*'
+ mgr.from table
+ mgr.orders << Arel::Nodes::Ascending.new(Arel.sql('foo'))
+ mgr.ast.grep(Arel::Nodes::OuterJoin)
+ mgr.to_sql.must_be_like %{ SELECT * FROM "users" ORDER BY foo ASC }
+ end
end
describe 'taken' do
The error throw looks like this. Without the ast.grep, the test would pass.
1) Error:
test_0002_should_allow_orders_to_work_when_the_ast_is_grepped(select manager::ast):
TypeError: Cannot visit Arel::Nodes::Ascending
./lib/arel/visitors/visitor.rb:25:in `visit'
./lib/arel/visitors/to_sql.rb:124:in `visit_Arel_Nodes_SelectStatement'
./lib/arel/visitors/to_sql.rb:124:in `map'
./lib/arel/visitors/to_sql.rb:124:in `visit_Arel_Nodes_SelectStatement'
./lib/arel/visitors/visitor.rb:19:in `send'
./lib/arel/visitors/visitor.rb:19:in `visit'
./lib/arel/visitors/visitor.rb:5:in `accept'
./lib/arel/visitors/to_sql.rb:20:in `accept'
./test/support/fake_record.rb:85:in `with_connection'
./lib/arel/visitors/to_sql.rb:18:in `accept'
./lib/arel/tree_manager.rb:21:in `to_sql'
./test/test_select_manager.rb:422:in `test_0002_should_allow_orders_to_work_when_the_ast_is_grepped'
Hello, I am trying to use the Arel#extract method. I have seen an example in a test case in test_extract.rb in the source but when I try to reproduce it in my app, I get undefined method.
table = Arel::Table.new :users
puts table[:created_at].extract('date').to_sql
=> NoMethodError: undefined method `extract' for #<Arel::Attributes::Attribute:0x7..8>
I have some code that tries to generate UNIONs of 3 or more subqueries, and I ran into a SQL generation problem for MySQL. The problem is that MySQL disallows parentheses around UNION operands. For example, this is bad syntax for MySQL:
((a UNION b) UNION c)
...instead, MySQL wants this:
(a UNION b UNION c)
I have a patch which seems to work for Arel::Visitors::MySQL
:
def visit_Arel_Nodes_Union o, suppress_parens = false
left_result = case o.left
when Arel::Nodes::Union
visit_Arel_Nodes_Union o.left, true
else
visit o.left
end
right_result = case o.right
when Arel::Nodes::Union
visit_Arel_Nodes_Union o.right, true
else
visit o.right
end
if suppress_parens
"#{left_result} UNION #{right_result}"
else
"( #{left_result} UNION #{right_result} )"
end
end
1) Error:
test_0001_should_be_thread_safe_around_usage_of_last_column(the to_sql visitor):
fatal: deadlock detected
/builddir/build/BUILDROOT/rubygem-arel-2.0.10-1.fc18.x86_64/usr/share/gems/gems/arel-2.0.10/test/visitors/test_to_sql.rb:22:in `join'
/builddir/build/BUILDROOT/rubygem-arel-2.0.10-1.fc18.x86_64/usr/share/gems/gems/arel-2.0.10/test/visitors/test_to_sql.rb:22:in `block (2 levels) in <module:Visitors>'
Seems to be due to 2c5a438. I am testing it with Ruby 1.9.3 if that makes any difference
As it stands, UNION, INTERSECT and EXCEPT are implemented and Binary nodes on two ASTs - but the SQL spec and (at least Postgres's) implementations treat them more like a sub-select. Check out:
http://www.postgresql.org/docs/9.1/static/sql-select.html
and
http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt (page 195)
Specifically, the only correct way to limit a union is like:
SELECT * FROM table {} UNION SELECT * FROM table LIMIT 100
LIMIT isn't valid (although it's accepted) at {} and it should apply to the overall query, not the second tree.
Regardless, SelectManager#{union,intersect,except} pass in two ASTs to the Binary nodes, so limits get removed anyway.
Having to do something like
Arel.sql("my_stored_procedure(#{yadda}, #{nada})") is well, a bad thing to do but using Arel by itself
there's no way to use named binds which would be incredibly convenient .
If there is a way to use binds and I don't know about that it what would be great!
Hello,
In arel 2.2.3, I observe that take(
n)
is being forced into LIMIT -1
(regardless of n value) when skip() is also used:
Loading development environment (Rails 3.1.3)
## ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-linux]
>> Arel::Table.new(:foobar).take(3).skip(3).to_sql
"SELECT FROM \"foobar\" LIMIT -1 OFFSET 3"
>> Arel::Table.new(:foobar).take(2).skip(3).to_sql
"SELECT FROM \"foobar\" LIMIT -1 OFFSET 3"
>> Arel::Table.new(:foobar).take(1).skip(3).to_sql
"SELECT FROM \"foobar\" LIMIT -1 OFFSET 3"
>> Arel::Table.new(:foobar).take(1).to_sql
"SELECT FROM \"foobar\" LIMIT 1"
>> Arel::Table.new(:foobar).take(2).to_sql
"SELECT FROM \"foobar\" LIMIT 2"
>> Arel::Table.new(:foobar).take(3).to_sql
"SELECT FROM \"foobar\" LIMIT 3"
I expect take(
n)
to become LIMIT
n in the generated SQL query.
Thanks for your consideration.
It would be awesome if arel supported least
and greatest
.
Here's the documentation I've found for postgres and mysql.
http://www.postgresql.org/docs/current/static/functions-conditional.html#FUNCTIONS-GREATEST-LEAST
http://dev.mysql.com/doc/refman/5.0/en/comparison-operators.html#function_least
I'd be up for trying to write a pull-request, any hints on where to start? I'm guessing that I'd need to make a new node in lib/arel/nodes
as a subclass of Function or at the bottom of lib/arel/nodes/function
with Sum, Max, Min, etc ...
I'm using Sequel and Rails in a project. Upgrading to Rails 3.2.8 from 3.2.6 caused the following backtrace:
> User.group('username').count
(0.5ms) SHOW max_identifier_length
TypeError: Cannot visit Sequel::SQL::AliasedExpression
from /Users/joe/projects/tanga/bundler/ruby/1.9.1/gems/arel-3.0.2/lib/arel/visitors/visitor.rb:25:in `rescue in visit'
from /Users/joe/projects/tanga/bundler/ruby/1.9.1/gems/arel-3.0.2/lib/arel/visitors/visitor.rb:19:in `visit'
from /Users/joe/projects/tanga/bundler/ruby/1.9.1/gems/arel-3.0.2/lib/arel/visitors/to_sql.rb:134:in `block in visit_Arel_Nodes_SelectCore'
from /Users/joe/projects/tanga/bundler/ruby/1.9.1/gems/arel-3.0.2/lib/arel/visitors/to_sql.rb:134:in `map'
from /Users/joe/projects/tanga/bundler/ruby/1.9.1/gems/arel-3.0.2/lib/arel/visitors/to_sql.rb:134:in `visit_Arel_Nodes_SelectCore'
from /Users/joe/projects/tanga/bundler/ruby/1.9.1/gems/arel-3.0.2/lib/arel/visitors/to_sql.rb:121:in `block in visit_Arel_Nodes_SelectStatement'
from /Users/joe/projects/tanga/bundler/ruby/1.9.1/gems/arel-3.0.2/lib/arel/visitors/to_sql.rb:121:in `map'
from /Users/joe/projects/tanga/bundler/ruby/1.9.1/gems/arel-3.0.2/lib/arel/visitors/to_sql.rb:121:in `visit_Arel_Nodes_SelectStatement'
from /Users/joe/projects/tanga/bundler/ruby/1.9.1/gems/arel-3.0.2/lib/arel/visitors/visitor.rb:19:in `visit'
from /Users/joe/projects/tanga/bundler/ruby/1.9.1/gems/arel-3.0.2/lib/arel/visitors/visitor.rb:5:in `accept'
from /Users/joe/projects/tanga/bundler/ruby/1.9.1/gems/arel-3.0.2/lib/arel/visitors/to_sql.rb:19:in `accept'
from /Users/joe/projects/tanga/bundler/ruby/1.9.1/bundler/gems/rails-c6854813c824/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb:7:in `to_sql'
from /Users/joe/projects/tanga/bundler/ruby/1.9.1/bundler/gems/rails-c6854813c824/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb:18:in `select_all'
from /Users/joe/projects/tanga/bundler/ruby/1.9.1/bundler/gems/rails-c6854813c824/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb:63:in `select_all'
from /Users/joe/projects/tanga/bundler/ruby/1.9.1/bundler/gems/rails-c6854813c824/activerecord/lib/active_record/relation/calculations.rb:289:in `execute_grouped_calculation'
from /Users/joe/projects/tanga/bundler/ruby/1.9.1/bundler/gems/rails-c6854813c824/activerecord/lib/active_record/relation/calculations.rb:206:in `perform_calculation'
from /Users/joe/projects/tanga/bundler/ruby/1.9.1/bundler/gems/rails-c6854813c824/activerecord/lib/active_record/relation/calculations.rb:159:in `calculate'
from /Users/joe/projects/tanga/bundler/ruby/1.9.1/bundler/gems/rails-c6854813c824/activerecord/lib/active_record/relation/calculations.rb:58:in `count'
from (irb):1
from /Users/joe/projects/tanga/bundler/ruby/1.9.1/bundler/gems/rails-c6854813c824/railties/lib/rails/commands/console.rb:47:in `start'
from /Users/joe/projects/tanga/bundler/ruby/1.9.1/bundler/gems/rails-c6854813c824/railties/lib/rails/commands/console.rb:8:in `start'
from /Users/joe/projects/tanga/bundler/ruby/1.9.1/bundler/gems/rails-c6854813c824/railties/lib/rails/commands.rb:41:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6
I believe this is the cause: jeremyevans/sequel#532
Hello,
I'm using Arel from Git (since my app needs patches that have been merged into master) with Rails 3.2.8 and I'm getting a NameError: uninitialized constant Arel::Relation
error when running my functional tests. Here's my setup:
$ rails -v
Rails 3.2.8
$ ruby -v
ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-linux]
$ bundle list | grep arel
* arel (3.0.2.20120819075748 de7e7c8)
Currently, I'm using this hack in my test_helper to work around the issue:
# XXX: this fixes NameError: uninitialized constant Arel::Relation
# http://intertwingly.net/blog/2012/03/28/Keeping-it-on-the-Rails
module Arel::Relation; end
Thanks for your consideration.
module Arel
module Expressions
def count distinct = false
..
gets included into SqlLiteral < String , and as such overrides the built in function.
This results in the fact that arel asts can't be yamld , because psyc calls the original count with 2 args (see below).
Probably not a major issue for anyone, just would help to study those trees.
Unfortunately I haven't got any idea how to fix this, but I thought I'd let someone know anyway.
ArgumentError: wrong number of arguments (2 for 1)
.rvm/gems/ruby-1.9.3-p286/bundler/gems/arel-890eaf4784fb/lib/arel/expressions.rb:3:in count' .rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:225:in
binary?'
.rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:234:in visit_String' .rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:103:in
accept'
.rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:292:in block in visit_Hash' .rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:291:in
each'
.rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:291:in visit_Hash' .rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:103:in
accept'
.rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:449:in block in dump_ivars' .rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:447:in
each'
.rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:447:in dump_ivars' .rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:125:in
visit_Object'
.rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:103:in accept' .rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:449:in
block in dump_ivars'
.rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:447:in each' .rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:447:in
dump_ivars'
.rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:125:in visit_Object' .rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:103:in
accept'
.rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:449:in block in dump_ivars' .rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:447:in
each'
.rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:447:in dump_ivars' .rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:125:in
visit_Object'
.rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:103:in accept' .rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:67:in
push'
.rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych.rb:242:in dump' .rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/core_ext.rb:14:in
psych_to_yaml'
rails/phoenix/lib/active_record/connection_adapters/phoenix_visitor.rb:30:in `accept'
.
.
.
the accept does a to_yaml on the ast tree, below
Arel::Nodes::SelectStatement:0x00000102900080 @cores=[#<Arel::Nodes::SelectCore:0x00000102900058 @source=#<Arel::Nodes::JoinSource:0x00000102900030 @left=#<Arel::Table:0x000001038a3870 @name="topics", @engine=Topic(important: text, last_read: date, parent_id: integer, bonus_time: time, created_at: datetime, updated_at: datetime, written_on: datetime, author_name: string, id: , author_email_address: string, parent_title: string, type: string, group: string, title: string, replies_count: integer, content: text, approved: boolean), @columns=nil, @Aliases=[], @table_alias=nil, @primary_key=nil>, @right=[]>, @top=#<Arel::Nodes::Top:0x000001028ffb80 @expr=1>, @set_quantifier=nil, @Projections=[#<struct Arel::Attributes::Attribute relation=#<Arel::Table:0x000001038a3870 @name="topics", @engine=Topic(important: text, last_read: date, parent_id: integer, bonus_time: time, created_at: datetime, updated_at: datetime, written_on: datetime, author_name: string, id: , author_email_address: string, parent_title: string, type: string, group: string, title: string, replies_count: integer, content: text, approved: boolean), @columns=nil, @Aliases=[], @table_alias=nil, @primary_key=nil>, name="*">], @Wheres=[#<Arel::Nodes::And:0x000001028ffd38 @children=[#<Arel::Nodes::Equality:0x00000102858858 @left=#<struct Arel::Attributes::Attribute relation=#<Arel::Table:0x000001038a3870 @name="topics", @engine=Topic(important: text, last_read: date, parent_id: integer, bonus_time: time, created_at: datetime, updated_at: datetime, written_on: datetime, author_name: string, id: , author_email_address: string, parent_title: string, type: string, group: string, title: string, replies_count: integer, content: text, approved: boolean), @columns=nil, @Aliases=[], @table_alias=nil, @primary_key=nil>, name="id">, @right="?">]>], @groups=[], @having=nil, @windows=[]>], @orders=[], @limit=#<Arel::Nodes::Limit:0x000001028ffba8 @expr=1>, @lock=nil, @offset=nil, @with=nil>
(above sort of shows why I want to use to_yaml)
Not much to go on at the moment, but on something like one run out of a hundred of our cucumber suite, we get a strange nil dereference coming from a bit of code that hooks up Arel bind values to ActiveRecord inserts.
The code in question is in lib/arel/visitors/bind_visitor.rb whose introduction was the sole diff from 2.2.2 in 2.2.3, so I was hoping you could give me some more background on the change.
I'm not clear on how the visitor stuff is used but my interpretation of the below backtrace is that there is one fewer bind value being provided than the AST expects. Is that reasonable?
I can't figure out how this could be intermittent. The model class in question has no magic stuff. Could well be an ActiveRecord bug but given bind_visitor only just went in, I am hazarding a guess it's Arel.
(We are running an older version of Rails - from 3-1-stable - but master has no relevant changes to this code that I can see, 4bc2ae0 being the only vaguely related thing, so I believe it's not already fixed. And I can't see anything wrong in the higher-level ActiveRecord calls nor the aliased methods to do query caching, transaction isolation levels, etc.)
undefined method `reverse' for nil:NilClass
/var/anonymized/vendor/bundle/ruby/1.8/bundler/gems/rails-a84c005e35d2/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb:10:in `to_sql'
/var/anonymized/vendor/bundle/ruby/1.8/gems/arel-2.2.3/lib/arel/visitors/bind_visitor.rb:17:in `call'
/var/anonymized/vendor/bundle/ruby/1.8/gems/arel-2.2.3/lib/arel/visitors/bind_visitor.rb:17:in `visit_Arel_Nodes_BindParam'
/var/anonymized/vendor/bundle/ruby/1.8/gems/arel-2.2.3/lib/arel/visitors/visitor.rb:19:in `send'
/var/anonymized/vendor/bundle/ruby/1.8/gems/arel-2.2.3/lib/arel/visitors/visitor.rb:19:in `visit'
/var/anonymized/vendor/bundle/ruby/1.8/gems/arel-2.2.3/lib/arel/visitors/to_sql.rb:119:in `visit_Arel_Nodes_Values'
/var/anonymized/vendor/bundle/ruby/1.8/gems/arel-2.2.3/lib/arel/visitors/to_sql.rb:117:in `map'
/var/anonymized/vendor/bundle/ruby/1.8/gems/arel-2.2.3/lib/arel/visitors/to_sql.rb:117:in `visit_Arel_Nodes_Values'
/var/anonymized/vendor/bundle/ruby/1.8/gems/arel-2.2.3/lib/arel/visitors/visitor.rb:19:in `send'
/var/anonymized/vendor/bundle/ruby/1.8/gems/arel-2.2.3/lib/arel/visitors/visitor.rb:19:in `visit'
/var/anonymized/vendor/bundle/ruby/1.8/gems/arel-2.2.3/lib/arel/visitors/to_sql.rb:82:in `visit_Arel_Nodes_InsertStatement'
/var/anonymized/vendor/bundle/ruby/1.8/gems/arel-2.2.3/lib/arel/visitors/visitor.rb:19:in `send'
/var/anonymized/vendor/bundle/ruby/1.8/gems/arel-2.2.3/lib/arel/visitors/visitor.rb:19:in `visit'
/var/anonymized/vendor/bundle/ruby/1.8/gems/arel-2.2.3/lib/arel/visitors/visitor.rb:5:in `accept'
/var/anonymized/vendor/bundle/ruby/1.8/gems/arel-2.2.3/lib/arel/visitors/to_sql.rb:18:in `accept'
/var/anonymized/vendor/bundle/ruby/1.8/bundler/gems/rails-a84c005e35d2/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb:185:in `with_connection'
/var/anonymized/vendor/bundle/ruby/1.8/gems/arel-2.2.3/lib/arel/visitors/to_sql.rb:16:in `accept'
/var/anonymized/vendor/bundle/ruby/1.8/gems/arel-2.2.3/lib/arel/visitors/bind_visitor.rb:11:in `accept'
/var/anonymized/vendor/bundle/ruby/1.8/bundler/gems/rails-a84c005e35d2/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb:9:in `to_sql'
/var/anonymized/vendor/bundle/ruby/1.8/bundler/gems/rails-a84c005e35d2/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb:91:in `insert'
/var/anonymized/vendor/bundle/ruby/1.8/bundler/gems/rails-a84c005e35d2/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb:14:in `insert'
/var/anonymized/vendor/bundle/ruby/1.8/bundler/gems/rails-a84c005e35d2/activerecord/lib/active_record/relation.rb:70:in `insert'
/var/anonymized/vendor/bundle/ruby/1.8/bundler/gems/rails-a84c005e35d2/activerecord/lib/active_record/persistence.rb:313:in `create'
/var/anonymized/vendor/bundle/ruby/1.8/bundler/gems/rails-a84c005e35d2/activerecord/lib/active_record/timestamp.rb:51:in `create'
/var/anonymized/vendor/bundle/ruby/1.8/bundler/gems/rails-a84c005e35d2/activerecord/lib/active_record/callbacks.rb:268:in `create'
/var/anonymized/vendor/bundle/ruby/1.8/bundler/gems/rails-a84c005e35d2/activesupport/lib/active_support/callbacks.rb:390:in `_run_create_callbacks'
/var/anonymized/vendor/bundle/ruby/1.8/bundler/gems/rails-a84c005e35d2/activesupport/lib/active_support/callbacks.rb:81:in `send'
/var/anonymized/vendor/bundle/ruby/1.8/bundler/gems/rails-a84c005e35d2/activesupport/lib/active_support/callbacks.rb:81:in `run_callbacks'
/var/anonymized/vendor/bundle/ruby/1.8/bundler/gems/rails-a84c005e35d2/ac...tiverecord/lib/active_record/callbacks.rb:268:in `create'
/var/anonymized/vendor/bundle/ruby/1.8/bundler/gems/rails-a84c005e35d2/activerecord/lib/active_record/persistence.rb:294:in `create_or_update'
/var/anonymized/vendor/bundle/ruby/1.8/bundler/gems/rails-a84c005e35d2/activerecord/lib/active_record/callbacks.rb:264:in `create_or_update'
/var/anonymized/vendor/bundle/ruby/1.8/bundler/gems/rails-a84c005e35d2/activesupport/lib/active_support/callbacks.rb:399:in `_run_save_callbacks'
/var/anonymized/vendor/bundle/ruby/1.8/bundler/gems/rails-a84c005e35d2/activesupport/lib/active_support/callbacks.rb:81:in `send'
/var/anonymized/vendor/bundle/ruby/1.8/bundler/gems/rails-a84c005e35d2/activesupport/lib/active_support/callbacks.rb:81:in `run_callbacks'
/var/anonymized/vendor/bundle/ruby/1.8/bundler/gems/rails-a84c005e35d2/activerecord/lib/active_record/callbacks.rb:264:in `create_or_update'
/var/anonymized/vendor/bundle/ruby/1.8/bundler/gems/rails-a84c005e35d2/activerecord/lib/active_record/persistence.rb:57:in `save!'
/var/anonymized/vendor/bundle/ruby/1.8/bundler/gems/rails-a84c005e35d2/activerecord/lib/active_record/validations.rb:56:in `save!'
/var/anonymized/vendor/bundle/ruby/1.8/bundler/gems/rails-a84c005e35d2/activerecord/lib/active_record/attribute_methods/dirty.rb:33:in `save!'
/var/anonymized/vendor/bundle/ruby/1.8/bundler/gems/rails-a84c005e35d2/activerecord/lib/active_record/transactions.rb:246:in `save!'
/var/anonymized/vendor/bundle/ruby/1.8/bundler/gems/rails-a84c005e35d2/activerecord/lib/active_record/transactions.rb:295:in `with_transaction_returning_status'
/var/anonymized/vendor/bundle/ruby/1.8/gems/transaction_isolation_level-0.1.0/lib/transaction_isolation_level/adapter_patches.rb:43:in `transaction'
/var/anonymized/vendor/bundle/ruby/1.8/bundler/gems/rails-a84c005e35d2/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb:199:in `transaction_without_isolation_level'
/var/anonymized/vendor/bundle/ruby/1.8/gems/transaction_isolation_level-0.1.0/lib/transaction_isolation_level/adapter_patches.rb:43:in `transaction'
/var/anonymized/vendor/bundle/ruby/1.8/bundler/gems/rails-a84c005e35d2/activerecord/lib/active_record/transactions.rb:208:in `transaction'
/var/anonymized/vendor/bundle/ruby/1.8/bundler/gems/rails-a84c005e35d2/activerecord/lib/active_record/transactions.rb:293:in `with_transaction_returning_status'
/var/anonymized/vendor/bundle/ruby/1.8/bundler/gems/rails-a84c005e35d2/activerecord/lib/active_record/transactions.rb:246:in `save!'
/var/anonymized/vendor/bundle/ruby/1.8/bundler/gems/rails-a84c005e35d2/activerecord/lib/active_record/associations/has_many_association.rb:14:in `insert_record'
/var/anonymized/vendor/bundle/ruby/1.8/bundler/gems/rails-a84c005e35d2/activerecord/lib/active_record/associations/collection_association.rb:436:in `create_record'
/var/anonymized/vendor/bundle/ruby/1.8/bundler/gems/rails-a84c005e35d2/activerecord/lib/active_record/associations/collection_association.rb:344:in `add_to_target'
/var/anonymized/vendor/bundle/ruby/1.8/bundler/gems/rails-a84c005e35d2/activerecord/lib/active_record/associations/collection_association.rb:434:in `create_record'
/var/anonymized/vendor/bundle/ruby/1.8/bundler/gems/rails-a84c005e35d2/activerecord/lib/active_record/associations/collection_association.rb:147:in `transaction'
/var/anonymized/vendor/bundle/ruby/1.8/gems/transaction_isolation_level-0.1.0/lib/transaction_isolation_level/adapter_patches.rb:43:in `transaction'
/var/anonymized/vendor/bundle/ruby/1.8/bundler/gems/rails-a84c005e35d2/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb:199:in `transaction_without_isolation_level'
/var/anonymized/vendor/bundle/ruby/1.8/gems/transaction_isolation_level-0.1.0/lib/transaction_isolation_level/adapter_patches.rb:43:in `transaction'
/var/anonymized/vendor/bundle/ruby/1.8/bundler/gems/rails-a84c005e35d2/activerecord/lib/active_record/transactions.rb:208:in `transaction'
/var/anonymized/vendor/bundle/ruby/1.8/bundler/gems/rails-a84c005e35d2/activerecord/lib/active_record/associations/collection_association.rb:146:in `transaction'
/var/anonymized/vendor/bundle/ruby/1.8/bundler/gems/rails-a84c005e35d2/activerecord/lib/active_record/associations/collection_association.rb:433:in `create_record'
/var/anonymized/vendor/bundle/ruby/1.8/bundler/gems/rails-a84c005e35d2/activerecord/lib/active_record/associations/collection_association.rb:115:in `create!'
/var/anonymized/vendor/bundle/ruby/1.8/bundler/gems/rails-a84c005e35d2/activerecord/lib/active_record/associations/collection_proxy.rb:53:in `__send__'
/var/anonymized/vendor/bundle/ruby/1.8/bundler/gems/rails-a84c005e35d2/activerecord/lib/active_record/associations/collection_proxy.rb:53:in `create!'
/var/anonymized/features/step_definitions/signup_steps.rb:126
The gem page for arel
on RubyGems.org still points to the following outdated links:
Assume there's a one to many relationship between people and projects.
This arel query:
people.project(:id).join(services).on(services[:person_id].eq(people[:id])).where(services[:type].eq(1)).intersect(
people.project(:id).join(services).on(services[:person_id].eq(people[:id])).where(services[:type].eq(2)))
outputs this SQL
( SELECT id
FROM `people` INNER JOIN `services` ON `services`.`person_id` = `people`.`id`
WHERE `services`.`type` = 1
INTERSECT
SELECT id
FROM `people` INNER JOIN `services` ON `services`.`person_id` = `people`.`id`
WHERE `services`.`type` = 2 )
problem is that it's not valid mysql (though you can work around it with inner join tricks). I can't seem to make such query play nicely with activerecord.
I'm redirected here from activerecord-hackery/squeel#187
Currently it seems we only have support for IN type of subqueries, like
SELECT 'users'.* FROM 'users' WHERE 'users'.'id' IN (SELECT max('users'.'id') FROM 'users')
It would be nice if we could write something like:
SELECT 'users'.* FROM 'users' WHERE 'users'.'id' < (SELECT max('users'.'id') FROM 'users')
This example is very simplistic and not overly useful at this complexity level, and only came up with it so that I could easily demonstrate the issue I (and others, please see activerecord-hackery/squeel#187) were having.
Furthermore, it would be all the best if by this improvement we could generate subquery-based single SQL statement wherever it is supported (not restricted to WHERE
clause but also in SELECT
, FROM
, etc...)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.