Rails - 2.3.8
Database - Postgres(9.2)
Active record query is not able to generate tablename in double quotes ie
# this ran fine
Table.find_by_sql('Select * from "Table" Limit 1')
Sql generated - Select * from "Table" Limit 1
But issue comes in,
Table.find(:first)
Sql generated - Select * from Table Limit 1 (Clearly noticed that table not in double quotes)
Active record displaying error
ActiveRecord::StatementInvalid: RuntimeError: ERROR
C42P01 Mrelation "Table" does not exist
P15 Fparse_relation.c L864
RparserOpenTable: SELECT * FROM Table LIMIT 1
I feel that postgresql adapter is not able to generate tablename in double quotes.
I never get a chance to work on Postgres. But I have a workaround solution for this. Try as follows:
table_name = '"Table"'
table_name.find(:first)
I haven't try this in my machine since I do not have the required setup. I hope it should work.
Related
I know precious nothing abour Rails, so please excuse my naivete about this question.
I'm trying to modify a piece of code that I got from somewhere to make it execute it for a randomly selected bunch of users. Here it goes:
users = RedshiftRecord.connection.execute(<<~SQL
select distinct user_id
from tablename
order by random()
limit 1000
SQL
).to_a
sql = 'select user_id, count(*) from tablename where user_id in (?) group by user_id'
<Library>.on_replica(:something) do
Something::SomethingElse.
connection.
exec_query(sql, users.join(',')).to_h
end
This gives me the following error:
ActiveRecord::StatementInvalid: PG::SyntaxError: ERROR: syntax error at or near ")"
LINE 1: ...ount(*) from tablename where user_id in (?) group by...
^
Users is an array, I know this coz I executed the following and it resulted in true:
p users.instance_of? Array
Would someone please help me execute this code? I want to execute a simple SQL query that would look like this:
select user_id, count(*) from tablename where user_id in (user1,user2,...,user1000) group by user_id
The problem here is that IN takes a list of parameters. Using a single bind IN (?) and a comma separated string will not magically turn it into a list of arguments. Thats just not how SQL works.
What you want is:
where user_id in (?, ?, ?, ...)
Where the number of binds matches the length of the array you want to pass.
The simple but hacky way to do this would be just interpolate in n number of question marks into the SQL string:
binds = Array.new(users.length, '?').join(',')
sql = <<~SQL
select user_id, count(*)
from tablename
where user_id in (#{binds)})
group by user_id'
SQL
<Library>.on_replica(:something) do
Something::SomethingElse.
connection.
exec_query(sql, users).to_h
end
But you would typically do this in a Rails app by creating a model and using the ActiveRecord query interface or using Arel to programatically create the SQL query.
I have a ruby on rails application which runs on Postgres database.
(application is not mine by the way, just trying to mess around with and learn more)
So, if I run a simple query such as this:
SELECT * FROM users ORDER BY users.id ASC LIMT 1
I get this:
SyntaxError: unexpected tIDENTIFIER, expecting keyword_do or '{' or '('
SELECT * FROM users ORDER BY users.id ASC LIMT 1
I've been getting that error pretty consistently regardless of any query I run, no matter how simple or complicated.
Why?
EDIT 1
Btw, wanted to mention that this query is run in the console ... fyi.
Even a simple query like this: SELECT * FROM user LIMIT 1 gets me the same error, regardless.
EDIT 2
This is what I get:
psql (9.0.13, server 9.3.1)
WARNING: psql version 9.0, server version 9.3.
Some psql features might not work.
Type "help" for help.
nameofApp=# SELECT * FROM user LIMIT 1
nameofApp-#
nameOfApp-#
nameofApp-#
The hashmarks continue when I press Enter. It doesn't seem to perform the query.
Just connect to Postgresql by psql NAMEOFDATABASEHERE
Then end all your queries with a semicolon.
select * from users; (ENTER)
If you don't type the semicolon the interpreter keeps waiting for more statements and you will be greeted by the next hash sign when pressing enter.
Hope it helps!
You need to run this in the db console. Try rails db from the commandline. Or for an equivalent result in the console try: User.first
Im trying to query my db for records that are similar to the currently viewed record (based on taggings), which I have working but I would like to randomize the order.
my development environment is mysql so I would do something like:
#tattoos = Tattoo.tagged_with(tags, :any => true).order("RAND()").limit(6)
which works, but my production environment is heroku which is using postgresql so I tried using this:
#tattoos = Tattoo.tagged_with(tags, :any => true).order("RANDOM()").limit(6)
but I get the following error:
ActionView::Template::Error (PGError: ERROR: for SELECT DISTINCT, ORDER BY expressions must appear in select list
SELECT DISTINCT tattoos.* FROM "tattoos" JOIN taggings
tattoos_taggings_color_fantasy_newschool_nerdy_tv_477 ON
tattoos_taggings_color_fantasy_newschool_nerdy_tv_477.taggable_id = tattoos.id AND
tattoos_taggings_color_fantasy_newschool_nerdy_tv_477.taggable_type = 'Tattoo' WHERE
(tattoos_taggings_color_fantasy_newschool_nerdy_tv_477.tag_id = 3 OR
tattoos_taggings_color_fantasy_newschool_nerdy_tv_477.tag_id = 4 OR
tattoos_taggings_color_fantasy_newschool_nerdy_tv_477.tag_id = 5 OR
tattoos_taggings_color_fantasy_newschool_nerdy_tv_477.tag_id = 24 OR
tattoos_taggings_color_fantasy_newschool_nerdy_tv_477.tag_id = 205) ORDER BY RANDOM() LIMIT 6):
After analyzing the query more closely, I have to correct my first draft. The query would require a DISTINCT or GROUP BY the way it is.
The (possibly) duplicate tattoos.* come from first joining to (possibly) multiple rows in the table taggings. Your query engine then tries to get rid of such duplicates again by using DISTINCT - in a syntactically illegal way.
DISTINCT basically sorts the resulting rows by the resulting columns from left to right and picks the first for each set of duplicates. That's why the leftmost ORDER BY column have to match the SELECT list.
MySQL is more permissive and allows the non-standard use of DISTINCT, but PostgreSQL throws an error.
ORMs often produce ineffective SQL statements (they are just crutches after all). However, if you use appropriate PostgreSQL libraries, such an illegal statement shouldn't be produced to begin with. I am no Ruby expert, but something's fishy here.
The query is also very ugly and inefficient.
There are several ways to fix it. For instance:
SELECT *
FROM (<query without ORDER BY and LIMIT>) x
ORDER BY RANDOM()
LIMIT 6
Or, better yet, rewrite the query with this faster, cleaner alternative doing the same:
SELECT ta.*
FROM tattoos ta
WHERE EXISTS (
SELECT 1
FROM taggings t
WHERE t.taggable_id = ta .id
AND t.taggable_type = 'Tattoo'
AND t.tag_id IN (3, 4, 5, 24, 205)
)
ORDER BY RANDOM()
LIMIT 6;
You'll have to implement it in Ruby yourself.
not sure about the random, as it should work.
But take a note of http://railsforum.com/viewtopic.php?id=36581
which has code that might suit you
/lib/agnostic_random.rb
module AgnosticRandom
def random
case DB_ADAPTER
when "mysql" then "RAND()"
when "postgresql" then "RANDOM()"
end
end
end
/initializers/extend_ar.rb (name doesn't matter)
ActiveRecord::Base.extend AgnosticRandom
I'm attempting a transition from MySQL to what seems to be the stricter and less Rails-friendly PostgreSQL.
I'm running into this funny conundrum:
irb(main):015:0> puts w.to_sql
SELECT DISTINCT ON (vendors.id) vendors.*
FROM "vendors"
INNER JOIN "locations" ON "locations"."locatable_id" = "vendors"."id"
AND "locations"."locatable_type" = 'Vendor'
WHERE (locations.latitude IS NOT NULL AND locations.longitude IS NOT NULL)
But...
irb(main):017:0> puts w.order('vendors.id').to_sql
SELECT * FROM (
SELECT DISTINCT ON (vendors.id) vendors.*
FROM "vendors"
INNER JOIN "locations" ON "locations"."locatable_id" = "vendors"."id"
AND "locations"."locatable_type" = 'Vendor'
WHERE (locations.latitude IS NOT NULL AND locations.longitude IS NOT NULL)
) AS id_list ORDER BY id_list.alias_0
This, despite the fact that just adding ORDER BY vendors.id works just fine as a valid PostgreSQL query. Instead of just adding that, it does something super funny and produces an invalid query at the end of the day:
ActiveRecord::StatementInvalid: PGError: ERROR: column id_list.alias_0 does not exist
LINE 1: ...tions.longitude IS NOT NULL)) AS id_list ORDER BY id_list.al...
Any clue what I should look at?
I've run into the same problem. Looks like it was a bug in Arel causing DISTINCT ON not to play nice with ORDER when using PostgreSQL.
The original bug is no longer visible since Rails has moved from Lighthouse to github issues but you can take a look at the Google cache. There's a comment on a more recent pull request which indicates the issue was fixed after Rails 3.0.7 was released. Looks like it will be in 3.1 but I couldn't verify as some of the gems I'm using are not yet compatible.
The current work-around is to use find_by_sql.
Hi
I changed my database from mySql to PostgreSQL and get an error every time I use query with :order statement
For example the following code works perfectly in MySQL
Hour.sum("working_hours",:conditions=>['project_id=? AND reported_date=?',project,h.reported_date],:order=>"reported_date
But gives me an error in PostgreSQL
PGError: ERROR: column "hours.reported_date" must appear in the GROUP BY clause or be used in an aggregate function
LINE 1: ...rted_date='2010-10-06 00:00:00.000000') ORDER BY reported_d..
: SELECT sum("hours".working_hours) AS sum_working_hours FROM "hours" WHERE (project_id=1 AND reported_date='2010-10-06 00:00:00.000000') ORDER BY reported_date
If I delete the order statement then the query works ok
I will most appreciate any help on this subject
PostreSQL is stricter to the SQL standard than MySQL is.
SQL states that if you ORDER by a column, that column must be SELECTed and appear in the GROUP BY clause.
Try this:
Hour.sum("working_hours",:conditions=>['project_id=? AND reported_date=?',project,h.reported_date], :order=>"reported_date", :group_by => "working_hours"