Scala Play Framework Anorm SQL.on disable wrapping replacements with ' ' - scala

Whenever I replace placeholders in the SQL query using on it surrounds the replacement with '', is there a way to prevent this?
It means I can't do things like
SQL("SELECT * FROM {table} blah").on("table" -> tabletouse)
because it wraps the table name with '' which causes an SQL syntax error.

you could certainly combine both approaches, using the format function for data you don't want to be escaped
SQL(
"""
select %s from %s
where
name = {name} and
date between {start} and {end}
order by %s
""".format(fields, table, order)
).on(
'name -> name,
'start -> startDate,
'end -> endDate
)
Just take into account that the data you are sending using the format function should NOT come from user input, otherwise it should be properly sanitized

You cannot do what you are trying. Anorm's replacement is based on PreparedStatements. Meaning all data will automatically be escaped, meaning you cannot use replacement for :
table names,
column names,
whatever operand, SQL keyword, etc.
The best you can do here is a String concatenation (and what is really a bad way in my opinion) :
SQL("SELECT * FROM " + tabletouse + " blah").as(whatever *)
PS : Checkout this question about table names in PreparedStatements.

Related

How can I allow users to submit q queries and interpret them as a string?

I want to allow users to write real q queries like
select from table where date=.z.d
Is it possible to use something like
E)select from table where date=.z.d
and then use the input to that E) to parse the query and do stuff with it?
If you create a function called .E.e, anything you pass to it will be interpreted as a string, so you can do something like this to start parsing your input:
q).E.e: {" " vs x}
q)E)select from table where date = .z.d
"select"
"from"
"table"
"where"
"date"
,"="
".z.d"

postgresql : regexp_substr - get sub string between occurrence of delimiters

I have these strings:
[{"Name":"id","Value":"Window_Ex_kebklipecbcegiocpa_widget_open"
[{"Name":"id","Value":"Window_Ex_kebklipecbcegiocpa_widget_close"
[{"Name":"id","Value":"Window_Ex_kebklipecbcegiocpa_widget_mid_value"
and I'm trying to extract only the parts after the third _, until the end of the string (which ends always with ")
widget_open
widget_close
widget_mid_value
I'm using postgresql, and wanted to use the regexp_substr syntax, in order to extract it.
Thanks!
regexp_replace(data::text,'^([^_]+_){3}','')
You can try
select regexp_replace(data::text,'^([^_]+_){3}','')
from (
select 'one_two_three_four s'::text as data
union select 'a_bb_ccc_dddd_eeee_ffff'
) data

Elixir: How to search database data with double spaces

In my front end, the data display has only single spaces. However, when I filter my data in search bar, it yields no result. It turns out the data actually has double spaces. But when its being repo.all, the double spaces becomes single spaces. I need to search that data.
I have a regexp which i found which i tried in pgadmin which works. I need to replicate it in my elixir datatable, for specifically, integrating it in ilike function.
The regexp is
SELECT trim(regexp_replace(name, '\s+', ' ', 'g')) as col_name
FROM table where col_name = 'TEST DATA'
I think a better approach might be to use % in place of spaces when searching, I find that this gives me generally better results. Here are the docs for ILIKE in Postgres, but I'll explain with an example. The % character used in ILIKE matches any string of characters (including the empty string).
SELECT * FROM t1 WHERE col_name ILIKE '%test%data%';
The query above will match the example that you've given. Granted, it will also match strings like "testdata", "test data", "something test something data", but I think that in general this approach will return results that a user would expect when entering a search like "test data".
A helper function to do this transformation from user input to a string suitable for Ecto's ilike would look like this:
defmodule SearchHelpers do
def to_ilike_search_string(search_string) do
joined_string =
search_string
|> String.split()
|> Enum.join("%")
"%#{joined_string}%"
end
end
# SearchHelpers.to_ilike_search_string("test data")
# => "%test%data%"
And you could use it in a query like this:
ilike_search_string = SearchHelpers.to_ilike_search_string("test data")
query = from p in Post,
where: ilike(p.content, ^ilike_search_string)
results = Repo.all(query)
Good luck, hope this helps.

Firebird query with string concatenation and like in the where clause doesn't work

I have a users table with first name and last name. I want to find a user for a string like 'clark kent'.
I do this
SELECT * FROM user WHERE fisrt_name || ' ' || last_name LIKE '%clark kent%'
but I don't have any result.
Why? If I search for 'clark' or 'kent' it works.
Solution:
SELECT *
FROM user
WHERE TRIM("first_name") || ' ' || TRIM("last_name") LIKE '%clark kent%';
Per the OP's comments, the difficulty was that first_name and last_name were CHAR and not VARCHAR fields, meaning that the fields are space-padded to their length. That is, the string 'clark' stored as CHAR(8) is 'clark[sp][sp][sp]'.
When concatenating the fields together to form a "full name", then, the resulting string had unexpected spaces: 'clark[sp][sp][sp][sp]kent[sp][sp][sp][sp]'.
(As an aside, in strict SQL, CHAR columns are rather counter-intuitive. They compare without regard to space padding, but the LIKE operator does not ignore space padding. See the Firebird FAQ.)
Try
SELECT *
FROM user
WHERE upper(fisrt_name) LIKE '%CLARK%'
and upper(last_name) LIKE '%KENT%'

tsql comma delimited testing for value

I've been given a table with a few fields that hold comma-separated values (either blank or Y/N) like so (and the field name where this data is stored is People_Notified):
Y,,N,
,Y,,N
,,N,Y
Each 'slot' relates to a particular field value and I need to now include that particular field name in the string as well (in this case Parent, Admin, Police and Medical) but inserting a "N" if the current value is blank but leaving the existing Y's and N's in place. So for the above example, where there are four known slots, I would want a tsql statement to end up with:
Parent=Y,Admin=N,Police=N,Medical=N
Parent=N,Admin=Y,Police=N,Medical=N
Parent=N,Admin=N,Police=N,Medical=Y
I tried to use a combination of CHARINDEX and CASE but haven't figured a way to make this work.
js
Although a bit messy, in theory can be done in one statement:
select
'Parent=' +stuff((stuff((stuff(
substring((replace(
(','+(replace((replace(#People_Notified,',,,',',N,N,')),',,',',N,'))+','),',,',',N,')),2,7),7,0,
'Medical=')),5,0,'Police=')),3,0,'Admin=')
broken down is easier to follow:
declare #People_Notified varchar(100)=',,Y,Y' -- test variable
-- Insert Ns
set #People_Notified= (select replace(#People_Notified,',,,',',N,N,')) -- case two consecutive missing
set #People_Notified= (select replace(#People_Notified,',,',',N,')) -- case one missing
set #People_Notified= (select replace((','+#People_Notified+','),',,',',N,')) -- case start or end missing
set #People_Notified= substring(#People_Notified,2,7) -- remove extra commas added previously
-- Stuff the labels
select 'Parent=' +stuff((stuff((stuff(#People_Notified,7,0,'Medical=')),5,0,'Police=')),3,0,'Admin=')
If you're able to use XQuery in SQL Server, I don't think you need to get too complex. You could do something like this:
SELECT CONVERT(XML, REPLACE('<pn>' + REPLACE(People_Notified, ',', '</pn><pn>') + '</pn>', '<pn></pn>', '<pn>N</pn>')).query('
concat("Parent=", data(/pn[1])[1], ",Admin=", data(/pn[2])[1], ",Police=", data(/pn[3])[1], ",Medical=", data(/pn[4])[1])
')
FROM ...
Explanation: Construct an XML-like string out of the original delimited string by replacing commas with closing and opening tags. Add an opening tag to the start and a closing tag to the end. Replace each empty element with one containing "N". Convert the XML-like string into actual XML data so that you can use XQuery. Then just concatenate what you need using concat() and the right indexes for the elements' data.
Here's one way to do it:
;WITH cteXML (Id, Notified)
AS
(
SELECT Id,
CONVERT(XML,'<Notified><YN>'
+ REPLACE([notified],',', '</YN><YN>')
+ '</YN></Notified>') AS Notified
FROM People_Notified
)
select id,
'Parent=' + case Notified.value('/Notified[1]/YN[1]','varchar(1)') when '' then 'N' else Notified.value('/Notified[1]/YN[1]','varchar(1)') end + ',' +
'Admin=' + case Notified.value('/Notified[1]/YN[2]','varchar(1)') when '' then 'N' else Notified.value('/Notified[1]/YN[2]','varchar(1)') end + ',' +
'Police=' + case Notified.value('/Notified[1]/YN[3]','varchar(1)') when '' then 'N' else Notified.value('/Notified[1]/YN[3]','varchar(1)') end + ',' +
'Medical=' + case Notified.value('/Notified[1]/YN[4]','varchar(1)') when '' then 'N' else Notified.value('/Notified[1]/YN[4]','varchar(1)') end Notified
from cteXML
SQL Fiddle
Check this page out for an explanation of what the XML stuff is doing.
This page has a pretty thorough look at the various ways you can split a delimited string into rows.