Rails: MySQL2 Error when hitting the finder of a model - mysql

with Rails I hit this:
User.find(:all, :conditions => ["character = ?", character])
character is a Fixnum, as you can see by the way it is translated for the sql. A Fixnum is expected.
Then I get this error:
Mysql2::Error: You have an error in your SQL syntax;
check the manual that corresponds to your MySQL server version for the right syntax to use near '= 5)'
at line 1: SELECT `users`.* FROM `users` WHERE (character = 5)
I'm somewhat confused and absolutely do not get what might be wrong with this line of sql.
Please help.
Yours
Joern

The problem is that character is a keyword in mysql. If you escape it in backticks it should work, eg
User.find(:all, :conditions => ["`character` = ?", character])
When you do a rails find like
User.where(:character => character)
as Rich Peck suggests, then rails automatically escapes the names of all fields to prevent this problem: you can see it do this in your log.
EDIT: you might find it less hassle in the long run to change the name of your column.

ActiveRecord
If using Rails 4, you should use this to look up multiple records:
User.where character: character
If you want to load a specific record, you can just use .find like this:
User.find_by character: character
--
Specific
I think your error is more an ActiveRecord issue than a Fixnum one - the fact you're using that data to look up the records shouldn't have any bearing.
I could be wrong, but I think the bottom line is your use of the ActiveRecord methods you've defined.

Related

How to query array column from mysql in Rails 5.2?

I am using gem rails~> 5.2 and gem mysql2 >= 0.3.13, < 0.5.
I have a model Lawer, which has an array column lawer_filed [sic].
# Model lawer.rb
serialize :lawer_field, Array
Then I created a Lawer, and I can get the lawer_field value as follows:
=> Lawer.first.lawer_field
=> ["2", "3", "5"]
Now, I want to find one Lawer with a query using lawer_field. I tried:
#lawer = Lawer.where("lawer_field && ARRAY[?]", "2")
which raised an error like this:
ActiveRecord::StatementInvalid (Mysql2::Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '['2']) LIMIT 11' at line 1: SELECT `lawers`.* FROM `lawers` WHERE (lawer_field && ARRAY['2']) LIMIT 11)
There is a mistake in my SQL syntax, but I don't how to fix it. Can anyone help?
MySQL, unlike PostgreSQL, does not support arrays in database. Therefore you needed to add this line:
serialize :lawer_field, Array
This means that you have a string field in your database, but whenever ActiveRecord is unpacking results returned by the database, it maps them directly to an instance of Ruby Array. What this means is that your only option to filter the results in the database is with any MySQL string comparison functions, LIKE, etc.
Your options are to either use LIKE or perform some other String functions (which will not perform well as you will be unable to use indices) or build another table, add a has_many association to it and use MySQL the way it was supposed to be used. You could also, of course, migrate to PostgreSQL, but that seems to be the most extreme option.
EDIT: you could also consider using MySQL`s JSON, which has been added recently. That depends on your version of MySQL though.
I didn't try this answer because I don't have any Rails project ready for testing, but I think the problem is in the syntax.
I think it should be something like this:
Lawer.where("lawer_field IN (?)", "2")

Getting Error after converting mysql query to postgresql

$ Customer.send("today").count
SELECT COUNT(*) FROM "customers" WHERE (`customers`.created_at >
'2014-02-07 05:00:00.000000')
ActiveRecord::StatementInvalid: PG::SyntaxError: ERROR: syntax error
at or near "."
LINE 1: ...LECT COUNT(*) FROM "customers" WHERE (`customers`.created_at > '2014-02-07 05:00:00.000000')
When I convert my MYSQL database to PG then I m getting this error how can I fix this. If I right this query in MySQL then it's working fine but in PG getting error.
Help me Please...!
Thanks In Advance
Backticks for quoting is a MySQL-ism, standard SQL and PostgreSQL use double quotes for quoting identifiers. Somewhere you have:
where('`customers`.created_at > ?', something)
but PostgreSQL wants to see:
where('"customers".created_at > ?', something)
However, since the table name is lower case and not a reserved word, you can drop the quotes and get something that is both easier to read and will work in both databases:
where('customers.created_at > ?', something)
Presumably this change needs to be made inside the send scope.

Rails & MySQL: SELECT Statement Single vs. Double Quotes

I have a CRON job which executes a SELECT statement to grab records. When the SELECT runs on my dev machine, it produces the following statement:
SELECT `users`.* FROM `users` WHERE `users`.`id` = 87 LIMIT 1
This is successful.
When the SELECT runs on my production (hosted) machine it produces the statement with double quotes:
SELECT "users".* FROM "users" WHERE "users”.”id” = 87 LIMIT 1
This is not successful and I get a MySQL 1064 error,
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '.* FROM "users" WHERE "users
The code is the same on both machines, but my dev MySQL is version 5.5.33, whereas production is 5.1.67 (I don't have control over this to set/update it)
Is there a way to force single quotes or another preferred method to handle this situation?
Thanks for your time and assistance.
--EDIT--
Here are the main code snippets that are invoked via my CRON job:
/lib/tasks/reports.rake
namespace :report do
desc "Send Daily Report"
task :daily => :environment do
User.where(:report_daily => 1).find_each do |user|
ReportsMailer.send_report(user, 'daily').deliver
end
end
/app/mailers/reports_mailer.rb
def send_report(user, date_increment)
#user = user
#date_increment = date_increment
get_times(user)
mail :to => user.email, :subject=> "Report: #{#dates}"
end
--EDIT2--
So it looks like I need to use slanted single quotes (`) in order for this to work successfully. How do I force my app or MySQL to use these instead of double (") quotes?
I don't know why it does this, but I do know that if you're referencing column names in MYSQL, you need to use ``, whereas values / data should be wrapped in "", like this:
SELECT `users`.* FROM `users` WHERE `users`.`id` = "87" LIMIT 1
I learnt this the hard way back in the day when I was learning how to do simple MYSQL queries
Here's some documentation from MYSQL's site for you:
The identifier quote character is the backtick (“`”):
mysql> SELECT * FROM `select` WHERE `select`.id > 100;
Identifier quote characters can be included within an identifier if
you quote the identifier. If the character to be included within the
identifier is the same as that used to quote the identifier itself,
then you need to double the character. The following statement creates
a table named a`b that contains a column named c"d:
mysql> CREATE TABLE `a``b` (`c"d` INT);
Is there any reason you couldn't put some of your sql statement directly into your code like:
User.where("`report_daily`=1").find_each do |user|
After further inspection, and working with my hosting company, its turns out that my query is timing out on their server. Thanks to all that responded.
Since you are not using any literals, the format of the generated SQL statements should be determined by the underlying adapter. Perhaps you have a different mysql adapter installed or configured on each machine. Check the installed version. For example:
bundle show mysql
and also check the adapter configuration for your project in database.yml. For example:
adapter: mysql
A comparison of the results of these checks between each machine should tell you if you are using different adapters on the two machines.

Ruby SQL Insert using Mysql2 gem

I'm trying to insert into a remote mysql database. I am able to connect correctly and can query 'select' no problem from it. However, I cannot perform inserts into the same table that I can select from. I suspect it has something to do with my binds, but this is nearly identical to what I was using to get sqlite3 working which I think uses the same Arel to insert.
#result = #db.query("insert into lead_to_processes (case_number, style_of_case) values (?,?)", [
self.case_number.to_blob.force_encoding("UTF-8"),
self.style_of_case.to_blob.force_encoding("UTF-8")
]
)
Ultimate goal is to be able query a remote database from inside of a model and insert data into it. I've tried using Octopus and that didn't quite work because the tables will be different from the databases.
I have full permissions with this user on the database.
So following guidance from comments i changed the syntax and am getting a different error
Mysql2::Error: You have an error in your SQL syntax;
However i'm doing the query like this now
#db = Mysql2::Client.new(connectionstring)
#case_number = #db.escape(self.case_number)
#style_of_case = #db.escape(self.style_of_case)
#db.query("insert into lead_to_processes (case_number, style_of_case) VALUES
(#{#case_number}, #{#style_of_case})
Any ideas or guidance? I've also tried this with '' encapsulating the variables that i'm inserting
I guess there were some weird characters in my code so I had to force UTF-8 encoding and then removed the characters using gsub below, everything is flowing now.
Thanks for the advice
#db.escape(self.style_of_case.force_encoding("UTF-8"))
#db.escape(self.case_number.gsub(/[\xC2]/,'').gsub(/[\xA0]/,'').force_encoding("UTF-8"))
Is it possible that you are missing an end quote?
this
#db.query("insert into lead_to_processes (case_number, style_of_case) VALUES
(#{#case_number}, #{#style_of_case})
should be
#db.query("insert into lead_to_processes (case_number, style_of_case) VALUES
(#{#case_number}, #{#style_of_case}") <== notice the quote at the end.

Rails 3 MySQL 2 reports an error in what looks to be valid SQL syntax

I am trying to use the following bit of code to help in seeding my database. I need to add data continually over development and do not want to have to completely reseed data every time I add something new to the seeds.rb file. So I added the following function to insert the data if it doesn't already exist.
def AddSetting(group, name, value, desc)
Admin::Setting.create({group: group, name: name, value: value, description: desc}) unless Admin::Setting.find_by_sql("SELECT * FROM admin_settings WHERE group = '#{group}' AND name = '#{name}';").exists?
end
AddSetting('google', 'analytics_id', '', 'The ID of your Google Analytics account.')
AddSetting('general', 'page_title', '', '')
AddSetting('general', 'tag_line', '', '')
This function is included in the db/seeds.rb file. Is this the right way to do this?
However I am getting the following error when I try to run it through rake.
rake aborted!
Mysql2::Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'group = 'google' AND name = 'analytics_id'' at line 1: SELECT * FROM admin_settings WHERE group = 'google' AND name = 'analytics_id';
Tasks: TOP => db:seed
(See full trace by running task with --trace)
Process finished with exit code 1
What is confusing me is that I am generating correct SQL as far as I can tell. In fact my code generates the SQL and I pass that to the find_by_sql function for the model, Rails itself can't be changing the SQL, or is it?
SELECT * FROM admin_settings WHERE group = 'google' AND name = 'analytics_id';
I've written a lot of SQL over the years and I've looked through similar questions here. Maybe I've missed something, but I cannot see it.
"group" is a keyword so you can't use it as-is as an identifier, you have to quote it with backticks (for MySQL at least):
SELECT *
FROM admin_settings
WHERE `group` = 'google'
AND name = 'analytics_id'
Any SQL that Rails/ActiveRecord generates will use the quoted version of the column name so I'd guess that you're generating some SQL (or just a snippet of SQL for the WHERE clause) and neglecting to quote the column names.
I'd recommend against using group as a column name, use something else so that you don't have to worry about sprinkling backticks all over the place in your code.
group is an invalid field name if left unquoted, as it is a SQL keyword. To fix, surround it with backticks in your find_by_sql query, so your DB doesn't attempt to interpret it as the GROUP keyword.