I have a function that queries SQL to get a string called Prefix.
function getPrefix(Guild) {
let query = "SELECT Prefix FROM Guilds WHERE GuildId=?";
Connection.query(query, [Guild.id], (err, result) => {
if (err) throw err;
return result[0].GuildPrefix;
});
};
Whenever I print the Prefix out (console.log(result[0].Prefix);), it logs it fine - however, whenever I return it and then attempt to call the function, it always returns undefined.
I am using Node JS Version 10.15.1 & I am using MariaDB Version 10.1.37 on the Raspbian stretch of Debian. Please comment if I have left any other information out. Thanks.
In Nodejs the functions related to mysql are always asynchronous which means they will either not return anything or will retuen undefined.
So the solution is to use a callback function.
Eg.
function getPrefix(Guild, callback) {
let query = "SELECT Prefix FROM Guilds WHERE GuildId=?";
Connection.query(query, [Guild.id], (err, result) => {
if (err){
callback(JSON.stringify(err));
};
callback(JSON.stringify(result));
});
};
This has to be a scope issue that I'm not familiar with. I have a small module I've written as so:
(function () {
var getPlanInfo = function (id, conn) {
conn.query('SELECT * FROM `items` WHERE `id` = ?', [id], function (error, result) {
if (error) console.error('Query error: ' + error.stack);
console.log(result[0]); // Everything is great
return result[0];
});
};
modules.exports.getPlanInfo = function (id, conn) { return getPlanInfo(id, conn); // Typo }
})();
Here comes the problem. When I call it from anywhere (inside the module itself or another file), the return value is always undefined. I checked from within the function, the query returns the result as expected.
var backend = require('./module.js');
var t = backend.getPlanInfo();
t is undefined. This is the same if I call that method from inside the module itself (another function within that module).
I'm familiar with the callback principle in javascript and how objects and functions have to be passed around as an argument to remain in scope. Is this the issue here or is this a node.js particularity?
I tried in in the Developer Console (Chrome), works as expected.
conn.query() looks like it is async. Thus, you can't return its result from getPlanInfo() because getPlanInfo() returns long before the result is available. Returning result[0] from the conn.query() callback just returns a piece of data back into the conn.query() infrastructure. getPlanInfo() has long before already returned.
If you want an async result, then you will have to change getPlanInfo() to use a mechanism that supports getting async results such as a direct callback or a promise or something like that.
Here's a plain callback way:
var getPlanInfo = function (id, conn, callback) {
conn.query('SELECT * FROM `items` WHERE `id` = ?', [id], function (error, result) {
if (error) {
console.error('Query error: ' + error.stack);
callback(error);
return;
}
console.log(result[0]); // Everything is great
callback(0, result[0]);
});
};
modules.exports.getPlanInfo = getPlanInfo;
Then, the caller of that module would look like this:
var m = require('whatever');
m.getPlanInfo(id, conn, function(err, result) {
if (err) {
// error here
} else {
// process result here
}
});
You don't return anything from getPlanInfo. Probably you wanted to write modules.exports.getPlanInfo = function (id, conn) { return getPlanInfo; }
(with return getPlanInfo; instead of return getPlanInfo();)
Is there any example of js accessing device's (ios and android) sqlite db via Trigger.io?
The normal web database API is available: http://www.w3.org/TR/webdatabase/
Note: not all browsers support Web SQL http://caniuse.com/#feat=sql-storage
For example, one of the tests we run is similar to this:
var db = openDatabase('mydb', '1.0', 'example database', 2 * 1024 * 1024);
db.transaction(function (tx) {
tx.executeSql('CREATE TABLE IF NOT EXISTS foo (id unique, text)');
tx.executeSql('INSERT INTO foo (id, text) VALUES (1, "foobar")');
});
db.transaction(function (tx) {
tx.executeSql('DROP TABLE foo');
// known to fail - so should rollback the DROP statement
tx.executeSql('INSERT INTO foo (id, text) VALUES (1, "foobar")');
forge.logging.error("INSERT into non-existent table succeeded!");
}, function (err) {
forge.logging.info("error callback invoked, as expected");
});
db.transaction(function (tx) {
tx.executeSql('SELECT * FROM foo', [], function (tx, results) {
forge.logging.info("row: "+results);
});
});
Nowadays you should use something like LocalForage as this fallsback through indexedDB to webSQL to localStorage for you, plus gives you a consistent api. And if you are using Angular/Ionic then this is the business: Angular-LocalForage
From a tutorial code like this
function queryDB(tx) {
tx.executeSql('SELECT * FROM DEMO', [], querySuccess, errorCB);
}
function querySuccess(tx, results) {
}
function errorCB(err) {
alert("Error processing SQL: "+err.code);
}
var db = window.openDatabase("Database", "1.0", "PhoneGap Demo", 200000);
db.transaction(queryDB, errorCB);
in db.transaction i want to pass a variable as argument to queryDB function, so the code which i think of should looks like
db.transaction(queryDB(id), errorCB);
How I can actually implement this ? Or its simply gonna work like this and my id will be passed and get in tx ?
Wrap it in a function again
var id = 'THEID';
db.transaction(function(){
queryDB(id)
}, errorCB);
Note - This is assuming that you're making the API. Some APIs / frameworks insert the required information automatically. For example
//the db.transaction method
function transaction(param, callback) {
//do code stuff
callback(someInternalId); //callback is the function you pass as the first parameter
}
So, if you want to pass your own data in the callback, wrap it in a function. Otherwise, the code you are using may be doing this for you automatically.
I like to keep things very simple so I use a limited number of functions when handling storage on phonegap applications that can receive parameters. A lot of the examples I have seen have calls to many sub functions and for me, this is a nightmare when it comes to debugging.
I was caught out an a number of issues around Web SQL but reading the specs really, really helped clarify what I could and couldn't do. (http://www.w3.org/TR/webdatabase/)
Look at this simple code for an insert function:
function dbInsert(param1, param2, dbObj) {
val1 = param1;
val2 = param2;
val3 = String(dbObj.item2);
var sqlTxt = "INSERT INTO demo (geo1, geo2, geo3) VALUES (?, ?, ?)";
db.transaction(function(tx) {tx.executeSql(sqlTxt,[val1,val2,val3])}, errorCB, successCB);
}
Lets just to walk through it. Obviously a standard function which receives parameters which can be anything, in this case an object as well a strings.
sqlTxt is where the fun begins. Write this as you would normally write an insert statement, but where you would normally have the data to be inserted/selected etc in VALUES use the ? placeholder for each field in the database tables you want to pass data into.
Now lets break down the next line:
db.transaction(function(tx) {tx.executeSql(sqlTxt,[val1,val2,val3])}, errorCB, successCB);
When you create a new database, db is the handler to the database object so db.transaction asks to execute a transaction on the database db.
If we write next next section like this you can see it's function that calls tx.executeSql and because it in execute inside the db.transaction method, it will be passed the db handle.
function(tx) {
tx.executeSql(sqlTxt,[val1,val2,val3])
}
Now if we were to parse the sqlTxt it might look like this
INSERT INTO demo (geo1, geo2, geo3) VALUES ('a', 'b', 'c');
and because we are passing the three variable in place of the ? holder, it looks like the line above. And finally you call error and success callback functions.
In your case I would create a queryDB function like this:
function queryDB(id) {
var sqlTxt = "SELECT * FROM DEMO WHERE id=?"
db.transaction(function(tx) {tx.executeSql(sqlTxt,[id])}, errorCB, successCB);
}
In essence, the function grabs the parameter id, passes it into the query in the [id] and executes and returns error or success. Obviously you can extend this to use multiple parameters or if you want to be really clever, you just create a single database transaction function and pass in the sql and the parameters to use as an object or array (Example will be on my blog this weekend)
Ok first of all create a class hat will handle you're db instances (db updates etc) this class will hold a function that you will use for all you're query's
self.db = window.openDatabase( // and so on
then the function:
// execute a query and fetches the data as an array of objects
self.executeQuery = function(string, args, callback, callbackparams) {
var self = this;
//console.log('db execute: '+string);
self.db.transaction(function(tx) {
tx.executeSql(string, args, function(tx, result) {
var retval = [];
for (var i = 0; i < result.rows.length; ++i) {
retval.push(result.rows.item(i));
}
if (callback) {
callback(retval, result, callbackparams);
}
}, self.error);
});
}
then when u have initiated you're class (i named it myDb) go apeshit!
myDb.executeQuery('select l.* from location l inner join item_location il on (il.location_id = l.id and il.item_id = ?)', [item.id], function(locations, res, item){
item.locations = locations;
myDb.executeQuery('select * from media where item_id = ?', [item.id], function(media, res, item){
item.media = media;
// create item.
createItem(item);
}, item);
}, item);
as you can see the executeQuery has 4 params,
query,
params for query,
callback (with 3 params, result, status and myparam)
myparam (for callback)
It took me some time to fix this, but when you've done this! no more annoying db horror!
We can't send any paramenter for queryDB function like "queryDB(id)"
I solved this issue by this way.
var contactId = 33
dbInst.transaction(function(tx){
tx.executeSql('CREATE TABLE IF NOT EXISTS CONTACT_REFERENCE (id unique)');
var sqlStr = 'INSERT INTO CONTACT_REFERENCE (id) VALUES (?)'
tx.executeSql(sqlStr, [contactId]);
}, errorCB, successCB);
I think everyone comes close to answering your question. Really you need one slight modification to JohnP's answer. You should pass in the SQLTransaction Object that carries the executeSQL function. So to build on John's answer:
var id = 'THEID';
db.transaction(function(tx){
queryDB(tx, id)
}, errorCB);
Then where you define the function you can grab your id param with an extra variable.
queryDB: function (tx, id) { ...your code... }
This is a worked solution:
var sqltxt= 'INSERT INTO CONTACTS(id, data) VALUES (?, ?)';
var db = window.openDatabase("Database", "1.0", "Demo", 200000);
db.transaction(function(tx){tx.executeSql('DROP TABLE IF EXISTS CONTACTS');
tx.executeSql('CREATE TABLE IF NOT EXISTS CONTACTS(name unique, password)');
tx.executeSql(sqltxt,[name, pass]);
}, errorCB, successCB);
I have the following code snippet :
function getCheckListTaskWithId(id){
var tempTask = db.readTransaction(function (tx) {
tx.executeSql('SELECT * FROM checklisttasks where id=? ', [id], function (tx, results) {
var len = results.rows.length;
if(len>0){
var task=results.rows.item(0);
var temp= new CheckListTask(task.id,task.crud,task.name,task.status);
alert(temp);
}
});
});
}
the function that I pass to the tx.execute method is a call back function. Now I wan to return temp var present in callback function, from getCheckListTaskWithId function.
How Do I do this?
I am assuming that the executions of db.readTransaction and tx.executeSql are asynchronous. So you cannot return the result from them, as you don't know when they'll finish. The solution is use an asynchronous callback yourself. Make the getCheckListTaskWithId take a callback function as an argument and call it when result it available.
function getCheckListTaskWithId(id, callback) {
var tempTask = db.readTransaction(function (tx) {
tx.executeSql('SELECT * FROM checklisttasks where id=? ', [id], function (tx, results) {
var len = results.rows.length;
if(len > 0) {
var task=results.rows.item(0);
var temp= new CheckListTask(task.id,task.crud,task.name,task.status);
alert(temp);
callback(temp);
}
});
});
}
Rewrite tx.executeSql so it gets the return value of the callback and returns it.
This assumes that tx.executeSql doesn't perform any Ajax. Ajax is Asynchronous, so an HTTP request is made, execution continues as normal and another function is run when the request comes back. In this case it is far too late to return a value to the earlier function and anything that needs to be done with the data can only be done by the callback.