Rails: Querying with an Array - mysql

I have the following method which creates and then executes an SQL query:
def edition_authors(edition, authors)
query_string = "contributor_type = ? AND author = ?"
for i in 1..authors.length - 1
query_string += " OR author = ?"
end
return edition.contributors.where(query_string, 'Author', authors)
end
The last line is the one I'm having trouble with. I want the 'authors' array to somehow turn into a set of strings. For instance, if the authors array contained ['James Joyce', 'Cory Doctorow', 'Cormac McCarthy'], I'd like that last line to read like:
return edition.contributors.where(query_string, 'Author', 'James Joyce', 'Cory Doctorow', 'Cormac McCarthy')
How could I accomplish this?

Depends which rails and which ruby you are using,
ActiveRecord already has this functionality in Rails 3: Model.where(:my_field => ['Author', 'James Joyce', 'Cory Doctorow', 'Cormac McCarthy'])
arr.map{|v| v.to_s.inspect} will get you a comma separated list
arr.join(',') will give you a comma separated list, no quotes.
Then you can use this string however you wish.

Try this:
Instead of using a big bunch of ORs, use a SQL IN clause, and
then use Array#join to supply the values
So:
.where("contributor_type = ? AND author IN (?)", 'Author', authors.join("','"))
should do the trick, with some caveats: string values in a SQL IN clause need to be single quoted and comma separated SELECT * FROM fubar WHERE blah IN ('foo','bar','baz'); I think Rails is clever about knowing how to quote things, so look in the Rails log to see what SQL is being generated if you're getting an error.
Also, since your values may contain single quotes (Georgia O'Keefe) I am not sure if Rails is smart enough to escape these for you when used in this manner.
Bonus tip: make sure there's an index on the Author column. This is an expensive query, in general.

Related

How to escape a whole sql string instead of escaping each argument?

I use https://github.com/mysqljs/mysql.git library.
I have a mysql db query architecture in which I can not modify the SQL query file one by one to escape each argument for there are too many files, but all the SQL queries will call the query method of a same base mysql instance, so I wonder if I can escape the eventual SQL string in the base mysql query method.
I want to escape the whole SQL string like
select * from tableA where name = 'foo'bar
to
select * from tableA where name = 'foo\'bar'
with some function like mysql_escape("select * from tableA where name = 'foo'bar'") instead of doing this using preparing queries or concating escaped strings.
There isn't a way to do this that wont result in a really inefficient function or some bad hack. Just use parameterized queries, Its basically what they are there for. If you cant use those you use concat strings.
Running mysql_escape on a whole query will require the function to know what characters are part of your query and what characters are part of the input values. You could write some kind of stupid regex to try pull the values from the query and then escape them but its just a bad idea.

DECODE Function in SQL

I am trying to insert the following query and I get syntax errors. Can you please help me with the below query:
INSERT INTO ABCTABLE (COLUMN1) values ('DECODE(MDSE_CD,NULL,'0000000000000000',LPAD(TO_NUMBER(MDSE_CD,'16',' '))');
Since you haven't really said anything other than "this query doesn't work, fix it", I have to take a stab in the dark what you want. From the query you have, I'm therefore guessing you want the value of the column to be DECODE(MDSE_CD,NULL,'0000000000000000',LPAD(TO_NUMBER(MDSE_CD,'16',' '))
In which case, you have to escape the single quotes within your string literal. Do this by doubling up the quotes:
INSERT INTO ABCTABLE (COLUMN1)
VALUES ('DECODE(MDSE_CD,NULL,''0000000000000000'',LPAD(TO_NUMBER(MDSE_CD,''16'','' ''))')
Try properly escaping the inner single quotes
INSERT INTO ABCTABLE (COLUMN1)
VALUES ('**DECODE**(MDSE_CD,NULL,''0000000000000000'',**LPAD**(TO_NUMBER(MDSE_CD,''16'','' ''))');
The problem is the use of quote marks. If we tried to break up your query it would look like this:
INSERT INTO ABCTABLE
(COLUMN1)
values
(
'DECODE(MDSE_CD,NULL,'
0000000000000000
',LPAD(TO_NUMBER(MDSE_CD,'
16
','
'))'
);
...which clearly makes no sense.
You might want to think about how to escape a quote mark inside a string.
Sql Server:
DECOD function in Sql Server can be replaced with CASE construct
LPAD function in Sql Server has not a direct correspondence but you can pad your string using string manage function REPLACE (replicate a character a number of specified times)
My Sql:
DECOD function in MySql can be replaced with CASE construct
LPAD function in MySql is existent
What do you want to store... a string literal 'DECODE(MDSE...))', or did you want to call a function to derive a value?
To store a string literal containing single quotes, you need to "escape" each single quote within the string with an extra single quote, e.g.
O'Hare Int'l ==> 'O''Hare Int''l'
The DECODE function is Oracle specific. That expression will need to be rewritten using different functions in both MySQL and SQL Server.

mysql_query syntax variation: at, quotes and curly braces

I am learning MySQL/php through online tutorials and have found the techniques and syntax different from different sources.
In one tutorial, I enter data (from an HTML form) like this:
$table = "ENTRIES";
$sql = "INSERT INTO $table SET
TITLE = '$_POST[title]',
SUMMARY = '$_POST[summary]',
CONTENT = '$_POST[content]'";
$query = #mysql_query($sql);
And in another, like this:
mysql_query("
INSERT INTO `posts` SET
`title` = '{$_POST['title']}',
`contents` = '{$_POST['post']}'
");}
They both work, and I understand the different variable arrangements. BUT I have the following questions, probably all related. (I gather that #mysql_query suppresses error messages, SO if that is what is going on here, can you please explain how it is functioning and what is actually proper syntax?)
1) In the first example, in #mysql_query(), it doesn't matter if I use ("") or ('') ... but in the second example, in mysql_query(), it breaks if I use (''). In fact it tells me that there is an unexpected {, which leads to my next question:
2) What is the deal with the {} in the second example? They don't seem to be doing anything, but it breaks without them.
3) In the first example, is breaks if I enclose title, summary, and content in single quotes ''. In the second, with 'title' and 'post', it breaks if I don't!
Any explanations or references/links comprehensible to a beginner would be much appreciated!
Run far away from this tutorial and fine one that uses PDO / mysqli and explains how to properly parameterize queries.
Anyway, your questions are PHP specific and have to do with variable interpolation in strings. In quoted strings (") variables are interpolated, and arrays can be accessed via:
"{$var['value']}"
"$var[value]"
Either one is valid ... they function identically and it's up to personal preference which one you should use.
mysql_query takes a string as an argument, so it actually makes no difference how you build it. Both of the above are valid. Using # makes no difference -- in fact, you shouldn't use it, and you should properly handle possible errors and check mysql_error

Are there markers for the start and end of a string in MySQL?

Basically I'm trying to remove a value (val2 for example) from a string that looks like 'val1,val2,val3'. However the values can be arranged in any order and I want to avoid ending up with stuff like ',val1,val3', 'val1,,val3' or 'val1,val3,'. I thought about replacing 'val2' with '' and then replacing ',,', ',end' and 'start,' with ','. But I don't know what the markers for end and start of a string are.
Storing multiple values in one single column is never a good idea. You should think about redesign your data model.
You can get what you want with regular expressions, see MYSQL documentation. There are two characters ^ and $ that match beginning and end of a string.

passing string in a query to MySQL database in MATLAB

I am using MySQL with MATLAB, and I want to get a name from user, and pass it to the table in mySQL, but it is rejecting a variable name in place of string
var_name=input('enter the name:');
mysql('insert into table (name) values (var_name)');
Any suggestions?
FIRST read the comments to this question - you don't want to shoot yourself in the foot with a mysql injection security problem. You have been warned. Now, to solve your current problem, without addressing the security risk of the whole approach when it comes to building SQL queries, read on...
In principle Amro has already posted two solutions for you which work, but since you have not accepted it I'll explain further.
Your problem is that you are not telling MATLAB which parts of your query it should interpret as a literal string, and which parts it should interpret as a variable name. To solve this, you can just end the literal string where appropriate, i.e. after the opening brackets, and then start them again before the closing brackets.
In between those literal strings you want to add the contents of your variables, so you need to tell MATLAB to concat your literal strings with your variables, since the mysql command probably expects the whole query as a single string. So in essence you want to take the string 'insert into table(' and the string saved in the variable name and the string ') values (' and so on and glue them into one big string. Amro and Isaac have shown you two solutions of how to do this without much explanation:
horzcat('insert into table (', name, ') values (', var_name, ')')
uses the function horzcat, while
['insert into table (' name ') values (' var_name ')']
uses the fact that MATLAB treats strings as arrays of characters so that you can just use square brackets to form a large array containing the strings one after the other.
The third solution, offered by Amro, is a bit more sublte:
sprintf('insert into table (%s) values (%s)',name,var_name)
It tells the function sprintf (which is made for that purpose) "take the string which I supply as first parameter and replace occurences of %s with the strings I supply as the following parameters. This last technique is in particular useful if you also need to insert numbers into your string, because sprintf can also convert numbers to string and allows fine control over how they are formatted. You should have a close look at the help page for sprintf to know more :-).
Try this instead:
mysql(['insert into table (' name ') values (' var_name ')']);
or even:
mysql(sprintf('insert into table (%s) values (%s)',name,var_name));
I believe the problem you are having is the same as the one in this other question. It sounds like you want to create a command string that itself contains a ' delimited string, which would require you to escape each ' with another ' when you create your command string (note the first example in this string handling documentation). Note also you may want to use the 's' option for the INPUT function:
var_name = input('Enter the name: ','s'); %# Treats input like a string
commandString = sprintf('insert into table (name) values (''%s'')', var_name);
%# Note the two apostrophes --^
mysql(commandString);
If I were to enter Ken for the input, the string commandString would contain the following:
insert into table (name) values ('Ken')
And of course, as others have already mentioned, beware injection vulnerabilities.