how can I pass argument in transaction callback function - javascript

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);

Related

Javascript function doesn't return query result

I am trying to figure out why one of my queries won't return the value from a query...my code looks like this:
var client = new pg.Client(conString);
client.connect();
var query = client.query("SELECT count(*) as count FROM sat_scores")
// Don't use demo key in production. Get a key from https://api.nasa.gov/index.html#apply-for-an-api-key
function getNEO(callback) {
var data = '';
query.on('rows', function(rows) {
console.log("Row count is: %s", rows[0].count)
data += rows[0].count;
});
query.on('end', function() {
callback(data);
});
}
with that, getNEO returns a blank...but if I set var data = '4', then getNEO returns 4....the query should return 128 but it just returns a blank...
First of all, getNEO() doesn't return anything - I'm operating on the assumption that you call getNEO() exactly once for your query, and pass in a callback to handle the data, and that callback is what's not getting the appropriate data?
My typical recommendation for troubleshooting things like this is to simplify your code, and try and get really close to any example code given (for instance):
var client = new pg.Client(conString);
// define your callback here, in theory
client.connect(function (err) {
if (err) throw err;
var query = client.query("SELECT count(*) as count FROM sat_scores"),
function(err, result) {
if (err) throw err;
console.log(result.rows.length);
}
);
});
... I'm doing a couple things here you'll want to note:
It looks like the client.connect() method is asynchronous - you can't just connect and then go run your query, you have to wait until the connection is completed, hence the callback. Looking through the code, it looks like it may emit a connect event when it's ready to send queries, so you don't have to use a callback on the connect() method directly.
I don't see a data event in the documentation for the query object nor do I see one in the code. You could use the row event, or you could use a callback directly on the query as in the example on the main page - that's what I've done here in the interest of simplicity.
I don't see the count property you're using, and row[0] is only going to be the first result - I think you want the length property on the whole rows array if you're looking for the number of rows returned.
I don't know if you have a good reason to use the getNEO() function as opposed to putting the code directly in procedurally, but I think you can get a closer approximation of what you're after like this:
var client = new pg.Client(conString);
// define your callback here, in theory
client.connect();
function getNEO(callback) {
client.on('connect', function () {
var query = client.query("SELECT count(*) as count FROM sat_scores"));
query.on('end', function(result) {
callback(result.rowCount);
});
});
}
... so, you can call your getNEO() function whenever you like, it'll appropriately wait for the connection to be completed, and then you can skip tracking each row as it comes; the end event receives the result object which will give you all the rows and the row count to do with what you wish.
so here is how I was able to resolve the issue....I moved the var query inside of the function
function getNEO(state, callback) {
var conString = "postgres://alexa:al#alexadb2.cgh3p2.us-east-1.redshift.amazonaws.com:5439/alexa";
var client = new pg.Client(conString);
client.connect();
var data = '';
var query = client.query("SELECT avg(Math) as math, avg(Reading) as reading FROM sat_scores WHERE State = '" + state + "'");
console.log("query is: %s", query);
query.on('row', function(row) {
console.log("Row cnt is: %s", row.math);
console.log("row is: " + row)
data += row;
});
console.log("made it");
query.on('end', function() {
callback(data);
});
}

MongoDB + node.js - SQL Select equivalent

I'm pretty new to node.js and mongodb. I need a function, that will return an array with results from database. When I query 'SELECT * FROM table' in php, it returns array or array of objects. But with node and mongo I have to use lot of code, which seems so unnecessary to me. So I wrote this function:
select: function (table, terms) {
var rows = [];
var find = function (error, db) {
var collection = db.collection(table);
var docs = collection.find(terms);
docs.each(function (error, doc) {
rows.push(doc);
});
};
client.connect(url, find);
return rows;
}
It takes table name [string] and terms [js object] as arguments. And I want to this function return an array like this: [ { doc1 }, { doc2 }, { doc3 }, ...].
When I log variable doc, in each function, it's alright - valid javascript object. But when I log variable rows after pushing all docs, it's empty - []. Also the result of function select() is empty array - [].
Please, is there someone who has an idea about what could be a problem or who uses some similar method to fetch data from MongoDB? Thank you
The connect function is asynchronous, and finishes after your return statement. Put your return statement within the callback function, just after the closing bracket of docs.each(.....); This way you're sure your return statement will be executed after your array has been filled.
Edit for completeness: a return statement doesn't work of course, because it returns from the function in find. Work with a callback function.
Like this:
select: function (table, terms, cb) {
var rows = [];
var find = function (error, db) {
var collection = db.collection(table);
var docs = collection.find(terms);
docs.each(function (error, doc) {
rows.push(doc);
});
cb(error, rows);
};
client.connect(url, find);
}
Edit: Above example (cb function instead of return)

Javascript WebSQL use one transaction object all the time

Hello I have factory which gives functions to work with database, it looks like this:
.factory('DBwork', function () {
var db = openDatabase("...");
db.transaction(function(tx){
tx.executeSql("CREATE TABLE...");
});
var factoryfunctions = {
insert: function() {
db.transaction(function(tx){
tx.executeSql("INSERT INTO...");});
},
select: function() {
db.transaction(function(tx){
tx.executeSql("SELECT FROM...");});
}
};
return factoryfunctions;
});
I need to use one transaction object all the time, or not use transactions at all, is that possible?
Simply, to make it like this.
var db = openDatabase("...");
tx = db.transaction();
var factoryfunctions = {
insert: function() {
tx.executeSql("INSERT INTO...");
},
select: function() {
tx.executeSql("SELECT FROM...");
}
};
return factoryfunctions;
Im new to javascript so thanks for any help
It doesn't make sense to cache transaction object for later use. It is unusable after transaction callback has completed. In specification's terms it's marked stale, so that any other call to its executeSql() throws an exception.
There are only three methods available on the database object, transaction(), readTransaction() and changeVersion(). There isn't a way to avoid transaction objects.
What you can do however, is call executeSql() multiple times in one transaction callback.
See this example, http://html5demos.com/database-rollback.

Node JS How to get the query data outside

I am new from Node js , just i am trying implementing this functionality last few days but i am unable to fix
exports.get_exercises_for_trainer = function(req, res)
{
connection.query('SELECT * FROM ag_exercise', function(err, exercise)
{
console.log('------------------------------before add fields ----------------------------------');
console.log(exercise);
for (var i in exercise)
{
fields(exercise[i].wt_id, function(result1) {
exercise[i].wt_fields = result1; //here i am adding result set of other query but i am not geting this fields data
console.log(result1) //but i printed here working fine but i need this result1 data out side query
});
}
console.log('------------------------------after add fields ----------------------------------');
console.log(exercise);
res.render('pages/trainer_home.ejs',{page_title:"Exercise Create",exercise:exercise});
});
}
function fields(wt_id,callback)
{
connection.query('SELECT * FROM ag_workout_type_fields WHERE wt_id = "'+wt_id+'"', function( err1, result1){
callback(result1);
});
}
I have one more query ? in node js : If table having users , users having different relation tables like orders , profiles , address
How to implement this
First i am getting users
User loop
getting every user profiles ,address,orders
end user loop
but above scenario i am unable to implement in node js but in php very simple like this
$get_users = ... //users data
foreach($getusers as $usr)
{
$usr->orders = //orders data
.... like etc
}
There are three main questions here, I will adress each seperately.
Question 1: When making an async function, how do I then access my data outside that function?
All data from async calls are accessed via callback, event listeners or promises (a fancy callback and event listener handler). For the most part, you are going to just be using callbacks. So, instead of :
get_user = function(user_id){
//Do some stuff to get the user
return the_user;
};
var user = get_user('1234');
//do whatever you want with user
You will see :
get_user = function(user_id,callback){
//Do some stuff to get the user
callback(null,the_user);
}
get_user('1234',function(err,user){
//do whatever you want with user
});
When we get to Question 3, you will see the more complicated use case you were speaking of.
Question 2: How do I loop through my data, perform a subsiquent query on each row, and append that data to my current data?
There are a couple of issues here.
Every time you query the database, you are performing an asynchronous function, so you need to manage all of those callbacks accordingly. Fortunately there are some great tools to do that for you, and we will be using async.
Every time you call an asynchronous function in a for loop, the for loop continues, thus your iterator is overwritten, but your asynchronous function is not done with it yet, so you will get all sorts of unexpected results like vanishing variables, or missmapped results. You can handle this with JavaScript closures, or, you can rely again on libraries like async which handle it all for you.
Instead of running a for loop over your queries results, we're going to pass it to async.forEachOf, which we will use to modify the existing array and append the results of the subsequent queries to the primary query's rows. It is important to note that forEachOf will run the subsequent queries in parallel, so you should not be using a single database connection, but a pool. If you MUST use a single database connection, use forEachOfSeries instead.
async = require('async');
exports.get_exercises_for_trainer = function(req, res){
connection.query('SELECT * FROM ag_exercise', function(err, exercises)
{
console.log('------------------------------before add fields ----------------------------------');
console.log(exercises);
async.forEachOf(exercises,function(exercise,index,callback){
connection.query('SELECT * FROM ag_workout_type_fields WHERE wt_id = "' + exercise.wt_id + '"', function( err, result1){
if(err)return callback(err1);
exercises[index].wt_fields = result1; //Modify original array
return callback();
});
},function(err){
if(err){return;} //do some error handling
console.log('------------------------------after add fields ----------------------------------');
console.log(exercises);
res.render('pages/trainer_home.ejs',{page_title:"Exercise Create",exercise:exercises});
});
});
};
Question 3: How do I perform many related but different queries so that I can populate information about my object?
This is another great usage of the async library. In this case since the queries are all different, we'll use parallel instead of forEachOf.
async = require('async');
populate_user = function(user,_callback){
async.paralell({
profile: function(callback){
var sql = "SELECT * FROM profiles WHERE user_id = " + user.id + " LIMIT 1 ";
var connection.query(sql,function(err,rows,fields){
if(err)return callback(err);
if(rows.length === 1)return callback(null,rows[0]);
return callback(null,[]);
});
},
address: function(callback){
var sql = "SELECT * FROM addresses WHERE user_id = " + user.id + " LIMIT 1 ";
var connection.query(sql,function(err,rows,fields){
if(err)return callback(err);
if(rows.length === 1)return callback(null,rows[0]);
return callback(null,[]);
});
},
orders: function(callback){
var sql = "SELECT * FROM orders WHERE user_id = " + user.id;
var connection.query(sql,function(err,rows,fields){
if(err)return callback(err);
if(rows.length > 0)return callback(null,rows); //notice how this one could have multiple results so we're returning them all
return callback(null,[]);
});
},
},
function(err,result){
if(err)return _callback(err);
for(var att in result){user[att] = result[att];}
callback(null,user);
}
}
user = {id:1234};
populate_user(user,function(err,populated_user)){
console.log(user); //wow notice how it's populated too!
console.log(populated_user); //this is really just a new handle for the same object
});
I want to note that NONE of this was tested, not even for syntax, so it may take a little reworking.

how to pass arguments to PhoneGap database transaction function

I have a working PhoneGap database transaction where I am able to run a sql query and process the results. However, in an effort to make it reusable, I need to be abe to pass arguments to the querying function. There should a better way than declaring global variables and accessing them/resetting in the query function. Appreciate any help in converting this:
//update images function
function updateGalleryCovers() {
var db = window.openDatabase("test db", "1.0", "Cordova DB", 200000);
db.transaction(queryDB_u_g, errorCB);
}
//Query the database
function queryDB_u_g(tx) {
var query = 'SELECT cover_img, objectId FROM USER_GALLERY WHERE userId="'+getUserId()+'"';
tx.executeSql(query, [], querySuccess_u_g, errorCB);
}
//Query success callback
function querySuccess_u_g(tx, results) {
var len = results.rows.length;
for (var i=0; i<len; i++){
// process results
}
}
to something like this:
//update images function
function updateGalleryCovers(userid) {
var db = window.openDatabase("test db", "1.0", "Cordova DB", 200000);
db.transaction(queryDB_u_g, userid, errorCB);
}
//Query the database
function queryDB_u_g(tx, userid) {
var query = 'SELECT cover_img, objectId FROM USER_GALLERY WHERE userId="'+userid+'"';
tx.executeSql(query, [], querySuccess_u_g, errorCB);
}
//Query success callback
function querySuccess_u_g(tx, results) {
var len = results.rows.length;
for (var i=0; i<len; i++){
// process results
}
}
Thanks!
The transaction functions are offered by sqlite and not phonegap. Its true that you can't pass extra variables to the functions because of the method signature sqlite accepts.
But here's a work around for the same:
db_conn.transaction( function(tx){ your_function(tx, parameter1, parameter2) }, ErrorCallBack );
Here you are passing a dummy function to the transaction success callback and taking the transaction object along with it.
Hope that helps

Categories

Resources