PostgreSql + Searching Issue for "'" present in string - ruby-on-rails

Here, I have a problem in searching record in Postgresql DB in RoR Application. Name of table :: address_books, name of attributes :: organization_name, federal_tax_id, city, zip , business_name. In search, organization name contain :: Claire's Inc as record. At the time of searching, it does not show the data while we select Claire's Inc in search box. Because "'" breaks the string and gives no result. So I have used "?" replace "'" at time of search in mysql and it works. But I am getting appropriate conversion to make search of this words.
Query :: SELECT * FROM "address_books"
WHERE ( address_books.organization_name = 'Claire?s Inc'
and address_books.federal_tax_id = '59-0940416'
and address_books.city = 'Hoffman Estates'
and address_books.zip = '60192' and address_books.business_name ='' )
ORDER BY address_books.organization_name , city LIMIT 100
Please suggest any other way to make successful search.
Thanks in Advance

You're messing up your data to deal with a matter of query syntax. Put a correctly escaped apostrophe in the place where the apostrophe should be.
One way is to escape it to 'Claire''s Inc'. Another is to use a library that lets you pass parameters and handles the escaping for you. Another is to enter the string as $$Claire's Inc$$ though that syntax allows for other things that may not be appropriate here.

I think you can use RoR parameter substituion, than RoR will escape your dangerous strings for you. something like:
AddressBook.find(:all, :conditions => { "organization_name => ?", "Claire's Inc" })
or
AddressBook.find(:all, :conditions => { :organization_name => "Claire's Inc" })

Related

Rails query to substitute field and query

could someone please help me to write a query to substitute hyphens in rails DB field with space?
For eg:
If I have a field called 'name' in a table User having a value 'asdc-sd bc', and want to remove special characters like '-' and replace it with space to match with a given name 'asdc sd bc'.
I tried using lower to convert the name to lowercase but am not able to find out how to substitute the hyphens with space. Please help!
You can use SQL REPLACE function to replace - with spaces(' ').
For example, if you are querying on name column of User model, you can write your query like below:
query_str = 'asdc sd bc'
User.where("REPLACE(name, '-', ' ') = ?", query_str)

convert my string to comma based elements

I am working on a legacy Rails project that relies on Ruby version 1.8
I have a string looks like this:
my_str = "a,b,c"
I would like to convert it to
value_list = "('a','b','c')"
so that I can directly use it in my SQL statement like:
"SELECT * from my_table WHERE value IN #{value_list}"
I tried:
my_str.split(",")
but it returns "abc" :(
How to convert it to what I need?
To split the string you can just do
my_str.split(",")
=> ["a", "b", "c"]
The easiest way to use that in a query, is using where as follows:
Post.where(value: my_str.split(","))
This will just work as expected. But, I understand you want to be able to build the SQL-string yourself, so then you need to do something like
quoted_values_str = my_str.split(",").map{|x| "'#{x}'"}.join(",")
=> "'a','b','c'"
sql = ""SELECT * from my_table WHERE value IN (#{quoted_values_str})"
Note that this is a naive approach: normally you should also escape quotes if they should be contained inside your strings, and makes you vulnerable for sql injection. Using where will handle all those edge cases correctly for you.
Under no circumstances should you reinvent the wheel for this. Rails has built-in methods for constructing SQL strings, and you should use them. In this case, you want sanitize_sql_for_assignment (aliased to sanitize_sql):
my_str = "a,b,c"
conditions = sanitize_sql(["value IN (?)", my_str.split(",")])
# => value IN ('a','b','c')
query = "SELECT * from my_table WHERE #{conditions}"
This will give you the result you want while also protecting you from SQL injection attacks (and other errors related to badly formed SQL).
The correct usage may depend what version of Rails you're using, but this method exists as far back as Rails 2.0 so it will definitely work even with a legacy app; just consult the docs for the version of Rails you're using.
value_list = "('#{my_str.split(",").join("','")}')"
But this is a very bad way to query. You better use:
Model.where(value: my_str.split(","))
The string can be manipulated directly; there is no need to convert it to an array, modify the array then join the elements.
str = "a,b,c"
"(%s)" % str.gsub(/([^,]+)/, "'\\1'")
#=> "('a','b','c')"
The regular expression reads, "match one or more characters other than commas and save to capture group 1. \\1 retrieves the contents of capture group 1 in the formation of gsub's replacement string.
couple of use cases:
def full_name
[last_name, first_name].join(' ')
end
or
def address_line
[address[:country], address[:city], address[:street], address[:zip]].join(', ')
end

Normalize seeking value in SQL search query

[PostgreSQL(9.4), Rails(4.1)]
The problem:
I have a table with the names of tools. The column_name is hstore type and looks like this: name -> ('en': value, 'de': value). Worth noting that 'de' is unnecessary in this problem, cause all names are stored only in 'en' key.
Next I have to construct a search query that will find the right record, but the format of the text in query are unknown, e.g.:
In DB:
WQXZ 123GT, should match query: WQXZ_123-GT
In DB:
Three Words Name 123-D45, should match query: Three_WORDS_NAME 123D45
and so on...
Solution:
To get this happen I want to normalize the value that I'm looking for and the query in such way that both of them will be identical. To do this I need to make both values in downcase, remove all whitspaces, remove all non-alphanumeric characters, so the values above will be:
wqxz123gt == wqxz123gt
and
threewordsname123d45 == threewordsname123d45
I have no problem to format a search value in ruby:
"sTR-in.g24 3".downcase.gsub(/\s/, "").gsub(/\W/, "") # => "string243"
But I can't understand how to do this in SQL-search query to look like:
Tool.where("CODE_I_AM_LOOKING_FOR(name -> 'en') = (?)", value.downcase.gsub(/\s/, "").gsub(/\W/, ""))
Thank you for your time.
UPD: I can make a downcase in query:
Tool.where("lower(name -> 'en') = (?)", value.downcase)
But it solves only a part of the problem (downcase). The whitespaces and non-word characters (dots, dashes, underscores, etc.) are still an issue.
You can use Postgres replace function to remove spaces. Then use lower function to match on that value. Like this.
Tool.where("lower(replace(name -> 'en', ' ', '')) = (?)", value.downcase.gsub(/\s/, "").gsub(/\W/, "") )
I hope this would be helpful.
Nitin Srivastava's answer directed me in right direction. All I needed was to use regexp_replace function.
So the proper query is:
Tool.where(
"lower(regexp_replace((name -> 'en'), '[^a-zA-Z0-9]+', '', 'g')) = ?",
value.downcase.gsub(/\s/, "").gsub(/\W/,"")
)

sanitize_sql_array is adding extra, unnecessary quotes to query

This is the first time I've seen this issue. I'm building up an SQL array to run through sanitize_sql_array and Rails is adding extra, unnecessary single quotes in the return value. So instead of returning:
SELECT DISTINCT data -> 'Foo' from products
it returns:
SELECT DISTINCT data -> ''Foo'' from products
which of course Postgres doesn't like.
Here is the code:
sql_array = ["SELECT DISTINCT %s from products", "data -> 'Foo'"]
sql_array = sanitize_sql_array(sql_array)
connection.select_values(sql_array)
Note the same thing happens when I use the shorter and more usual:
sql_array = ["SELECT DISTINCT %s from products", "data -> 'Foo'"]
connection.select_values(send(:sanitize_sql_array, sql_array))
Ever seen this before? Does it have something to do with using HStore? I definitely need that string sanitized since the string Foo is actually coming from a user-entered variable.
Thanks!
You're giving sanitize_sql_array a string that contains an hstore expression and expecting sanitize_sql_array to understand that the string contains some hstore stuff; that's asking far too much, sanitize_sql_array only knows about simple things like strings and numbers, it doesn't know how to parse PostgreSQL's SQL extensions or even standard SQL. How would you expect sanitize_sql_array to tell the difference between, for example, a string that happens to contain '11 * 23' and a string that is supposed to represent the arithmetical expression 11 * 23?
You should split your data -> 'Foo' into two pieces so that sanitize_sql_array only sees the string part when it is sanitizing things:
sql_array = [ 'select distinct data -> ? from products', 'Foo' ]
sql = sanitize_sql_array(sql_array)
That will give you the SQL you're looking for:
select distinct data -> 'Foo' from products

Symfony, propel, question mark

I want to create a search function on my website, and I don't want to use a plugin for this thing, because it's very simple, but I can't solve this problem:
I give the keyword to the model which creates a query, but I couldn't figure out how to put joker characters in this query.
I'm using Propel
Dennis
The filterByXXX() query functions will use LIKE when your query contains wildcards:
$books = BookQuery::create()
->filterByTitle('War%')
->find();
// example Query generated for a MySQL database
$query = 'SELECT book.* from `book` WHERE book.TITLE LIKE :p1'; // :p1 => 'War%'
Remember, the wildcards you can use in SQL are _ for exactly one and % for zero or more characters. So not ? or *.

Resources