I have a rather complex sql statement that is created on the fly. But the same problem exists for a simple query, so I use this one as an example.
I have a Feature model. I can call Feature.count --> 4
But if I try to get all Feature ids using ActiveRecord::Base.connection.execute("SELECT ID from features") the result is a OCI8::Cursor object. I do not know how to get the data out of it.
If I try ActiveRecord::Base.connection.execute("SELECT ID from features").fetch I get [1]. With xyz.fetch_hash I get {"ID" => 1}.
I would like to have all IDs.
I just switched from PostgreSQL to Oracle.
Using PostgreSQL, I got all data using ActiveRecord::Base.connection.execute("SELECT ID from features").to_a, but to_a does not exist using the activerecord-oracle_enhanced-adapter gem (*** NoMethodError Exception: undefined method 'to_a' for #<OCI8::Cursor:0x00000007028aa8>).
I am using Ruby 2.0 and Rails 4. The connection to the Oracle database is working, except my manually created statement.
I found a solution.
Old: ActiveRecord::Base.connection.execute("SELECT ID from features")
New: ActiveRecord::Base.connection.exec_query("SELECT ID from features").to_a
Maybe someone have the same problem.
Related
Running Rails 4.0.13 with TinyTDS connected to Microsoft SQL Server 2012, I'm trying to run the following query:
sql = Model.where(:foo => bar).select(:open, :high, :low, :close).to_sql
Model.connection.execute(sql)
The problem is, the generated sql is
"SELECT open, high, low, close FROM [models]"
Which gives me an error as the column names open and close are protected.
TinyTds::Error: Incorrect syntax near the keyword 'open'
If I use #pluck, I can see the correct SQL is generated (with column names escaped):
"SELECT [models].[open], [models].[high], [models].[low], [models].[close] FROM [models]"
However, this produces an array, which is not what I want.
My question is how can i get #select to correctly quote the column names?
Thank you
I don't think you can make the select method to protect your column names when using symbols (maybe because different DBMS use different quoting identifiers), but you could pass your selection as a string :
sql = Model.where(:foo => bar).select("[open], [high], [low], [close]").to_sql
Model.connection.execute(sql)
I attempted to submit a bug report to Rails, however in doing so I saw the problem did not appear to exists using SQLite test case, this leads me to believe the issue is with the SQL Server Adapter.
Since I am on Rails 4 and not the latest version of the adapter I left it and wrote the following (horrible) method as wrapping the column names was not enough, I needed to prefix the table to prevent ambiguous column names. Yuck
def self.quote(*columns, klass)
columns.map { |col| "[#{klass.table_name}].[#{col}]" }.join(', ')
end
I can't find this documented anywhere but here is my problem: when I query via active record and use "only" the "order" clause is ignored. For example I have a Blog model:
Blog.order('id desc')
returns all the blogs with the highest ID first - as expected but:
Blog.order('id desc').only(:id)
returns only the id's (as expected) but the order clause is completely ignored, the smallest id comes first.
I have tested this with Ruby 1.9.3p327 and both Rails 4.0.0.beta1 and Rails 3.2.13 and I get the same results.
Is this a feature or a bug? To me it's a bug because the Rails crew were trumpeting how find_by_sql is not really needed but in this case it is:
Blog.find_by_sql("select id from blogs order by id desc")
which gives the correct answer.
Try using pluck instead of only. only is used to override portions of the previously formed query chain. As the the docs demonstrate:
Post.where('id > 10').limit(20).order('id desc').only(:order, :where)
results in:
SELECT * FROM posts WHERE id > 10 ORDER BY id DESC
This is because the limit modification will be ignored, since the list passed to only doesn't include :limit.
UPDATE
If you need an actual model object returned instead of an array of id's, use select:
Blog.order('id desc').select('id')
When a client hits my Rails app's API for data, I would like to pass back the query that generated the data with the data. I'm using Rails 2.
Right now I've edited the Rails mysql_adapter to put all queries in a global hash that has the user session as a key and the query as a value.
This is very hacky and probably not thread-safe.
Is there a better way?
Don't know if it can help but you can whenever you want call to_sql on an ActiveRecord object :
user = User.where(:id => 1)
user.to_sql # Outputs "SELECT \"users\".* FROM \"users\" WHERE \"users\".\"id\" = 1"
You can use fake_arel gem to get the .to_sql functionality into rails 2.
I have finally started upgrading my Rails apps from 2.3.8 to 3.1.0. I was watching RailsCasts (http://railscasts.com/episodes/202-active-record-queries-in-rails-3) about Active Record queries.
When I open up the console (rails c) and do query similar to this:
articles = Article.order("name")
Instead of returning Active Record relations, I see the query executed. What am I doing wrong here?
Rails version: 3.1.0
RVM on 1.9.2
Thank you for your help!
EDIT: I have added a screenshot from the example.
The ActiveRecord Relation class is configured to perform the query when a query method like .all, .last, .first, ... is invoked. The list of method also includes .inspect, the same method called by the console to display the representation of the return value.
For this reason it seems to you that the object is never a relation, because you always see the result of the query.
But if you inspect the object class, you'll notice it's a relation
Article.order("name").class
# => ActiveRecord::Relation
You're doing everything right. You see query executed because console invokes inspect method on output. Try articles = Article.order("name").class
I'm using ruby 1.9.2 and rails 3 with a postgresql 8.4 database.
I have the following piece of rails code.
#playersonline = Member.find(:all, :conditions => ["loggedIn = ?", true] )
And I get the following error when the line is encountered:
PGError: ERROR: column "loggedin" does not exist
Looking at the query it generates it shows the following:
SELECT "members".* FROM "members" WHERE (loggedIn = 't')
The loggedIn column does exist in my table, and it has a boolean data type.
Another thing that is odd, when I try to query just the loggedIn column via a sql browser I get the same error? i.e. select loggedIn from members
Thanks
Postgres is case-sensitive by default so loggedIn isn't the same as loggedin. Although you can override it, Rails convention is that variable name-parts are separates by an underscore.
I wouldn't recommend re-inventing the wheel. Go in and change the columnn name (and any other columns that follow your notation) you might have to logged_in. This will prevent you from encountering any more strange errors.