sql.eachRow only adds the last record into a list - sql

Good day, I'm trying to add all the users from my db to a list and print it out in a frame. But the problem is that I am only retrieving the LAST record of the users table. The others are being ignored. Here's my code
table(selectionMode: ListSelectionModel.SINGLE_SELECTION){
sql.eachRow("select * from users"){row->
println row;
def staffList = []
staffList.add(uname:row.uname,pwd:row.pwd);
tableModel(list : staffList){
closureColumn(header:'Username',read:{row1 -> return row1.uname})
closureColumn(header:'Password',read:{row1 -> return row1.pwd})
}

I think the problem is that you have redefined the staffList array within the loop. Move that to before, and you may have better results.

Related

want to assert inner list in karate

I have this kind of response in my API and I want to check that any of the list doesn't contain duplicate values.
[["1100","1100"],["123456"],["123456"],["123456"],["123516","110011"],["123515","110010"],["123514","110009"],["123513","110008"]]
when I use * match response == karate.distinct(response) , it compares all the values and not the values within the inner list like below
[["1100","2200"],["123456"],["123516","110011"],["123515","110010"],["123514","110009"],["123513","110008"]]
I only want to check whether inner list doesn't contain duplicate values, regardless of outer list elements.
This is the parent question https://stackoverflow.com/a/71807872/3664382, but now I'm stuck here -
Use match each: https://github.com/karatelabs/karate#match-each
And combine it with a "self" validation: https://github.com/karatelabs/karate#self-validation-expressions
* def fun = function(x){ return karate.match(x, karate.distinct(x)).pass }
* match each response == '#? fun(_)'
I have no idea how people end up with these weird situations. Please read this and I hope it makes sense: https://stackoverflow.com/a/54126724/143475
For completeness, you should take some time to understand JsonPath. This below will "flatten" the entire response into a single array:
* def temp = $response[*][*]

request where there are at least 2 records in other table

I have this doc xml(short version) :
<Artiste>
<artiste a_id="A62" a_p_id="UK" a_date_nais="07/06/1952" a_sexe="M">
<a_prenom>Liam</a_prenom>
<a_nom>Neeson</a_nom>
</artiste>
<artiste a_id="A66" a_p_id="UK" a_date_nais="08/09/1971" a_sexe="M">
<a_prenom>Martin</a_prenom>
<a_nom>Freeman</a_nom>
</artiste>
<Film>
<film f_id="F1" f_p_id="FR" f_r_id="A61">
<f_genre>P</f_genre>
<f_titre>Banlieue 13</f_titre>
<f_date_sortie>10/11/2004</f_date_sortie>
<f_resume>fiction française</f_resume>
<f_role ro_nom="Leïto" ro_a_id="A63"/>
<f_role ro_nom="Lola" ro_a_id="A64"/>
</film>
<film f_id="F2" f_p_id="NZ" f_r_id="A59">
<f_genre>A</f_genre>
<f_titre>Les seigneurs des anneaux</f_titre>
<f_date_sortie>19/12/2005</f_date_sortie>
<f_resume>fiction américaine</f_resume>
<f_role ro_nom="Pêcheur" ro_a_id="A25"/>
<f_role ro_nom="Sirène" ro_a_id="A2"/>
</film>
</Film>
An artist play in a film(movie), an artist has a 'a_id" field in Artiste which is the same then in ro_a_id in Film
I want to select the name and first name (a_prenom, a_nom) of every artists that have played in at least 2 movies (film)
This is what I've done :
for $artiste in doc('S:/path/file.xml')//Artiste/artiste
(: retrieve film $artiste is working in :)
let $film := ('S:/path/file.xml')//Film/film[#ro_a_id=$artiste/#a_id]
where count(#ro_a_id)>=2
order by $artiste/#a_id
return $x/a_nom, $x/a_prenom
So I don't know how to join and make the request, and I also don't know how to return 2 fields (I know that $x/a_nom, $x/a_prenom line generates an error)
You're very close, but your query has a couple of problems:
The return clause references an undefined variable $x. This should be changed to $artiste
Once that is fixed, you can return each actor's two name elements by constructing a sequence—by wrapping the items in parentheses: ($artiste/a_nom, $artiste/a_prenom). Alternatively you could return a single item, e.g., a string created by concatenating the two name parts, with concat($artiste/a_nom, " ", $artiste/a_prenom).
Your where clause should reference the $film variable—specifically, $film/f_role/#ro_a_id.
Your sample data here doesn't contain any artists who appear in more than two of the films listed. So the where clause, even if fixed, will result in 0 hits.
I've posted a revised query to http://xqueryfiddle.liberty-development.net/nbUY4kp/1 showing these suggested changes. You'll see that I commented out the where clause so that we get some results.
The easiest way to make your query work is as follows:
for $artiste in doc('S:/path/file.xml')//Artiste/artiste
(: retrieve film $artiste is working in :)
let $film := doc('S:/path/file.xml')//Film/film[f_role/#ro_a_id=$artiste/#a_id]
where count($film)>=2
order by $artiste/#a_id
return ($artiste/a_nom, $artiste/a_prenom)
Here are the things I changed:
The expression ('S:/path/file.xml') in line 3 should probably be doc('S:/path/file.xml').
#ro_a_id is an attribute of f_role, not film.
You have to count the film elements, #ro_a_id is not in scope on line 4.
$x is never declared, you probably mean $artiste.
The final problem in the last row is that the FLWOR expression ends after the comma, so $artiste/a_prenom is not part of it. You can solve that by surrounding both parts with parentheses.

Unique values from one column using ActiveAndroid?

I'm trying to get all unique values from a single column from a table. I'm utterly failing, and the docs don't seem to go into enough depth, and what I've gleaned from looking at the source seems like that should help, but doesn't.
List<Question> questions = new Select().from(Question.class).where("ZCLASSLEVEL = ? ", classLevel).execute();
works to get all the columns of all the Questions.
However,
List<Question> questions = new Select(columns).from(Question.class).where("ZCLASSLEVEL = ? ", classLevel).execute();
doesn't return any data (questions.size() = 0), where I've tried
String[] columns = { "ZHRSSECTION" };
and
Select.Column[] columns = { new Select.Column("ZHRSSECTION", "ZHRSSECTION")};
Presumably, throwing .distinct(). after the Select() should return only unique values, but I can't even get just the single column I'm interested in to get returned.
What am I missing here?
Thanks!
randy
You should use groupBy() method to make the use of distinct() method.
For example:
List<Question> questions = new Select()
.distinct()
.from(Question.class)
.groupBy("ZCLASSLEVEL")
.execute();
The above code returns a list of Questions, one for each ZCLASSLEVEL (probably the last row).
Then you can get the unique values of ZCLASSLEVEL as
for(Question question: questions){
int level = question.ZCLASSLEVEL;
//do something with level.
}
A little late in answering this, but the issue is because SQLiteUtils.rawQuery() makes the assumption that the Id column is always going to be in the cursor result. Set your columns String[] to {Id, ZHRSSECTION} and you'll be fine.
List<FooRecord> list = new Select(new String[]{"Id,tagName"}).from(FooRecord.class).execute();

Sql Select - Total Rows Returned

Using the database/sql package and drivers for Postgres and Mysql I want to achieve the following. I want to be able to Select one row and know that there is either zero rows, one row, or more than one row. the QueryRow function does not achieve that, because as far as I can ascertain, it will return one row without error regardless of if there is more than one row. For my situation, more than one row may be an error, and I want to know about it. I want to create a general function to do this.I looked at creating a function that uses the Query function, but I do not know how to return the first row if there is more than one row. I want to return the fact that there is more than one row, but I also want to return the first row. To determine that there is more than one row, I have to do a Next, and that overwrites the first row. Obviously I can achieve this without creating a general function, but I want a function to do it because I need to do this in a number of placesCould someone please explain to me how to achieve this. IE. To return the first row from a function when a successful Next has been done or the Next returned nothing.
I'm using both database/sql & MySQLDriver to achieve this. You can download MySQLDriver at https://github.com/go-sql-driver/ .
I wrote execQuery function myself to get one or more rows from database. It's based on MySQL but I think it can also used to Postgres with similar implement.
Assume you have a DB table named test, and have rows named id, name, age.
Code:
var db *sql.DB // it should be initialized by "sql.Open()"
func execQuery(SQL string, args ...interface{}) (rows *sql.Rows, is_succeed bool) {
rows, err := db.Query(SQL, args...)
var ret bool
if err == nil && rows != nil { // if DB query error rows will be nil, it will return false
ret = true
} else {
ret = false
}
return rows, ret
}
Usage:
var name, age string
rows, is_succeed = execQuery("SELECT `name`, `age` FROM `test` WHERE `id` = ?", "123")
if !is_succeed {
// error
return
}
for rows.Next() { // if have zero result rows, this for route won't execute
err := rows.Scan(&name, &age)
// check if has error & do something
}
If you want to know how much rows returned, just add a counter in for route, use SQL can also achieve this.
sql.Rows likes a list structure, rows *sql.Rows points on first row of returned rows. Use rows.Next() to traverse every rows. I think that's what you've asked.
If you really want to know rows count very often, using a cache mechanic like memcacheDB or Redis or just implement a simple counter yourself can help you solve the problem.

Best way to compare two hash of hashes?

Right now I have two hash of hashes, 1 that I created by parsing a log file, and 1 that I grab from SQL. I need to compare them to find out if the record from the log file exists in the database already. Right now I am iterating through each element to compare them:
foreach my $i(#record)
{
foreach my $a(#{$data})
{
if ($i->{port} eq $a->{port} and $i->{name} eq $a->{name})
{
print "match found $i->{name}, updating record in table\n";
}
else
{
print "no match found for $tableDate $i->{port} $i->{owner} $i->{name} adding record to table\n";
executeStatement("INSERT INTO client_usage (date, port, owner, name, emailed) VALUES (\'$tableDate\', \'$i->{port}\', \'$i->{owner}\', \'$i->{name}\', '0')");
}
}
}
Naturally, this takes a long time to run through as the database gets bigger. Is there a more efficient way of doing this? Can I compare the keys directly?
You have more than a hash of hashes. You have two lists and each element in each list contains a hash of hashes. Thus, you have to compare each item in the list with each item in the other list. Your algorithm is efficiency is O2 -- not because it's a hash of hashes, but because you're comparing each row in one list with each row in another list.
Is it possible to go through your lists and turn them into a hash that is keyed by the port and name? That way, you go through each list once to create the indexing hash, then go through the hash once to do the comparison.
For example, to create the hash from the record:
my %record_hash;
foreach my $record_item (#record) {
my $name = $record_item->{name};
my $data = $record_item->{data}
my $record_hash{$name:$data} = \$record_item #Or something like this...
}
Next, you'd do the same for your data list:
my %data_hash;
foreach my $data_item (#{$data}) {
my $name = $data_item->{name};
my $data = $data_item->{data}
my $data_hash{$name:$data} = \$data_item #Or something like this...
}
Now you can go through your newly created hash just once:
foreach my $key (keys %record_hash) {
if (exists $data_hash{$key}) {
print "match found $i->{name}, updating record in table\n";
}
else {
print "no match found for $tableDate $i->{port} $i->{owner} $i->{name} adding record to table\n";
executeStatement("INSERT INTO client_usage (date, port, owner, name, emailed) VALUES (\'$tableDate\', \'$i->{port}\', \'$i->{owner}\', \'$i->{name}\', '0')");
}
}
Let's say you have 1000 elements in one list, and 500 elements in the other. Your original algorithm would have to loop 500 * 1000 times (half a million times). By creating an index hash, you have to loop through 2(500 + 1000) times (about 3000 times).
Another possibility: Since you're already using a SQL database, why not do the whole thing as a SQL query. That is, don't fetch the records. Instead, go through your data, and for each data item, fetch the record. If the record exists, you update it. If not, you create a new one. That maybe even faster because you're not turning the whole thing into a list in order to turn it into a hash.
There's a way to tie SQL databases directly to hashes. That might be a good way to go too.
Are you using Perl-DBI?
How about using Data::Difference:
use Data:Difference qw(data_diff);
my #diff = data_diff(\%hash_a, \%hash_b);
#diff = (
{ 'a' => 'value', 'path' => [ 'data' ] }, # exists in 'a' but not in 'b'
{ 'b' => 'value', 'path' => [ 'data' ] }, # exists in 'b' not in 'a'
);