Where clause using some field is not returning any rows in phonegap - sql

I am finding one funny error but not sure whether that is my mistake or not. Below is my code for phonegap storage application. I have to fetch the records by one field in SELECT Query. If I try without where condition it s working but with where clause it is not working. Anyone have an idea on this?
function setDetailWordList()
{
db.transaction(SetDetailWords);
}
function SetDetailWords(tx)
{
alert("Qiuery executing...");
alert('SELECT * FROM DW_Words WHERE word = "'+word+'"');
tx.executeSql('SELECT * FROM DW_Words where word = "'+word+'"', [], SetDetailWordsSuccess);
}
function SetDetailWordsSuccess(tx,results)
{
alert(results.rows.length);
$('#words').html("").listview('refresh');
for (var i=0; i < results.rows.length; i++)
{
$('#words').append('<li><a><div>'+results.rows.item(i).explanation+'</div></a></li>');
}
$('#words').listview('refresh');
//AddEvents();
}

Related

How do perform a graph query and join?

I apologize for the title, I don't exactly know how to word it. But essentially, this is a graph-type query but I know RavenDB's graph functionality will be going away so this probably needs to be solved with Javascript.
Here is the scenario:
I have a bunch of documents of different types, call them A, B, C, D. Each of these particular types of documents have some common properties. The one that I'm interested in right now is "Owner". The owner field is an ID which points to one of two other document types; it can be a Group or a User.
The Group document has a 'Members' field which contains an ID which either points to a User or another Group. Something like this
It's worth noting that the documents in play have custom IDs that begin with their entity type. For example Users and Groups begin with user: and group: respectively. Example IDs look like this: user:john#castleblack.com or group:the-nights-watch. This comes into play later.
What I want to be able to do is the following type of query:
"Given that I have either a group id or a user id, return all documents of type a, b, or c where the group/user id is equal to or is a descendant of the document's owner."
In other words, I need to be able to return all documents that are owned by a particular user or group either explicitly or implicitly through a hierarchy.
I've considered solving this a couple different ways with no luck. Here are the two approaches I've tried:
Using a function within a query
With Dejan's help in an email thread, I was able to devise a function that would walk it's way down the ownership graph. What this attempted to do was build a flat array of IDs which represented explicit and implicit owners (i.e. root + descendants):
declare function hierarchy(doc, owners){
owners = owners || [];
while(doc != null) {
let ownerId = id(doc)
if(ownerId.startsWith('user:')) {
owners.push(ownerId);
} else if(ownerId.startsWith('group:')) {
owners.push(ownerId);
doc.Members.forEach(m => {
let owner = load(m, 'Users') || load(m, 'Groups');
owners = hierarchy(owner, owners);
});
}
}
return owners;
}
I had two issues with this. 1. I don't actually know how to use this in a query lol. I tried to use it as part of the where clause but apparently that's not allowed:
from #all_docs as d
where hierarchy(d) = 'group:my-group-d'
// error: method hierarchy not allowed
Or if I tried anything in the select statement, I got an error that I have exceeded the number of allowed statements.
As a custom index
I tried the same idea through a custom index. Essentially, I tried to create an index that would produce an array of IDs using roughly the same function above, so that I could just query where my id was in that array
map('#all_docs', function(doc) {
function hierarchy(n, graph) {
while(n != null) {
let ownerId = id(n);
if(ownerId.startsWith('user:')) {
graph.push(ownerId);
return graph;
} else if(ownerId.startsWith('group:')){
graph.push(ownerId);
n.Members.forEach(g => {
let owner = load(g, 'Groups') || load(g, 'Users');
hierarchy(owner, graph);
});
return graph;
}
}
}
function distinct(value, index, self){ return self.indexOf(value) === index; }
let ownerGraph = []
if(doc.Owner) {
let owner = load(doc.Owner, 'Groups') || load(doc.Owner, 'Users');
ownerGraph = hierarchy(owner, ownerGraph).filter(distinct);
}
return { Owners: ownerGraph };
})
// error: recursion is not allowed by the javascript host
The problem with this is that I'm getting an error that recursion is not allowed.
So I'm stumped now. Am I going about this wrong? I feel like this could be a subquery of sorts or a filter by function, but I'm not sure how to do that either. Am I going to have to do this in two separate queries (i.e. two round-trips), one to get the IDs and the other to get the docs?
Update 1
I've revised my attempt at the index to the following and I'm not getting the recursion error anymore, but assuming my queries are correct, it's not returning anything
// Entity/ByOwnerGraph
map('#all_docs', function(doc) {
function walkGraph(ownerId) {
let owners = []
let idsToProcess = [ownerId]
while(idsToProcess.length > 0) {
let current = idsToProcess.shift();
if(current.startsWith('user:')){
owners.push(current);
} else if(current.startsWith('group:')) {
owners.push(current);
let group = load(current, 'Groups')
if(!group) { continue; }
idsToProcess.concat(group.Members)
}
}
return owners;
}
let owners = [];
if(doc.Owner) {
owners.concat(walkGraph(doc.Owner))
}
return { Owners: owners };
})
// query (no results)
from index Entity/ByOwnerGraph as x
where x.Owners = "group:my-group-id"
// alternate query (no results)
from index Entity/ByOwnerGraph as x
where x.Owners ALL IN ("group:my-group-id")
I still can't use this approach in a query either as I get the same error that there are too many statements.

React Native sqlite issues selecting where column is NULL

I have React Native project where I am using react-native-sqlite-store (npm i react-native-sqlite-storage). The issue is that I get no results when I try the follow query show below. I need to be able to select all rows where the columns have exact match with the values. I need to also be able to select where the value could be NULL. With the correct code I am not able to get results however if I remove the midiGroup field from the query I get results. Not sure how to fix this.
Basically I need to be able to check even if a column has NULL. In React Native the message?.midiGroup value is null
tx.executeSql(
"SELECT * FROM MidiMap WHERE midiType= ? AND midiNote= ? AND midiChannel= ? AND midiVelocity= ? AND midiGroup= ?;",
[
message?.midiType, // <---- noteOn
message?.midiNote, // <---- 60
message?.midiChannel, // <---- 0
message?.midiVelocity, // <---- 64
message?.midiGroup, // <---- for this query midiGroup is null
],
(sqlTx, res) => {
console.log(activeProfile, message?.midiType);
let len = res.rows.length;
// Check for items here
if (len > 0) {
for (let i = 0; i < len; i++) {
let item = res.rows.item(i);
// Trigger here
console.log(item);
}
}
},
(error) => {
console.log(`Error checking results for midi triggering: ${error.message}`);
}
);
Use the operator IS to make comparisons against null.
Depending on your requirement, your query could be written as:
SELECT *
FROM MidiMap
WHERE midiType = ?
AND midiNote = ?
AND midiChannel = ?
AND midiVelocity = ?
AND midiGroup IS ?;
or:
SELECT *
FROM MidiMap
WHERE midiType = ?
AND midiNote = ?
AND midiChannel = ?
AND midiVelocity = ?
AND (midiGroup = ? OR midiGroup IS NULL);

Deleting many managed objects selectd by fragment name

I want to delete many managed objects, selected by fragment type. There are more then 2000 elements in it. Unfortunately I can not delete all with one function call. I have to call this function many times until I have deleted all. How can I delete a list of managed objects in a sufficient way? Not defining page size did not help...
This is my current function:
InventoryFilter filter = new InventoryFilter();
filter.byFragmentType("xy_fragment");
ManagedObjectCollection moc = inventoryApi.getManagedObjectsByFilter(filter);
int count = 0;
// max page size is 2000
for (ManagedObjectRepresentation mo : moc.get(2000).allPages()) {
if (mo.get("c8y_IsBinary") != null) {
binariesApi.deleteFile(mo.getId());
} else {
inventoryApi.delete(mo.getId());
}
LOG.debug(count + " remove: " + mo.getName() + ", " + mo.getType());
count++;
}
LOG.info("all objectes removed, count:" + count);
By calling moc.get(2000).allPages() you already obtain an iterator that queries following pages on demand as you iterate over it.
The problem you are facing is caused by deleting elements from the same list you are iterating over. You delete element from the first page, but once the second page is queried from the server it does not contain the expected elements anymore because you already deleted the first page. Now all elements are shifted forward by your page size.
You can avoid all of that by making a local copy of all elements you want to delete first:
List<ManagedObjectRepresentation> allObjects = Lists.newArrayList( moc.get(2000).allPages())
for (ManagedObjectRepresentation mo : allObjects) {
//delete here
}
There is no bulk delete allowed on the inventory API so your method of looping through the objects is the correct approach.
A bulk delete is already a dangerous tool on the other APIs but on the inventory API it would give you the potential to accidentally delete all your data with just one call (as all data associated with a managedObject is also deleted upon the deletion of the managedObject).
That is why it is not available.
I solved the problem by calling the method until no elements can be found any more. It is not nice but I have no other idea.
public synchronized void removeManagedObjects(String deviceTypeKey) {
int count = 0;
do {
count = deleteManagedObjectes(deviceTypeKey);
}while(count > 0);
}
private int deleteManagedObjectes(String deviceTypeKey) {
InventoryFilter filter = new InventoryFilter();
filter.byFragmentType("xy_fragment");
ManagedObjectCollection moc = inventoryApi.getManagedObjectsByFilter(filter);
int count = 0;
if(moc == null) {
LOG.info("ManagedObjectCollection are NULL");
return count;
}
for (ManagedObjectRepresentation mo : moc.get(2000).allPages()) {
if (mo.get("c8y_IsBinary") != null) {
binariesApi.deleteFile(mo.getId());
} else {
inventoryApi.delete(mo.getId());
}
LOG.debug(count + " remove: " + mo.getName() + ", " + mo.getType());
count++;
}
LOG.info("all objectes removed, count:" + count);
return count;
}

Orderby rotating values in laravel

I am trying to create a sort by feature for "recommended" on my ecommerce site using the orderBy method. Here's a sample of a simple orderby:
if($params['sortby'] == 'numpricehl') $query->orderBy('price','desc');
What I am hoping to do is order by rotating values. Example: Given 10 products priced at: (10,20,30,....100), it would order them like this (low,mid,high,low,mid,high) etc. so that the products would display like this (10,50,100,20,60,80)
What would be the best way to go about doing this?
Here's a solution that works on the query result:
$tiers = 3;
$result = [];
$products = Product::orderBy('price')->get();
$size = ceil($products->count() / $tiers);
$split = $products->pluck('price')->chunk($size);
while(!$split[0]->isEmpty()) {
for($tier = 0; $tier < $tiers; $tier++) {
if(!$split[$tier]->isEmpty()) {
$result[] = $split[$tier]->shift();
}
}
}
There's probably an in-database solution with orderBy(), but I'm pretty sure it's more complicated.
The chunk() part isn't ideal yet because it splits 10 products into 4,4,2.
You can add this to get 4,3,3:
if($products->count() % $tiers == 1) {
$split[2]->prepend($split[1]->pop());
}

Filter cached sqlJdbs query in Pentaho CE

I use sqlJdbs query as a data provider for my CCC controls. I use geospatial request in my query that's why I cache my results(Cache=True). Otherwise the request made long.
It works fine. However I have to use parameters in my query to filter resulting rows:
SELECT ...
FROM ...
WHERE someField IN (${aoi_param})
Is there some way to cache full set of rows and then apply WHERE to cached results without rebuilding new cache for each set of values in the ${aoi_param}?
What is the best practice?
So, I am not really sure that it is the best practice, but I solved my problem this way:
I included aoi_param to the Listeners and Parameters of my chart control
Then I filtered data set in Post Fetch:
function f(data){
var _aoi_param = this.dashboard.getParameterValue('${p:aoi_param}');
function isInArray(myValue, myArray) {
var arrayLength = myArray.length;
for (var i = 0; i < arrayLength; i++) {
if (myValue == myArray[i]) return true;
}
return false;
}
function getFiltered(cdaData, filterArray) {
var allCdaData = cdaData;
cdaData = {
metadata: allCdaData.metadata,
resultset: allCdaData.resultset.filter(function(row){
// 2nd column is an AOI id in my dataset
return isInArray(row[2], filterArray);
})
};
return cdaData;
}
var dataFiltered = getFiltered(data, _aoi_param);
return dataFiltered;
}
excluded WHERE someField IN (${aoi_param}) from the query of my sql over sqlJdbc component