Web SQL UPDATE query not working - javascript

I am trying to update a table in an Phonegap Cordova App using Web SQL.
Following is the function that i have built for updating record but it is not updating the database nor giving any error.
function updatedrink(x, y, z) {
alert(x);
alert(y);
alert(z);
db = window.openDatabase("smartbar", "1.0", "Smart Bar", 10000);
db.transaction(function (tx) {
tx.executeSql("UPDATE drinks SET name=?, qty=? WHERE pos=?", [y, z, x], function(tx, result) {
alert('Updated');
}, function(error) {
alert(error);
});
});
}
All the alert statements are giving the correct values but table is not updated. No matter how much i try i cannot point out a single mistake. Please rescue.

Related

azure custom apis: performing database transaction returns a timeout

On a azure custom api, I'm attempting to perform bulk insert operation to three tables utilising database transctions.Then I'm facing this error on the console.
The request 'POST /api/saveinvite' has timed out. This could be caused by a script that fails to write to the response, or otherwise fails to return from an asynchronous call in a timely manner.
exports.post = function (request, response) {
console.log("save invite executed!!");
var jsonfriendcircle = request.body.jsonfriendcircle;
var jsoninviteelist = request.body.jsoninviteelist;
var jsoninviteefriendcirclelist = request.body.jsoninviteefriendcirclelist;
console.log("Circle is :" + jsonfriendcircle);
console.log("Inviteelist is :" + jsoninviteelist);
console.log("Inviteefriendcirclelist is :" + jsoninviteefriendcirclelist);
var parsedjsfrcircle = JSON.parse(jsonfriendcircle);
var mssql = request.service.mssql;
console.log("mssql obj :" + mssql);
mssql.open({
success: function (connection) {
console.log("connection to db success");
console.log("circle id: " + parsedjsfrcircle["id"]);
console.log("circle name :" + parsedjsfrcircle["circle_name"]);
var sqlst1 = 'insert into friendcircle (id,circle_name)values(?,?)';
connection.query(sqlst1, [parsedjsfrcircle["id"], parsedjsfrcircle["circle_name"]], function (err, results) {
if (err) {
console.log("Error:" + err);
connection.rollback();
response.send(statusCodes.Error, { message: '' });
connection.close();
return;
} else {
// connection.commit();
// connection.close();
}
});
}
, error: function (err) {
console.log("Unable to connect to DB :" + err);
response.send(statusCodes.Error, { message: err });
}
});
};
It doesn't look like your trying to do too much. Inserting a few hundred rows should come back before the timeout.
You'll get a timeout if there is permissions issues with the Mobile Services user on the database table and your transaction and custom error handling may be hiding that. Ensure you've run a
GRANT SELECT, INSERT, UPDATE ON OBJECT::[dbo].[Invitee_FriendCircle] TO [Created_MobileServicesLogin_User]
--For whatever name was created when you made the app (not the name you entered when you created the app, but the wacky one that mobile services made)
Some things to try:
Ensure the tables you are inserting to are indexed for the type of insert you're doing. If it's a huge table and indexing is an issue, let the mobile api insert to a small temp table and then run an asynch job with sp_start_job to update the main table with the temp table. That way you are not waiting while the table does the update.
Write stored procedures in the database that contain the inserts and pass the variables into them instead of writing the INSERT query here. Inside the sproc you can also do BULK INSERT if you really are passing a lot of values and need to do it quick.
Modify the ConnectionTimeout property in the connection string to your database.
You can modify the request.service.config.sqlConnectionString.
Try stripping it down to find the problem. Remove the transaction and just try doing it without the transaction and custom error handlers, on just one table at a time. Try
exports.post = function(request, response) {
var jsonfriendcircle=request.body.jsonfriendcircle;
var jsoninviteelist=request.body.jsoninviteelist;
var jsoninviteefriendcirclelist=request.body.jsoninviteefriendcirclelist;
var mssql=request.service.mssql;
var sqlst1='insert into FriendCircle (id,circle_name)values(?,?)' ;
mssql.query(sqlst1,[jsonfriendcircle.id,jsonfriendcircle.circle_name], {
success: function(results) {
response.send(statusCodes.OK, { message : 'success' });
},
error: function(err) {
console.log("error is: " + err);
}
});
};
Try them one at a time to see if anything fails, and if it does, check the LOGS on the Azure portal to see if it was a permission issue.
Good Luck!
Probably a transaction timeout after 30 seconds?
In SQL What is the default max transaction timeout
Try to rewrite the insert into multiple smaller transactions

SQLError 19 UNIQUE constraint failed

I am getting this error when setting up my app, creating a local database and simply inserting the first and only user (who has logged in locally). Please see comment in code for where I get the error message.
angular.module("greenApp")
.service("dbService",['$q', function($q){
var db;
var promise = function(){
var deferred = $q.defer();
db = window.openDatabase('greenDB', '1.0', 'Green Database', 2*1024*1024);
db.transaction(function(tx){
tx.executeSql("CREATE TABLE IF NOT EXISTS user (user TEXT PRIMARY KEY) ")
}, function(err){
alert('Something went wrong... Error: DATABASE INIT ' + err);
}, function(scc){
deferred.resolve();
})
return deferred.promise;
}
promise();
var query = function(sql, args) {
var deferred = $q.defer();
db.transaction(function(tx) {
tx.executeSql(sql, args, function(tx, results) {
deferred.resolve(results);
});
}, function(err) {
deferred.reject(err);
});
return deferred.promise;
};
var insert_into = function(args) {
var queryPromise = query("INSERT INTO user (user) VALUES (?)", args);
console.log("in insert_into", queryPromise) // Error message comes here
return queryPromise;
};
return {
promise: promise,
insert_into: insert_into,
};
}]);
Where args is simply ["user-name-string"], I get an error message that says:
"could not execute statement due to a constaint failure (19 UNIQUE
constraint failed: user.user)
Any ideas what could have happened? Exactly the same code was running and working in a recent pure cordova project which I just ported to Ionic.
It looks like you are inserting twice in your code ... here
var insert_into = function(args) {
var queryPromise = query("INSERT INTO user (user) VALUES (?)", args);
console.log("in insert_into", queryPromise) // Error message comes here
return query("INSERT INTO user (user) VALUES (?)", args); <-- you did a query above, now you do it again?!?
};
The sqlite db persists when you exit the app, so each time you start the app it will try to do the insert. (I gess it worked at first launch and you got the error the second time).
As you use CREATE TABLE IF NOT EXISTS the app does not fail on table creation but on the first insert.
You can use the pragma user_version to read/write version of your database and so know in wich case you have to create tables / insert values or if the db is already ready to go.

Issue with database entry in PhoneGap.

I am working on a camera app using the PhoneGap.
The thing I am trying to accomplish is, that when my app takes a picture and I store the picture in the app directory, I want to insert an entry in the database also with the name of the file, path and uploaded flag entry.
I am having trouble doing this. And I am unsure where the problem is occurring.
The code used to create database and the Table and then insert the entry is shown below. I call the "insertInTable" function after the file is already saved in the app directory.
function insertInTable(name, path)
{
var db = window.openDatabase('taukydb', '1.0', 'Tauky Database', 200000);
db.transaction(populateDB, errorCB, successCB);
//db.transaction(successCB, errorCB, );
//return();
}
function populateDB(tx) {
tx.executeSql('CREATE TABLE IF NOT EXISTS taukytb (name UNIQUE, path, uploaded)');
tx.executeSql('INSERT INTO taukytb (name, path, uploaded) VALUES (filename, filepath, 0)');
}
// Transaction success callback
function successCB() {
alert("Hurrey!!!");
//this is just for testing
var db = window.openDatabase("Database", "1.0", "Cordova Demo", 200000);
db.transaction(queryDB, errorCB);
}
function queryDB(tx) {
tx.executeSql('SELECT * FROM taukytb', [], querySuccess, errorCB);
}
function querySuccess(tx, results) {
var len = results.rows.length;
alert(len);
}
// Transaction error callback
function errorCB1(err) {
alert("Error 11111 processing SQL: "+err.code);
//console.log("Error processing SQL: "+err.code);
}
// Transaction error callback
function errorCB(err) {
alert("Error processing SQL: "+err.code);
//console.log("Error processing SQL: "+err.code);
}
When I run this code, the function "succesCB" never gets called, neither the errorCB is called.
Please have a look at this. I am new to mobile development and I have been stuck on this since sometime now.
Thanking in advance
I have made few changes to make it work.
tx.executeSql('INSERT INTO taukytb (name, path, uploaded) VALUES ("'+filename+'", "'+filepath+'", 0)');
This change will call the successCB as the query executes fine.
function successCB() {
alert("Hurrey!!!");
//this is just for testing
var db = window.openDatabase("Database", "1.0", "Cordova Demo", 200000);
db.transaction(queryDB, errorCB);
}
function queryDB(tx) {
tx.executeSql('SELECT * FROM taukytb', [], querySuccess, errorCB);
}
This method however will not work as you expect as you are creating second database providing the transaction of that but then querying for the table of first database.
Below is the full source example which creates two database with same table in both
https://gist.github.com/3058562
Don't know much about phonegap, but that create table statement seems to be lacking some types.
Also this line:
tx.executeSql('INSERT INTO taukytb (name, path, uploaded) VALUES (filename, filepath, 0)');
what is filename?

Tigger.io accessing device sqlite db

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

how can I pass argument in transaction callback function

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

Categories

Resources