synchronizing executeSql in Safari (WebKit) Web Sql database - javascript

WebKit (Safari 4+ is my focus) has a feature called Web SQL.
Web SQL is specified in the W3C draft.
Currently only the asynchronous flavor is supported.
I have a situation where I want to synchronize a few different operations - writing to database (using CREATE TABLE query and then a loop through INSERT queries) and then reading from the database. How do I do this? I googled and read a lot of tutorials, but did not find any explanation of that.
If I can't find answer to this, I shall try the Worker feature and if unsuccessful I plan to store the data in webstorage (localstorage) instead.

I have written a possible solution for this in my blog. Don't know if that would fit your problem, but have a look.
http://wander-mind.blogspot.com/2011/03/how-to-synchronize-html5-websql-with.html

Seems that nbody answers this. My current undertanding is that storing a block in localstorage is the best

You chain the operations through success callbacks. That way you can be sure of the order of operations. See the example code available in this article.
You can use the callbacks available for the transaction object or the individual queries, tx.executeSql(sql, [], callback, errorCallback).
var sql_createTables = "CREATE .....",
sql_inserts= "INSERT .....";
function errorHandler(tx, error) {
//do error handling
}
db.transaction(
function(tx){
tx.executeSql(sql_createTables,[], function(tx, result){
//The table was created
tx.executeSql(sql_inserts,[], function(tx, result){
// Inserts completed
});
},
errorHandler);
}, function(error) { alert("Oh, noes! The whole transaction failed!"); },
function() { alert("Yeah, baby! We did it."); });
WebWorker has nothing to do with this, and will not help you in any way, as a WebWorker has no access to the DOM, of which localStorage and WebSql are parts.

Related

Run Native SQL Command in Azure Scheduler

I have been trying to achieve this myself for 3 days now and combined with my knowledge and searching have come up blank! Just edited and change the question to be a bit more "generic" but lead me to a solution.
Using the azure mobile services scheduler, JavaScript, I want to increment a value for each record in a table. Basically run "turns++" on the table, up to a maximum of a certain amount.
Is there a way to run a native SQL command in the azure scheduler?
For Example: Connect to the database and run "SELECT * FROM tableName" as this will let me run the increment that I need.
Alternatively is there a way, which I'm assuming more complicated, to run "for each" on records from the table and then update them with a field incremented?
Thanks in advance!
You CAN do this in Azure Scheduler! It provides a special mssql object which is initialized with connection to the current Database associated with the Azure Mobile Service. And it is extremely easy to use:
function sql() {
mssql.query('select top 3 * from TestTable', {
success: function(results) {
console.log(results);
for (var testObj in results) {
console.log('id: ' + results[testObj].id + 'name : ' + results[testObj].fname);
}
},
error: function(err) {
console.log("error is: " + err);
}
});
}
(Note that here 'sql' is just the name of my Scheduler Job) The only trick is, that if you want to access tables that are not part of the Standard Mobile Services API tables, you will have to explicitly grant read/write access to those tables following this nice guide.
The Result of execution of the above script is this:
Looping through the records you can do much more than just dumping to the log - i.e. execute other queries, etc. You can read the full documentation of the mssql object here.
Advice from MSDN Evangelist is that you cant do this in Azure Scheduler as it has only 3 action verbs - HTTP, HTTPS and Queue.
https://twitter.com/plankytronixx/status/516899252749225985
The solution is to use a free azure website and their new feature "web jobs". I did this with PHP but web jobs supports more languages.
$options = array("Database" => "database name",
"UID" => "userid",
"PWD" => "password",
"MultipleActiveResultSets" => false);
$conn = sqlsrv_connect($hostname, $options)or die ("Cannot connect to host");
sqlsrv_query($conn, "UPDATE schema.tablename SET turns = turns+1 WHERE turns < 10;")or die (print_r(sqlsrv_errors()));
More about Azure web jobs here http://azure.microsoft.com/en-us/documentation/articles/web-sites-create-web-jobs/

node.js how to handle change of objects and variables in callbacks

I have just started a large project with node.js and I have stumbled upon some callback nightmare issues. I have done some node.js development before, but only small stuff based on tutorials.
I have a user model and a owner model, who is the owner for that user...basically the part I am building in node.js will be a REST service so I need to send a json containing a user and it's owner name. My problem is trying to get the owner name like I would do it in ruby or php and setting it as a property..but it doesn't work.
How do people handle this kind of logic in node.js where you need to change objects in callback functions? Also I do not want it to affect performance.
I am using mysql as the database because this was a requirement. So the code is this:
//find all
req.models.users.find({
'id' : req.query.id
}, function(err, users) {
if (err) console.log(err); //do something better here
else {
var json = [];
users.forEach(function(user) {
user.getOwner(function(err, owner) {
user.accountOwner = owner.name;
json.push(user;
});
});
res.type('application/json');
res.send(json);
}
});
I want to send something like this:
[{
'id': user.id,
'username": user.username,
'email': user.email,
'owner': user.owner.name'
},
{...}]
The problem is you are not understanding the control flow of node code. It doesn't go line by line top to bottom in chronological order. So your issue is your res.send(json) happens BEFORE (in time) your user.getOwner callback executes, so you send your empty json, then you stuff things into the json array after it's already been sent. You need to use something like async.each to do your joins, wait for all of the user`s owners to be populated, and then send the response. Or you could actually let the database join the data by writing a SQL join instead of doing N+1 queries against your database.

delete row from result set in web sql with javascript

I understand that the result set from web sql isn't quite an array, more of an object? I'm cycling through a result set and to speed things up I'd like to remove a row once it's been found. I've tried "delete" and "splice", the former does nothing and the latter throws an error. Here's a piece of what I'm trying to do, notice the delete on line 18:
function selectFromReverse(reverseRay,suggRay){
var reverseString = reverseRay.toString();
db.transaction(function (tx) {
tx.executeSql('SELECT votecount, comboid FROM counterCombos WHERE comboid IN ('+reverseString+') AND votecount>0', [], function(tx, results){
processSelectFromReverse(results,suggRay);
});
}, function(){onError});
}
function processSelectFromReverse(results,suggRay){
var i = suggRay.length;
while(i--){
var j = results.rows.length;
while(j--){
console.log('searching');
var found = 0;
if(suggRay[i].reverse == results.rows.item(j).comboid){
delete results.rows.item(j);
console.log('found');
found++;
break;
}
}
if(found == 0){
console.log('lost');
}
}
}
Actually you use DELETE sql command to delete the record from the database. For example:
tx.executeSql('DELETE FROM counterCombos WHERE comboid = ?', [comboid], success, error);
processSelectFromReverse could modified to include tx as input like
processSelectFromReverse(results,suggRay,tx)
Web SQL has been dropped from the HTML5 workup for almost 2 years now and isn't supported. Web Storage and Indexed DB have taken its place.
Your syntax for deleting objects: delete object; is correct. It's not used often in JavaScript but I have used it and that is the correct usage.
Using web-storage (more commonly called local storage) you would instansiate a localStorage object which comes with the method removeItem(item key), already built in.
You can see more at the above link on webstorage or go here for a tutorial.
If your concern is IOS or Android, making an application that is wrapped natively would allow you to create a javascript interface. From this interface you can access (for android) sqlite and create a nice, query0able solution. The downside is this would require people downloading your application rather then accessing a site.
http://caniuse.com/indexeddb
indexeddb support is growing rather slowly. With a proper coding style you could probably use local storage (as mentioned in the above comments) with pretty respectable speeds.

"Cannot call method 'open' of undefined" error when using indexedDB.open

I am new to IndexedDB and I am following this guide IndexedDB Tutorial I am simply trying to create a database and then be able to add a few entries. This is what I have so far.
var db = window.indexedDB.open('FriendDB', 'My Friends!');
if (db.version != '1') {
// User's first visit, initialize database (name, key, auto increment).
db.createObjectStore('Friends', 'id', true);
db.setVersion('1');
} else {
// DB already initialized.
}
var store = db.openObjectStore('Friends');
var user = store.put({name: 'Eric', gender: 'male', likes: 'html5'});
In my console I get the error "Cannot call method 'open' of undefined" how can I get this working? Also if there is a better resource online that would help me because I can't seem to find anything on the topic of IndexedDB for a newbie.
Here is the indexeddb demo from html5rocks which i have improved to work on Mozilla Firefox and added features for viewing details data and editing existing data. Inside you have explanations how to create db, insert, update and delete data in indexeddb.
https://github.com/denimf/IndexedDbToDo
Any time you see code containing a call to setVersion, it's using an outdated syntax. It was unfortunate that we had to make such a big change so late during the spec writing, but it made using IndexedDB correctly tremendously simpler so we decided it was worth it.
There is good documentation on developer.mozilla.org, even though it could definitely be improved.

How to delete a database in WebSQL programmatically?

I am new to Web SQL database and I use it to save data in a local database in a web page.
 I can create a database by
var db = openDatabase('database', '1.0', 'my database', 2 * 1024 * 1024);
 and I can create a table by doing this
db.transaction(function (tx) {
tx.executeSql('CREATE TABLE IF NOT EXISTS mytable (blah,blah)');
});
 I can delete the table by
db.transaction(function (tx) {
tx.executeSql('DROP TABLE mytable');
});
 but is there a way to delete the database programmatically?
Using PersistenceJS there is a persistence.reset API which will wipe the database clean.
PersistenceJS Site
For developing / testing purposes, you can view content and delete webSQL, IndexedDB, cookies, etc by searching for your domain name at this URL in Chrome:
chrome://settings/cookies
There, you can delete all the storage for a domain or just certain local storage entities. Yes, the URL implies just 'cookies', but the interface at this URL includes all types of offline storage.
It would be great I think if the Chrome developer tools interface had the ability to right-click and delete a data storage entity in the Resources tab along with inspecting the content. But for now, all I know of is the settings/cookies URL.
Spec says:
4.1 Databases
Each origin has an associated set of databases. Each database has a name and a current version. There is no way to enumerate or delete the databases available for an origin from this API.
I am developing a phonegap+jquery-mobile+KO app with offline storage using web sql via persistencejs, and jasmine js for BDD.
I'm working on some sort of "database cleaner" to be executed after each spec. When I was searching on how to drop a web sql database I read the reply https://stackoverflow.com/a/10929725/667598 (in this thread/question), and went to see what's in that directory (Mac OS X).
cd ~/Library/Application\ Support/Google/Chrome/Default/databases
Inside you will see a Databases.db SQLite3 database, and directories for each origin. These directories are named with the pattern protocol_host_somenumber (I don't know what that number is). So for example, in my case, since my apps are just files I open in Google Chrome with the file:/// … protocol, I can see a file__0 directory. And for twitter and I can also see a http_twitter.com_0 and a https_twitter.com_0.
Inside this directories all file names are just numbers. For example inside file__0 I found a file named 8 and another named 9. In my case, these files are websql database. I don't know if there also Indexed DB databases in chrome's Default/databases dir.
With this names it is a little hard to guess what database is what. You can open the database and you'll have to infer the app or site via its tables and data.
Luckily, the Databases.db I mentioned before is a mapping between those files named with numbers and the databases.
You can open the Databases.db and any other web sql file with the sqlite3 command
sqlite3 Databases.db
Obviously, once inside the sqlite3 shell, is handy to have some SQL knowledge. Anyway, it is also always handy some help, which is available via the command
.help
With the command .tables you can list tables in the database. Inside this Databases.db we can find the tables Databases and meta. The important one is Databases, so with a
select * from Databases;
we can see the mapping between the databases and their files. For example
7|http_jquerymobile.com_0|testdb|html5 test db|200000
8|file__0|elfaro_dev|Base de datos de ElFaro para desarrollo|734003200
The first column is the id of the table which is the number used for db file names, the second is the origin (the directory) the other columns are the db name, the db description and the estimated size used when creating the db from the Javascript API.
So to actually delete a database what I did was to delete it from this table, for example:
delete from Databases where id = 8
And then delete the actual file from the filesystem (outside sqlite3 shell)
rm file__0/8
And that's it.
PS: I know this is a too long answer for a simple subject but I just needed to flush this from my system and back it up somewhere like SO or a blog.
The developer options
There is no way to enumerate or delete the databases programmatically (yet).
Chrome developers can navigate to chrome://settings/cookies search and delete any database
Opera developers can navigate to opera://settings/cookies
The only way to truly delete a database (and everything else)
A new Spec says this might be possible in the feature with both response header and javascript.
The disadvantages is that you can't control what is being deleted, So you would need to create a backup first of everything else unless you want to clear everything
2.1.3. The storage parameter
The storage parameter indicates that the server wishes to remove locally stored data associated with the origin of a particular response’s url. This includes storage mechansims such as (localStorage, sessionStorage, [INDEXEDDB], [WEBDATABASE], etc), as well as tangentially related mechainsm such as service worker registrations.
Js:
navigator.storage.clear({
types: [ "storage" ],
includeSubdomains: true // false by default
});
Response header:
res.header("Clear-Site-Data", "storage; includeSubdomains");
But this is not avalible to any browser yet...
Best solution for clients (not the developers)
/* This will fetch all tables from sqlite_master
* except some few we can't delete.
* It will then drop (delete) all tables.
* as a final touch, it is going to change the database
* version to "", which is the same thing you would get if
* you would check if it the database were just created
*
* #param name [string] - the database to delete
* #param cb [function] - the callback when it's done
*/
function dropDatabase(name, cb){
// empty string means: I do not care what version, desc, size the db is
var db = openDatabase(name, "", "", "");
function error(tx, err){
console.log(err);
}
db.transaction(ts => {
// query all tabels from sqlite_master that we have created and can modify
var query = "SELECT * FROM sqlite_master WHERE name NOT LIKE 'sqlite\\_%' escape '\\' AND name NOT LIKE '\\_%' escape '\\'";
var args = [];
var success = (tx, result) => {
var rows, i, n, name;
rows = result.rows;
n = i = rows.length;
// invokes cb once it’s called n times
function after(){
if (--n < 0) {
// Change the database version back to empty string
// (same as when we compear new database creations)
db.changeVersion(db.version, "", function(){}, error, cb);
}
}
while(i--){
// drop all tabels and calls after() each time
name = JSON.stringify(rows.item(i).name);
tx.executeSql('DROP TABLE ' + name, [], after, error);
}
// call it just 1 more extra time incase we didn't get any tabels
after();
};
ts.executeSql(query, args, success, error);
});
}
Usage
dropDatabase("database", function(){
console.log("done")
});
The localdatabase files are stored in your Windows user settings under Application Data > Google > Chrome > User Data > Default > databases.
So manually deleting them is theoretically possible. This is only useful while testing / developing on your own computer, since when another user opens your app/site, it is unlikely to have file system access.
However, even though you can find the files and delete them, the data sticks around. I've tried it with Chrome both open and closed and all chrome processes ended, and yet the browser inspector keeps showing me my old database with all the unwanted fields and data in it.
This is answered in HTML5 database storage (SQL lite) - few questions.
To summarize:
Currently no way to drop a WebSQL database.
Probably use Indexed DB or localStorage instead.
In my library implementation, I just delete all tables. Which, indeed, delete the database. List of tables are select * from sqlite_master.
Please note that if you use multiple
tx.executeSql('DROP TABLE mytable');
statements in the same transaction callback then make sure that they all exist or consider using DROP TABLE IF EXISTS syntax instead. If even one table doesn't exist when you try to drop it will result in the entire transaction failing. This failure results in a rollback of the transaction and means that the data will stay in your database even when you thought that it should have been deleted. There is no error reported unless you're specifically listening for it in the executeSql's 4th argument which is an error callback. This is intended behavior but is, in my experience, confusing.
No method to delete the existing database in websql it will clear when the cache is cleared or
The browser is closed. If you want to create a database with the same name Just use openDatabase Method It will first check for the existence of the database with the same name. If not exists it will create one otherwise it will open the existing one
please follow this link http://html5doctor.com/introducing-web-sql-databases/

Categories