SELECT COUNT(*) doesn't work in QML - qt

I'm trying to get the number of records with QML LocalStorage, which uses sqlite. Let's take this snippet in account:
function f() {
var db = LocalStorage.openDatabaseSync(...)
db.transaction (
function(tx) {
var b = tx.executeSql("SELECT * FROM t")
console.log(b.rows.length)
var c = tx.executeSql("SELECT COUNT(*) FROM t")
console.log(JSON.stringify(c))
}
)
}
The output is:
qml: 3
qml: {"rowsAffected":0,"insertId":"","rows":{}}
What am I doing wrong that the SELECT COUNT(*) doesn't output anything?
EDIT: rows only seems empty in the second command. Calling
console.log(JSON.stringify(c.rows.item(0)))
gives
qml: {"COUNT(*)":3}
Two questions now:
Why is rows shown as empty
How can I access the property inside c.rows.item(0)

In order to visit the items, you have to use:
b.rows.item(i)
Where i is the index of the item you want to get (in your first example, i belongs to [0, 1, 2] for you have 3 items, in the second one it is 0 and you can query it as c.rows.item(0)).
The rows field appears empty and it is a valid result, for the items are not part of the rows field itself (indeed you have to use a method to get them, as far as I know that method could also be a memento that completely enclose the response data) and the item method is probably defined as not enumerable (I cannot verify it, I'm on the beach and it's quite difficult to explore the Qt code now :-)). You can safely rely on the length parameter to know if there are returned values, thus you can iterate over them to print them out. I did something like that in a project of mine and it works fine.
The properties inside item(0) have the same names given for the query. I suggest to rewrite that query as:
select count(*) as cnt from t
Then, you can get the count as:
c.rows.item(0).cnt

Related

A Search Query Term Should Not Be Prefix of Any Data in Db

Give a table User_DNA and column a sequence,
I want to write a query such that if data in the sequence column matches or is prefix of the search query term, it should return an item found or true.
e.g,
sequence
dog
hor
cat
tig
cat
if my search query is doga (has dog as prefix in db), horrible(has hor as prefix in db),tiger(has tig as prefix in db), caterpillar(has cat as prefix in db), the query should return true as all these search queries have prefixes in the database.
What should my sql search query?
Thanks
If you use Room, you can try this (using Kotlin):
#Query("select * from User_DNA WHERE sequence LIKE :search")
fun getItem(search: String): UserDNA?
Setting your search parameter to this method you should put the search pattern as "[your search string]%", for example: "dog%"
if my search query is dog, the query should return true or one of the
items (dogsequence/doggysequence) what ever is efficient
You can check result of the query - if it's null, then there are no matching values in your column.
UPDATED
If you want to find "hor" with "horrible" I can propose next way (maybe it's a task for RegExp but honestly I haven't used it in ROOM):
You can put two methods in your DAO. One method is auxiliary, its task - is ti fill a list with words, that we want to find. For example, for pattern "horrible" that method should prepare list with {"horrible", "horribl", "horrib", "horri", "horr", "hor"}.
Second method should fetch a result from SQLite where your fields holds value from the list prepared on step1. This method should be annotated with Room annotation.
So first method prepares list, invokes query for searching word in SQLite and returns it to ViewModel (or Repository).
Something like this:
#Query("select * from User_DNA WHERE sequence IN (:search) ORDER BY sequence")
fun getItem(search: List<String>): User_DNA?
fun findItem(search: String): User_DNA? {
val searchList = mutableListOf<String>()
val minimalStringLength = 2 // it's up to you, maybe 1?
while (search.length > minimalStringLength) {
searchList.add(search)
search = search.dropLast(1)
}
return getItem(searchList.toList())
}

How to retrieve a node based on its top-most parent node in Neo4j

I have a hierarchy of node relationships like:
Organisation -> Department -> System -> Function -> Port - > Request -> Response -> Parameter
The query -
MATCH q=(p)-[*]->(b:checkoutby) WHERE p.name ="william" RETURN q
gives the entire network belonging to the Parent node -> william up-till the last node mentioned -> checkoutby.
However, I want only the two related nodes to appear.
I tried the query -
MATCH (n:william) WHERE n is null RETURN n UNION MATCH n=(p)-
[:Parameter]->(b) WHERE
b.name ="checkoutBy" RETURN n
But here the effect of "william" node i.e. the first parent node is nullified and we get the output irrespective of the parent node.
For which, I even tried this query -
MATCH (n) WHERE none(node in nodes(n) WHERE node:william) RETURN n
UNION MATCH n=(p)--()-[:Parameter]->(b) WHERE b.name ="cabinet"
RETURN n
but I get error -
Neo.ClientError.Statement.SyntaxError: Type mismatch: expected Path but was Node (line 1, column 36 (offset: 35))
"MATCH (n) WHERE none(node in nodes(n) WHERE node: william ) RETURN n UNION MATCH n=(p)--()-[:Parameter]->(b) WHERE b.name ="cabinet" RETURN n"
I even tried the intersection query but to no avail .
MATCH (n1:william), (n2),(q:cabinet)
WHERE (n1)<-[:Department]-() AND (n2)<-[:Parameter]-(q)
RETURN count(q), collect(q.name)
Warning Error-
This query builds a Cartesian product between disconnected patterns.
If a part of a query contains multiple disconnected patterns, this will build a Cartesian product between all those parts. This may produce a large amount of data and slow down query processing. While occasionally intended, it may often be possible to reformulate the query that avoids the use of this cross product, perhaps by adding a relationship between the different parts or by using OPTIONAL MATCH (identifier is: (n2))
EXPLAIN MATCH (n1:william), (n2),(ego:cabinet)
^
Even this query doesn't work -
MATCH (n:william) RETURN n UNION MATCH n=(p)-[:Parameter]->(b)
WHERE b.name ="checkoutBy"
call apoc.path.expandConfig(n, {labelFilter:'-william'}) yield path
return path
I want to retrieve the checkoutby / cabinet node only if it is from the topmost parent node (william).
I don't have reputations to comment so asking here:
It's not clear from your question if William is a Name property or a Label?
You used it as a name in the first query and as a Label in all other queries.
I am assuming it is a Label, It looks like it is a label from the screenshot you shared.
If you want to check if the checkoutby/cabinet node is related to William node and return only if it's related you can use the following query:
MATCH (w:william)-[*]-(c:checkoutby) return w,c
Please note: These type of queries consumes too much Memory.
If I've understood your problem the (b:checkoutby) node does not have any incoming relationships so you could write :
MATCH (p)-[*]->(b:checkoutby) WHERE p.name ="william" AND NOT EXISTS ( (b)-[]->()) RETURN p, b

complex reduce sample unclear how the reduce works

Starting with complex reduce sample
I have trimmed it down to a single chart and I am trying to understand how the reduce works
I have made comments in the code that were not in the example denoting what I think is happening based on how I read the docs.
function groupArrayAdd(keyfn) {
var bisect = d3.bisector(keyfn); //set the bisector value function
//elements is the group that we are reducing,item is the current item
//this is a the reduce function being supplied to the reduce call on the group runAvgGroup for add below
return function(elements, item) {
//get the position of the key value for this element in the sorted array and put it there
var pos = bisect.right(elements, keyfn(item));
elements.splice(pos, 0, item);
return elements;
};
}
function groupArrayRemove(keyfn) {
var bisect = d3.bisector(keyfn);//set the bisector value function
//elements is the group that we are reducing,item is the current item
//this is a the reduce function being supplied to the reduce call on the group runAvgGroup for remove below
return function(elements, item) {
//get the position of the key value for this element in the sorted array and splice it out
var pos = bisect.left(elements, keyfn(item));
if(keyfn(elements[pos])===keyfn(item))
elements.splice(pos, 1);
return elements;
};
}
function groupArrayInit() {
//for each key found by the key function return this array?
return []; //the result array for where the data is being inserted in sorted order?
}
I am not quite sure my perception of how this is working is quite right. Some of the magic isn't showing itself. Am I correct that elements is the group the reduce function is being called on ? also the array in groupArrayInit() how is it being indirectly populated?
Part of me feels that the functions supplied to the reduce call are really array.map functions not array.reduce functions but I just can't quite put my finger on why. having read the docs I am just not making a connection here.
Any help would be appreciated.
Also have I missed Pens/Fiddles that are created for all these examples? like this one
http://dc-js.github.io/dc.js/examples/complex-reduce.html which is where I started with this but had to download the csv and manually convert to Json.
--------------Update
I added some print statements to try to clarify how the add function is working
function groupArrayAdd(keyfn) {
var bisect = d3.bisector(keyfn); //set the bisector value function
//elements is the group that we are reducing,item is the current item
//this is a the reduce function being supplied to the reduce call on the group runAvgGroup for add below
return function(elements, item) {
console.log("---Start Elements and Item and keyfn(item)----")
console.log(elements) //elements grouped by run?
console.log(item) //not seeing the pattern on what this is on each run
console.log(keyfn(item))
console.log("---End----")
//get the position of the key value for this element in the sorted array and put it there
var pos = bisect.right(elements, keyfn(item));
elements.splice(pos, 0, item);
return elements;
};
}
and to print out the group's contents
console.log("RunAvgGroup")
console.log(runAvgGroup.top(Infinity))
which results in
Which appears to be incorrect b/c the values are not sorted by key (the run number)?
And looking at the results of the print statements doesn't seem to help either.
This looks basically right to me. The issues are just conceptual.
Crossfilter’s group.reduce is not exactly like either Array.reduce or Array.map. Group.reduce defines methods for handling adding new records to a group or removing records from a group. So it is conceptually similar to an incremental Array.reduce that supports an reversal operation. This allows filters to be applied and removed.
Group.top returns your list of groups. The value property of these groups should be the elements value that your reduce functions return. The key of the group is the value returned by your group accessor (defined in the dimension.group call that creates your group) or your dimension accessor if you didn’t define a group accessor. Reduce functions work only on the group values and do not have direct access to the group key.
So check those values in the group.top output and hopefully you’ll see the lists of elements you expect.

Using Rascal MAP

I am trying to create an empty map, that will be then populated within a for loop. Not sure how to proceed in Rascal. For testing purpose, I tried:
rascal>map[int, list[int]] x;
ok
Though, when I try to populate "x" using:
rascal>x += (1, [1,2,3])
>>>>>>>;
>>>>>>>;
^ Parse error here
I got a parse error.
To start, it would be best to assign it an initial value. You don't have to do this at the console, but this is required if you declare the variable inside a script. Also, if you are going to use +=, it has to already have an assigned value.
rascal>map[int,list[int]] x = ( );
map[int, list[int]]: ()
Then, when you are adding items into the map, the key and the value are separated by a :, not by a ,, so you want something like this instead:
rascal>x += ( 1 : [1,2,3]);
map[int, list[int]]: (1:[1,2,3])
rascal>x[1];
list[int]: [1,2,3]
An easier way to do this is to use similar notation to the lookup shown just above:
rascal>x[1] = [1,2,3];
map[int, list[int]]: (1:[1,2,3])
Generally, if you are just setting the value for one key, or are assigning keys inside a loop, x[key] = value is better, += is better if you are adding two existing maps together and saving the result into one of them.
I also like this solution sometimes, where you instead of joining maps just update the value of a certain key:
m = ();
for (...whatever...) {
m[key]?[] += [1,2,3];
}
In this code, when the key is not yet present in the map, then it starts with the [] empty list and then concatenates [1,2,3] to it, or if the key is present already, let's say it's already at [1,2,3], then this will create [1,2,3,1,2,3] at the specific key in the map.

Can I insert into a map by key in F#?

I'm messing around a bit with F# and I'm not quite sure if I'm doing this correctly. In C# this could be done with an IDictionary or something similar.
type School() =
member val Roster = Map.empty with get, set
member this.add(grade: int, studentName: string) =
match this.Roster.ContainsKey(grade) with
| true -> // Can I do something like this.Roster.[grade].Insert([studentName])?
| false -> this.Roster <- this.Roster.Add(grade, [studentName])
Is there a way to insert into the map if it contains a specified key or am I just using the wrong collection in this case?
The F# Map type is a mapping from keys to values just like ordinary .NET Dictionary, except that it is immutable.
If I understand your aim correctly, you're trying to keep a list of students for each grade. The type in that case is a map from integers to lists of names, i.e. Map<int, string list>.
The Add operation on the map actually either adds or replaces an element, so I think that's the operation you want in the false case. In the true case, you need to get the current list, append the new student and then replace the existing record. One way to do this is to write something like:
type School() =
member val Roster = Map.empty with get, set
member this.Add(grade: int, studentName: string) =
// Try to get the current list of students for a given 'grade'
let studentsOpt = this.Roster.TryFind(grade)
// If the result was 'None', then use empty list as the default
let students = defaultArg studentsOpt []
// Create a new list with the new student at the front
let newStudents = studentName::students
// Create & save map with new/replaced mapping for 'grade'
this.Roster <- this.Roster.Add(grade, newStudents)
This is not thread-safe (because calling Add concurrently might not update the map properly). However, you can access school.Roster at any time, iterate over it (or share references to it) safely, because it is an immutable structure. However, if you do not care about that, then using standard Dictionary would be perfectly fine too - depends on your actual use case.

Resources