Pass Java List to SQL query Grails - sql

i have a populated list:
def someList=... (string values)
and I want to pass this into a SQL statement to restrict which columns the query selects.
db.rows("select ${someList} from arch_application")
However, I get this error when I try to do so:
There is a ? parameter in the select list. This is not allowed.
Anyone have an ideas? Thanks!

When you pass a GString to Sql.rows, it gets parsed differently than normal in groovy. In particular, it creates a PreparedStatement with replaceable parameters for ${} substitutions. In your case this is probably not what you want. Try forcing the GString to a Java string:
db.rows("select ${someList.join(',')} from arch_application" as String)

Related

Access FlowVar dynamically in DataWeave

I'm trying to access a FlowVar name dynamically in DataWeave.
For example:
I have a flowVars named taxInfo123. This is a linked list and my applicant.ApplicantID = 123
In my dataweave, I want to access this dynamically. Something like the following:
"TaxInfo": flowVars.'taxInfo'+applicant.ApplicantID map ((taxIdentificationDetail , indexOfTaxIdentificationDetail) -> {
This obviously doesn't work, and I'm hoping this is possible and I just need the correct syntax.
If you need to dynamically create the variable name, you can use the flowVars[key] syntax instead of the flowVars.key syntax. In your scenario:
"TaxInfo": flowVars[('taxInfo' ++ (flowVars.applicant.ApplicantID as :string))]
I assumed applicant was also a flowVar but you could just as easily use payload.applicant.ApplicantID or whatever your situation calls for. I also assumed it was a number so I had to cast it as a string.
When you use this syntax you want to make sure you wrap the key expression in parenthesis so it is evaluated first and then the flowVar is resolved.
So to summarize:
If you know the variable name is 'taxInfo123' -
flowVars.taxInfo123 or flowVars[taxInfo123] are both valid
If you need to create the variable name dynamically -
flowVars[(expression)]
Hope that helps!
Forming the variable name needs append operator like ++. Please go through the MuleSoft documentation for Dataweave operators to get better understanding of how much flexiblity is possible in Dataweave.
https://docs.mulesoft.com/mule-user-guide/v/3.8/dataweave-operators

IntelliJ IDEA: inject language with String.format()

I have an SQL query which unfortunately cannot be written as a prepared statement because it has variable column names. Because of this, I have to build my SQL using String formatting.
The language (SQL dialect) I'm using is PostgreSQL, but because I have String.format() in my queries, IntelliJ complains about syntax errors in my code.
public class Example {
public String getUniqueFeatureCountSqlQuery(String feature, Long sourceUserId) {
//language=PostgreSQL
return String.format("SELECT COUNT(DISTINCT targetUserId), %s FROM userComments GROUP BY %s WHERE userId = %d",
feature, feature, sourceUserId);
}
}
How do I make IntelliJ recognize this string properly? It should know that it is PostgreSQL which is first formatted by String.format().
Thanks to #WillHumphreys I found a solution via youtrack.
You have to go the the User Parameters settings under Tools -> Database -> User Parameters, or use the find action command.
Then make these changes.
You may also have to use the argument index string format notation (String.format("SELECT %1s ...", ...)) for the parameters to be distinguishable when attempting to alt-enter run the query in the console.

String concatenation in stringtemplate

I'm trying to make a lookup to a hash table m.notes using concatenated value of position.qid and literal ".qid" like this:
$tag(name="itemId", content=m.notes.(position.qid".qid").itemId)$
I tried different options, but I get runtime error. Can someone correct my syntax?
Put the 2 items in an array. StringTemplate concatenates all items in an array (or as they call it, a multi-valued-attribute) when it executes a ToString() on it.
[position.qid, ".qid"]
So, if position.qid evaluates to "hello", this expression would become
hello.qid.
Not sure whether such concatenation is possible in string template. Why don't you use a different method that could do the concatenation and return the value.
e.g:
position.fullQid instead of position.qid
where,
public String getFullQid(){
return getQid() + ".qid";
}
in template group, I can do like this, first, define a concantenate template:
concantenate(substr)::=""
then use as following
(concantenate([position.qid,".qid"]))

Dynamic named parameters in Groovy?

I found it really cool that in Groovy SQL it is possible to do this:
def resultList = Domain.executeQuery('select * from languages where name = :name', [name: 'Groovy'])
I am trying to get the HQL "in" keyword to work with a dynamic list used as the argument, not a fixed list.
I also know that you can use the "?" operator for your SQL parameters instead of using named parameters. However according to this question:
Doing an "IN" query with Hibernate
The "in" keyword only supports named and positional parameters, not the "?" parameter. The problem is, when I try to do something like this:
def paramMap = [:]
paramMap.put("name", "groovy")
def resultList = Domain.executeQuery('select * from languages where name = :name', paramMap)
I get an error saying that I have not specified the parameter name. So it is acting as if I have not actually specified the parameter "name". I have read the Groovy documentation on named parameters here:
http://groovy.codehaus.org/api/groovy/sql/Sql.html
But all of the examples using named parameters use a predefined parameter list. I have searched and have not found an example of using a dynamic parameter list map. How can I pass a dynamic map of parameters into Groovy named SQL query? If that is not possible, how can I use the "in" keyword with a dynamic list?
To be clear, I am constructing a dynamic SQL query and I would like to be able to add parameters to a map or list as I go along. I was previously using the "?" operator until I had to use the "in" clause, which does not work with "?".
Why not try find all with closures?
def paramMap = [:]
paramMap.put("name", "groovy")
def resultList = Domain.findAll {
paramMap.containsValue(name)
}
Here's the docs, hopefully it helps! http://grails.org/doc/latest/ref/Domain%20Classes/findAll.html

Escape dot from GString

I would like to learn how to escape dot in GString so groovy (1.8) does not treat it as a part of an variable inside sql.execute. I have the following code:
Map<String, String> dbSettings = [schemaName:"testSchema"];
String myDbPrefix = dbSetting.schemaName + ".";
sql.execute "DELETE FROM ${myDbPrefix}myTable"
And I got this error:
Ignoring groovy.lang.MissingPropertyException: No such property: myTable for class: java.lang.String
Clearly indicating that . was interpreted as part of variable ${myDbPrefix}.
Does escaping the embedded variable help?
  sql.execute "DELETE FROM ${Sql.expand myDbPrefix}myTable"
I got hit by this problem today. GStrings get handled by a special way in GroovySQL. It's mentioned in the javadoc. It does automatic parameter binding.
Each value in the GString will become a parameter (?) which gets set as a JDBC prepared statement parameter.
What a surprise!
I'm going to fix the problem in my application by subclassing the Sql class and overriding the GString handling with plain ".toString()" .
Documented in Groovy wiki:
GString Use Cases - GSQL Another use case for GString is GSQL where
parameters can be passed into SQL statements using this same mechanism
which makes for a neat way to integrate Groovy with other languages
like SQL. GroovySql then converts the expressions to ? and uses a JDBC
PreparedStatement and passes the values in, preserving their types.
If you explicitly want to coerce the GString to a String you can use
the toString() method. Groovy can also automatically coerce GStrings
into Strings for you.