Send parameters to sqlite function on Phonegap - javascript

I have a list with some items, & a loop in which I check whether each item in the list is found in the database or not (To insert it if it's not found).
function AddItems(tx)
{
for(var i = 0 ; i<itemscounter; i++)
{
itemI=itemsList[i];
tx.executeSql('SELECT * FROM Items Where ItemsTable.ItemId="'+itemI+'"', [], AddItemsToDB, errorCB);
}
}
The problem is that the function waits till it finishes all the iterations then execute the sqlite statement so the itemI value is always equal to itemsList[itemscounter].
So it enters the AddItemsToDB "items counter" times, but always with the same value (the last one in the array).
This is the success Function:
function AddItemsToDB(tx, results)
{
var len = results.rows.length;
alert(itemI); // Always has the same value!
if(len==0)
{
tx.executeSql('INSERT INTO ItemsTable (ItemId) VALUES ('+itemI +')');
}
}
So, I'm wondering if there is some method to pass parameters at the success function itself, or if there is another method to pass the items one by one ?

Yes , there is.Try something like this:
tx.executeSql('SELECT * FROM Items Where ItemsTable.ItemId="'+itemI+'"', [],
(function(itemI){
return function(tx,results){
AddItemsToDB(tx,results,itemI);
};
})(itemI), errorCB);
And modify AddItemsToDB like a:
function AddItemsToDB(tx, results, itemI) {

Related

How to run a function for each item in an array or write array objects individually on Mongoose

Hi everyone I'm trying to create an API for calculating revenue from a calculator service, all it essentially does is grab the values from the dB that the calculator needs and pass them through it and get the resulting values. I need to write the results back into the dB however for logging.
I'm having some problems however
I am trying to pass some objects from a Mongoose array to a JSON API URL service using axios get and I'm having trouble writing the resulting array to my Mongoose dB
Can anyone help me with what I'm missing?
See below
/* Users :
_id : 5cac
username: sample
email: email#email.com
orderHistory: [
{xmr_hr: 9000},
{xmr_hr: 2000},
{xmr_hr: 3000}
],
profitHistory:[
{
xmr_usd_gross:
}
]
*/
var email = "email#email.com"
var id = "5cac"
function xmr(callback){
function getUsers(){
var cursor = User.find({email: email}, function (err, users) {
}).cursor();
return cursor;
}
var cursor = getUsers();
cursor.on('data', function(name){
const xmr_hr= name.orderHistory.map(element => element.xmr_hr);
var xmrLength = xmr_hr.length;
for (var i = 0; i < xmrLength; i++) {
console.log(xmr_hr[i]
// returns [9000,2000,3000]
// variables
var algo = "cn8"
var hr = xmr_hr
var wttURL = "wtt.com/json" + algo + hr[i]
axios.get(wttURL)
.then((response) => {
var btcGrossRevenue = response.data.coins.Monero.btc_revenue
console.log(btcGrossRevenue)
// runs through each value in array and returns revenue [0.06, 0.02, 0.03]
// below is my problem
var updateProfits = [{
xmr_usd_gross : btcGrossRevenue,
}]
User.findByIdAndUpdate(id, {upsert: false, "$addToSet": { 'profitHistory': updateProfits}},
function(err, user) {
if(err) { console.log(err) }
else {
console.log(user.length)
};
})
})
}
// initial callback
for (var v = 1; v < 2; v++)
xmr(function(v){})
// cronJob and callback continuation
var xmrJob = new cron.CronJob('* 10 * * * *', function() {
console.log('Function executed!');
for (var v = 1; v < 2; v++) // amount of times to run function
xmr(function(v){})
}, null, true);
xmrJob.start
I know the problem is the fact that I'm trying to write an array to an object inside an array, but I'm not sure how to pass each object in the array individually.
I am thinking either there is a way to do it by just running the callback function individually for each object item in the array or find the ability to dissect the resulting array and write them sequentially.
I would like for my Collections to look like this once everything is written
/* Users :
_id : 5cac
username: sample
email: email#email.com
orderHistory: [
{xmr_hr: 9000},
{xmr_hr: 2000},
{xmr_hr: 3000}
],
profitHistory:[
{xmr_usd_gross: 0.06},
{xmr_usd_gross: 0.03},
{xmr_usd_gross: 0.02},
]
*/
Any help would be much appreciated
You can use the Map function.
const fn = (item) => {
return item *10;
}
[1,2,3,4,5].map( fn );
with this simple example, the function fn is executed on each item in the map and returns a value. If you assign it to something you can leverage that value resulting array.
I obviously seperated them out but you can easily do them inline as well.... or leverage the forEach function.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
[1,2,3,4,5].map( item => item * 10 );
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach
[1,2,3,4,5].forEach( item => {
console.log( item * 10 );
});
Your arrays can be anything, objects, numbers whatever, and similarly... you can do anything in the functions.

Array returning empty in Javascript

This is all still pretty new to me but I am running into an interesting behavior issue when generating an array of numbers in a NodeJS application that handles .nessus result files. First, some details on what I am trying to accomplish. My application generates an array [1234,1223,1222] of entries from an uploaded "results" file that is then used to query a mongodb instance to determine if those entries are currently in the DB. If those entries are not currently in the mongodb instance, it redirects to a page where a user can edit them before being added. If there are no new entries, it goes to a page to generate a report on the entries.
When a file is uploaded, it stores the new entries. In .nessus files, sometimes there is more than one host with entries. That changes the json structure and the function needs to iterate a little differently. The following function is how those entries are stored. This is important as this is where the weird behavior originates (I think)
function parsePluginNumbers(json){
var pluginNumbers = []
//Let's check the number of hosts
var hostLength = json['NessusClientData_v2']['Report'].ReportHost.length
if (hostLength != undefined) {
for (var i = 0; i < hostLength; i++) { //Since there is more than 1, need to iterate over each host to find the findings.
var item_length = json['NessusClientData_v2']['Report'].ReportHost[i].ReportItem.length
for (var t = 0; t < item_length; t++) { //Iterate through each finding on each host
if (json['NessusClientData_v2']['Report'].ReportHost[i].ReportItem[t].risk_factor != 'None') {
var newEntry = json['NessusClientData_v2']['Report'].ReportHost[i].ReportItem[t].pluginID
if (pluginNumbers.indexOf(newEntry) == -1) {
pluginNumbers.push(newEntry)
}
else {
continue
}
} else {
continue
}
}
}
} else {
var item_length = json['NessusClientData_v2']['Report']['ReportHost'].ReportItem.length
for (var t = 0; t < item_length; t++) { //Iterate over findings
if (json['NessusClientData_v2']['Report']['ReportHost'].ReportItem[t].risk_factor != 'None') {
var newEntry = json['NessusClientData_v2']['Report']['ReportHost'].ReportItem[t].pluginID
if (pluginNumbers.indexOf(newEntry) == -1) {
pluginNumbers.push(newEntry)
}
else {
continue
}
} else {
continue
}
}
}
return pluginNumbers
}
Once those plugins are stored. Another function is called to look if those results are in the mongodbinstance. In this function, those plugins are in an array "pluginsTotal".
function queryForNewResultsInANessusFile(pluginsTotal, collectionname, filename){ //function to call mongodb query and send results to parseNewFindings and parseOldFindings.
var db = req.db;
var collection = db.get(collectionname);
collection.find({ 'PluginNumber' : { $in: pluginsTotal }}, 'FindingTitle FindingDescription Remediation Mitigation SeeAlso PluginFamily PluginNumber CVE Risk -_id', function(error, result){
var newPluginArray = parseOutFindingNumbersInMongoDB(result, pluginsTotal);
//IF statements go here with specific redirects as needed to check if there are new values not in the repo
}
During this collection.find call, there is a function parseOutFindingNumbersInMongoDB that is called to determine if there are plugins in the .nessus results file that are not in the repo. It compares the results from collection.find and pluginsTotal (generated from the first function) and returns an array of the new plugins that are not in the repo. The function details are below:
function parseOutFindingNumbersInMongoDB(repoResults, reportPlugins) {
for (var i = 0; i < repoResults.length; i++){
var index = reportPlugins.indexOf(repoResults[i].PluginNumber);
if (index != -1) {
reportPlugins.splice(index, 1);
}
else {
continue
}
}
return reportPlugins
}
Now to my question --- When I upload a .nessus file with more than one host, parseOutFindingNumberInMongoDB always returns empty even though there are new entries. What gives? Is it the way I parse out the numbers to begin with in the parsePluginNumbers function or is because it is called in the collection.find synchronous function (This seems unlikely as if there is one host, it returns the new plugin values as I want)? Any thoughts/ideas/review would be much appreciated as I cannot figure out what is wrong. I have checked the data types within the array before being passed into the functions and they all match up.
It's always returning an empty array because every element in the array matches the condition to be spliced.
You first retrieve elements that have a PluginNumber in pluginTotal array with this filter { $in: pluginsTotal }
collection.find({ 'PluginNumber' : { $in: pluginsTotal }}, 'FindingTitle FindingDescription Remediation Mitigation SeeAlso PluginFamily PluginNumber CVE Risk -_id', function(error, result){
var newPluginArray = parseOutFindingNumbersInMongoDB(result, pluginsTotal);
}
Then you remove all elements that have a PluginNumber in pluginTotal
var index = reportPlugins.indexOf(repoResults[i].PluginNumber);
if (index != -1) {
reportPlugins.splice(index, 1);
}
So the result is always an empty array.

Javascript function always returns 0

I am writing a function which searches for a value in my IndexedDB and if it finds one, then it should return 1, else it should return 0. The problem is that it always returns 0 though the value exists in a database (variable arr is incremented, but 0 is returned as a result). The code is as follows:
searchAllValues: function(store, type)
{
var arr = 0;
AAA.initDb(function()
{
var obj = {};
AAA.aaaDb.transaction(store).objectStore(store).openCursor().onsuccess = function(store)
{
var storeresult = store.target.result;
if(storeresult.value.value == type ){
arr++;
}else{console.log('value NOT found');}
storeresult ? (obj[storeresult.key] = storeresult.value.value, storeresult["continue"]()) : callback(obj)
}
});if(arr!=0){return 1}else{return 0}
}
EDIT_1:
Ok, I have refactored the code as follows:
addInfo: function(store, type, info)
{
var arr = [];
P4S.p4sPushDb.transaction(store).objectStore(store).openCursor().onsuccess = function(store)
{
var storeresult = store.target.result;
console.log('value of storeresult==>'+storeresult.value.value);
if(storeresult.value.value == info)
{
arr.push(storeresult.value.values);return;//If it finds something it should stop here, no more search or anything to be done
}else
{
console.log('continuing..');
storeresult['continue']();
}
console.log('arr length==> '+arr.length);//If it finds nothing after the looping the whole DB, I want it to print this statement, only once (to send it to my DB actually but sending code is omitted for simplicity).
}
}
Instead I get console.log('arr length==>') statement executed 2 times, for every key in my object store (there are 2 of them actually). So it is doing the code when it finds nothing AND when it finds the value in the DB. Any ideas how to fix it?
Any ideas would be welcome, Thank You
Because by the time the line if(arr!=0){return 1}else{return 0} is executed the db transaction is not complete and value of arr is 0. Though never used indexedDb, but webSql do take some extra miliseconds to read from DB.
Try to put your return logic inside the onsuccess function where you incrementing the arr. You can simply test it by printing value of arr just before your return logic
You need to learn about how to write asynchronous javascript. There are several other indexedDB questions where there are explanations as to why this happens.
For example: Uncaught TypeError: Cannot read property 'transaction' of null with an indexeddb
function addInfo(store, type, info, next)
{
var arr = [];
P4S.p4sPushDb.transaction(store).objectStore(store).openCursor().onsuccess = function(store)
{
var storeresult = store.target.result;
console.log('value of storeresult==>'+storeresult.value.value);
if(storeresult.value.value == info)
{
arr.push(storeresult.value.values);
next(arr);//If it finds something it should stop here, no more search or anything to be done
}else
{
console.log('continuing..');
storeresult.continue();
}
console.log('arr length==> '+arr.length);//If it finds nothing after the looping the whole DB, I want it to print this statement, only once (to send it to my DB actually but sending code is omitted for simplicity).
}
}
Added an extra parameter called 'next' to your the addInfo function.
'next' param is the very last function called if the condition (storeresult.value.value == info) is true.
The next function which you create, will use the 'arr' variable and do whatever with it
your 'return statement' doesnt work the sameway with asynchronous functions, would highly advice you search up asynchronous functions to get a gist of how its different to regular functions
This is how you would call your newly edited function:
addInfo(store,type,info,function(arr){
//do something with arr
})
Note that you have a potential state which would break your code
what if the cursor reaches the end of its iterations and never meets that condition (storeresult.value.value == info). storeresult would be null, and the check for the condition (null.value.value == info) will throw an exception
correction:
function addInfo(store, type, info, next)
{
var arr = [];
P4S.p4sPushDb.transaction(store).objectStore(store).openCursor().onsuccess = function(store){
var storeresult = store.target.result;
if(storeresult){
if(storeresult.value.value == info){
arr.push(storeresult.value.values);
next(arr);
}else storeresult.continue();
}else next();
}
}
And when you call it you handle the scenario whereby arr == null
addInfo(store,type,info,function(arr){
if(arr){
//do something with arr
}else{
//do somethingelse when arr == null
}
})

how to return results to the calling function (development of a firefox extension)

In my firefox extension I have a sqlite-database with some tables. Using executeAsync(), I updated the tables, inserted some new data and selected some values. The select-case cause me some problems.
Within the handleCompletion()-function I can pass the retrieved data from the table to another function (and can alerting the results, for example). But I would like to pass the result back to the calling function. I searched the net for an answer to my problem, but I can't find a solution.
What I found:
retrieveData: function() {
var rows = new Array();
if (this.dbConn.connectionReady){
statement = this.dbConn.createAsyncStatement("SELECT * " +
"FROM 'domains' " +
";");
statement.executeAsync ({
handleResult: function(aResultSet) {
var i = 0;
for (let row = aResultSet.getNextRow(); row; row = aResultSet.getNextRow()) {
rows[i] = row;
++i;
}
},
handleError: function(anError) {
alert("error");
},
handleCompletion: function(aReason) {
if (aReason != Components.interfaces.mozIStorageStatementCallback.REASON_FINISHED) {
// something went wrong
alert("error2");
}
}
});
}
return rows;
}
This code does not return the expected results. The statement is executed after the method returned the Array "rows". So, my calling function can never receive the data from the table...
How can I solve this problem? Is there something like a timeout for returning the datarows of the table?
Thanks a lot for help!
You should ideally be dealing in callbacks in the above example. Thats how the SQLite API developers intended the API to be used. :)
retrieveData: function(_callback) {
...
statement.executeAsync ({
...
handleCompletion: function(aReason) {
...
_callback(rows);
}
});
}
And where you call the function:
retrieveData(function(rows) {
// do stuff with rows here
});

Nested HTML5 Web SQL Query Issued after Entire For Loop Processed

In this query listed below, my for loop is executing 4 values. In the first alert(id), it is alerting those 4 distinct values. However, in the nested query, the alert statement is printing out the last id value only, 4x with different max(b.id) values. I'm confused. Does anyone know what may be happening? Could a race condition be occurring?
My goal is to place an Ajax call in the nested query, which has input values based on both id and b.id. I am currently doing this, but the value in the ajax call for the "id" is the same for all 4 different calls, which messes up the return data. Thanks.
database.db.transaction(function (tx) {
tx.executeSql('SELECT id, name from programs d', [], function (tx, results) {
for (var i = 0; i < results.rows.length; i++) {
var id = results.rows.item(i)['id'];
var name = results.rows.item(i)['name'];
alert(id);
tx.executeSql('SELECT max(b.id) + 1 max from people b where b.sid = ?',
[id],
function (tx, results) {
lastRecord = results.rows.item(0)['max'];
alert(id + "last rec: " + name);
}
);
}
},
function (event) { alert(event.message); });
As per my comments, you to return a closed function to bind the parameter correctly.
A much simpler example is the following:
Running this produces 4 alerts, all showing 4:
for (i=0;i<4;i++) {
setTimeout( function() { alert(i)}, 1000);
}
Running this produces 4 alerts, showing 0/4, 1/4, 2/4, 3/4.
for (i=0;i<4;i++) {
setTimeout(function(inneri) {
return(
function() {
alert(inneri + "/" + i);
}
);
}(i), 1000);
}
where I've named inneri the value that was preserved upon closure. Note that i, itself is still referring to the outer scope, and thus is 4 (which is what is true at time of execution, since that is the value of i when it dumps out of the for loop, as we're delaying the execution using setTimeout().
The first case is a simpler version of what you're doing, whereas you want the second case.
Rewriting your js (and hoping I get all these ( and {'s in the right place :) ) gives:
database.db.transaction(function (tx) {
tx.executeSql('SELECT id, name from programs d', [], function (tx, results) {
for (var i = 0; i < results.rows.length; i++) {
var id = results.rows.item(i)['id'];
var name = results.rows.item(i)['name'];
alert(id);
tx.executeSql('SELECT max(b.id) + 1 max from people b where b.sid = ?',
[id],
function(innerId) {
return (
function (tx, results) {
lastRecord = results.rows.item(0)['max'];
alert(innerId + "last rec: " + name);
}
);
}(id) //be careful to avoid the ";" here!
);
}
},
function (event) { alert(event.message);
});
Where I have inserted:
function(innerId) {
return (
function (tx, results) {
lastRecord = results.rows.item(0)['max'];
alert(innerId + "last rec: " + name);
}
);
}(id)
in. This function is called immediately via the (id) and returns a function that takes tx and results as arguments and does the appropriate action.
I have checked braces/parenthesis, but don't have a direct way to verify that I didn't make any typos.

Categories

Resources