I am currently rendering a list of sql rows from a database using:
Sql sql = new Sql(dataSource)
def list = []
def index = 0
params.mrnaIds.each { mrnaName ->
sql.eachRow ("select value from patient_mrna where mrna_id=$mrnaId") { row ->
list[index] = row.value
index++
}
}
render list
However I would like to avoid assigning the values to a list before rendering them.
The variable params.mrnaIds is coming from a multi select input, so it could either be a single string or a string array containing ids. Is there a way to iterate through these ids inside the eachRow method?
I would like to be able to execute something like:
render sql.eachRow ("select value from patient_mrna where mrna_id=?", params.mrnaIds) { row ->
list[index] = row.value
index++
}
But I'm not completely sure that there is a way to call eachRow with this functionality. If there is not, is there some other way to render the results without storing them in a list?
I think you can render each row:
sql.eachRow( someQuery, someParams ){ row ->
render row as JSON
}
There is rows() to return a list instead ok working with it (like eachRow() is used for). It also shares all the different arguments. E.g.:
render sql.rows("select value from patient_mrna where mrna_id=?", params).collect{ it.value }
Related
I have got list of objects
listOf(User("John",32), User("Katy",15), User("Sam",43))
How can write a function which returns me the User object if in parameter I pass a name. For example getUser("John") and it suppose to return me User("John",32)
One possibility is also using firstOrNull:
val list = listOf(User("John",32), User("Katy",15), User("Sam",43))
list.firstOrNull { it.name == "John" }
I've a list
def a = [kitkat lollypop orea android-11]
another list
def b = ["kitkat", "lollypop", "honeycomb", "nougat", "android-11"]
I need to do some task on list a items if they exist in list b if they don't exist in list b then do something else.
One thing to note is list a items are separated by space and no quotes whereas list be is by comma and has items within quotes; due to this things I've tried below did not work.
I've tried the following:
1)
a.split(" ").each{
def itema = it
b.split(",").each{
if(b.contains(itema){
//do something
}
}
//do something else
)
a.split(" ").each{
if(b.split(",").contains(it){
//do something
}
//do something else
}
for(itema in a){
for(itemb in b){
if(itema == itemb){
//do something
}
}
//do something else
}
a.intersect(b)
but this threw exception due to list a having spaces between elements
I think what I want is create a new list from list a by changing it to have comma separated items with quotes and then could use one of the above solution
or is there a better way to do in groovy what I wanted?
You're almost there in examples 1 and 2, but there are a few issues.
I'm going to assume this:
def a = [kitkat lollypop orea android-11]
is actually a String, based on how you're attempting to split it. In my solution I'm going to assume it's this:
def a = "[kitkat lollypop orea android-11]"
Using the String in 'a', take everything between the two brackets. From there, split the String by the space character in order to get a list of items. Then, using this new items list, we're going to go one by one and iterate through list b to see if we have any matches:
def items = a.takeBetween("[", "]")
items.split(/\s/).each {
if (it in b) {
println "I'm in list b - $it"
} else {
println "I'm not in list b - $it"
}
}
This will result in:
I'm in list b - kitkat
I'm in list b - lollypop
I'm not in list b - orea
I'm in list b - android-11
I have a situation here where I want to omit the nested maps and get it done in one liner . Can it be done using chain or any other ways .
self.workorder.tasklist = _.map(self.workorder.tasklists, function (tasklist) {
tasklist.tasklistGroups = _.map(tasklist.tasklistGroups, function (tasklistGroup, tgKey) {
tasklistGroup.tasklistItems = _.map(tasklistGroup.tasklistItems, function (taskListItem, tKey) {
taskListItem = _.omit(taskListItem, ["open"]);
return taskListItem;
});
return tasklistGroup;
});
return tasklist;
});
I don't want so many nested map calls .
Because you are modifying your items in place I would say this is possible:
_.chain(self.workorder.tasklists).map(function(tasklist) {
return tasklist.tasklistGroups;
}).flatten().map(function(group) {
return group.tasklistItems
}).flatten().forEach(function(item) {
delete item.open;
}).value();
Jsfiddle
The idea is to flatten your array to last level (level of items) and then modify them using forEach.
Domain class:
class Transaction {
String roundId
BigDecimal amount
:
}
The SQL we wish to execute the following:
"select sum(t.amount) from transaction t where t.roundId = xxx"
We have been unable to find an example which does not return Transaction rows.
We assume there are two approaches:
Use projections and/or criteria etc? All the examples we have found only return lists of transaction rows, not the sum.
Use raw SQL. How do we call SQL, and get a handle on the BigDecimal it returns?
I tried this:
class bla{
def sessionFactory
def someMethod() {
def SQLsession = sessionFactory.getCurrentSession()
def results = SQLsession.createSQLQuery("select sum(t.credit) from transaction t where t.round_id = :roundId", [roundId: roundId])
But this fails with
groovy.lang.MissingMethodException: No signature of method: org.hibernate.internal.SessionImpl.createSQLQuery() is applicable for argument types: (java.lang.String, java.util.LinkedHashMap)
Also, I have no idea what the return type would be (cant find any documentation). I am guessing it will be a list of something: Arrays? Maps?
==== UPDATE ====
Found one way which works (not very elegant or grails like)
def SQLsession = sessionFactory.getCurrentSession()
final query = "select sum(t.credit) from transaction t where t.round_id = :roundId"
final sqlQuery = SQLsession.createSQLQuery(query)
final results = sqlQuery.with {
setString('roundId', roundId)
list() // what is this for? Is there a better return value?
}
This seems to return an array, not a list as expected, so I can do this:
if (results?.size == 1) {
println results[0] // outputs a big decimal
}
Strangely, results.length fails, but results.size works.
Using Criteria, you can do
Transaction.withCriteria {
eq 'roundId', yourRoundIdValueHere
projections {
sum 'amount'
}
}
https://docs.jboss.org/hibernate/core/3.3/api/org/hibernate/classic/Session.html
Query createSQLQuery(String sql, String[] returnAliases, Class[] returnClasses)
Query createSQLQuery(String sql, String returnAlias, Class returnClass)
The second argument of createSQLQuery is one or more returnAliases and not meant for binding the statement to a value.
Instead of passing your values in the 2nd argument, use the setters of your Query object i.e. setString, setInteger, etc.
results.setInteger('roundId',roundId);
I have this response in soapUI:
<pointsCriteria>
<calculatorLabel>Have you registered for inContact, signed up for marketing news from FNB/RMB Private Bank, updated your contact details and chosen to receive your statements</calculatorLabel>
<description>Be registered for inContact, allow us to communicate with you (i.e. update your marketing consent to 'Yes'), receive your statements via email and keep your contact information up to date</description>
<grades>
<points>0</points>
<value>No</value>
</grades>
<grades>
<points>1000</points>
<value>Yes</value>
</grades>
<label>Marketing consent given and Online Contact details updated in last 12 months</label>
<name>c21_mrktng_cnsnt_cntct_cmb_point</name>
</pointsCriteria>
There are many many many pointsCriteria and I use the below xquery to give me the DB value and Range of what that field is meant to be:
<return>
{
for $x in //pointsCriteria
return <DBRange>
<db>{data($x/name/text())}</db>
<points>{data($x//points/text())}</points>
</DBRange>
}
</return>
And i get the below response
<return><DBRange><db>c21_mrktng_cnsnt_cntct_cmb_point</db><points>0 1000</points></DBRange>
That last bit sits in a property transfer. I need SQL to bring back all rows where that DB field is not in that points range (field can only be 0 or 1000 in this case), my problem is I dont know how to loop through each DBRange/DBrange in this manner? please help
I'm not sure that I really understand your question, however I think that you want to make queries in your DB using specific table with a column name defined in your <db> field of your xml, and using as values the values defined in <points> field of the same xml.
So you can try using a groovy TestStep, first parse your Xml and get back your column name, and your points. To iterate over points if the values are separated with a blank space you can make a split(" ") to get a list and then use each() to iterate over the points on this list. Then using groovy.sql.Sql you can perform the queries in your DB.
Only one more thing, you need to put the JDBC drivers for your vendor DB in $SOAPUI_HOME/bin/ext and then restart SOAPUI in order that it can load the necessary driver classes.
So the follow code approach can achieve your goal:
import groovy.sql.Sql
import groovy.util.XmlSlurper
// soapui groovy testStep requires that first register your
// db vendor drivers, as example I use oracle drivers...
com.eviware.soapui.support.GroovyUtils.registerJdbcDriver( "oracle.jdbc.driver.OracleDriver")
// connection properties db (example for oracle data base)
def db = [
url : 'jdbc:oracle:thin:#db_host:d_bport/db_name',
username : 'yourUser',
password : '********',
driver : 'oracle.jdbc.driver.OracleDriver'
]
// create the db instance
def sql = Sql.newInstance("${db.url}", "${db.username}", "${db.password}","${db.driver}")
def result = '''<return>
<DBRange>
<db>c21_mrktng_cnsnt_cntct_cmb_point</db>
<points>0 1000</points>
</DBRange>
</return>'''
def resXml = new XmlSlurper().parseText(result)
// get the field
def field = resXml.DBRange.db.text()
// get the points
def points = resXml.DBRange.points.text()
// points are separated by blank space,
// so split to get an array with the points
def pointList = points.split(" ")
// for each point make your query
pointList.each {
def sqlResult = sql.rows "select * from your_table where ${field} = ?",[it]
log.info sqlResult
}
sql.close();
Hope this helps,
Thanks again for your help #albciff, I had to add this into a multidimensional array (I renamed field to column and result is a large return from the Xquery above)
def resXml = new XmlSlurper().parseText(result)
//get the columns and points ranges
def Column = resXml.DBRange.db*.text()
def Points = resXml.DBRange.points*.text()
//sorting it all out into a multidimensional array (index per index)
count = 0
bigList = Column.collect
{
[it, Points[count++]]
}
//iterating through the array
bigList.each
{//creating two smaller lists and making it readable for sql part later
def column = it[0]
def points = it[1]
//further splitting the points to test each
pointList = points.split(" ")
pointList.each
{//test each points range per column
def sqlResult = sql.rows "select * from my_table where ${column} <> ",[it]
log.info sqlResult
}
}
sql.close();
return;